Skip to content

Commit

Permalink
Feat/task block view for issues (#1949)
Browse files Browse the repository at this point in the history
* feat:add  task block card

* feat: add radial bar

* feat: add task block card times

* feat: add radial progress

* feat: add block issues filter UI

* feat: add filter features on issues  block view

* fix: task filter missing

* fix: issues views var

* fix: svg synthax error

* fix: issue card view style

* fix: issue card view style

* fix:delete  comments
  • Loading branch information
Cedric921 authored Dec 4, 2023
1 parent fa86abe commit 7bea142
Show file tree
Hide file tree
Showing 22 changed files with 1,073 additions and 33 deletions.
6 changes: 6 additions & 0 deletions apps/web/app/stores/task-filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { atom } from 'recoil';

export const taskBlockFilterState = atom<'all' | 'running' | 'online' | 'pause' | 'idle' | 'suspended'>({
key: 'taskBlockFilterState',
default: 'all'
});
52 changes: 52 additions & 0 deletions apps/web/lib/components/radial-progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export default function RadialProgress({
radius = 24,
cx = 24,
cy = 24,
percentage = 55
}: {
radius?: number;
cx?: number;
cy?: number;
percentage: number;
}) {
const circumference = radius * 2 * Math.PI;

return (
<>
<div
x-data="{ scrollProgress: 0 }"
className="relative -rotate-90 inline-flex items-center justify-center overflow-hidden rounded-full"
>
<svg className="w-12 h-12">
<circle
className="text-gray-300"
strokeWidth="8"
stroke="currentColor"
fill="transparent"
r={radius}
cx={cx}
cy={cy}
/>
<circle
className="text-[#27AE60]"
strokeWidth="8"
strokeDasharray={circumference}
strokeDashoffset={`calc(${circumference} - ${(percentage / 100) * circumference})`}
strokeLinecap="round"
stroke="currentColor"
fill="transparent"
r={radius}
cx={cx}
cy={cy}
/>
</svg>
<span
className="absolute text-xs font-normal text-black dark:text-white rotate-90"
x-text={`${percentage}%`}
>
{percentage}%
</span>
</div>
</>
);
}
8 changes: 8 additions & 0 deletions apps/web/lib/components/separator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ import { clsxm } from '@app/utils';
export const VerticalSeparator = ({ className }: IClassName) => {
return <div className={clsxm('w-1 self-stretch border-l-[0.125rem] dark:border-l-[#FFFFFF14]', className)} />;
};

export const HorizontalSeparator = ({ className }: IClassName) => {
return (
<div className="px-4 w-full">
<div className={clsxm('h-1 w-full border-t-[0.125rem] dark:border-l-[#FFFFFF14]', className)} />
</div>
);
};
50 changes: 45 additions & 5 deletions apps/web/lib/components/svgs/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,46 @@ export function StopCircleIcon({ className }: IClassName) {
);
}

export function NotWorkingIcon({ className }: IClassName) {
return (
<svg
aria-hidden="true"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className={clsxm('stroke-[#282048]', className)}
>
<path
d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
);
}

export function OnlineIcon({ className }: IClassName) {
return (
<svg
aria-hidden="true"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className={clsxm('stroke-[#282048]', className)}
>
<path
d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
);
}

// ============================= Settings 4 Icon ============================= //

export function Settings4Icon({ className }: IClassName) {
Expand Down Expand Up @@ -2221,13 +2261,13 @@ export function QuoteBlockIcon({ className }: IClassName) {
);
}

export function AddIcon({
export function AddIcon({
className,
width=14,
height=14
width = 14,
height = 14
}: IClassName<{
width?: number,
height?: number,
width?: number;
height?: number;
}>) {
return (
<svg
Expand Down
2 changes: 2 additions & 0 deletions apps/web/lib/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export * from './task/task-labels';
export * from './task/task-displays';

export * from './team/user-team-card';
export * from './team/user-team-block';
export * from './team/user-team-block/user-team-block-header';
export * from './team-members';
export * from './team/create-team-modal';
export * from './team/teams-dropdown';
Expand Down
12 changes: 10 additions & 2 deletions apps/web/lib/features/task/task-all-status-type.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ import {
useTaskStatusValue
} from './task-status';

export function TaskAllStatusTypes({ task, showStatus = false }: { task?: Nullable<ITeamTask>; showStatus?: boolean }) {
export function TaskAllStatusTypes({
task,
showStatus = false,
toBlockCard = false
}: {
task?: Nullable<ITeamTask>;
showStatus?: boolean;
toBlockCard?: boolean;
}) {
const taskPriorities = useTaskPrioritiesValue();
const taskSizes = useTaskSizesValue();
const taskLabels = useTaskLabelsValue();
Expand Down Expand Up @@ -64,7 +72,7 @@ export function TaskAllStatusTypes({ task, showStatus = false }: { task?: Nullab
/>
)}

{task?.size && (
{task?.size && !toBlockCard && (
<TaskStatus
{...taskSizes[task?.size || 'Medium']}
className="rounded-[0.625rem]"
Expand Down
8 changes: 5 additions & 3 deletions apps/web/lib/features/task/task-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,16 @@ function TaskStatusFilter({ hook }: { hook: I_TaskFilter }) {
);
}

function TaskNameFilter({
export function TaskNameFilter({
value,
setValue,
close
close,
fullWidth = false
}: {
value: string;
setValue: (v: string) => void;
close: () => void;
fullWidth?: boolean;
}) {
const { t } = useTranslation();

Expand All @@ -426,7 +428,7 @@ function TaskNameFilter({
};

return (
<div className="flex flex-row w-1/2 gap-2 mt-3 ml-auto">
<div className={clsxm('flex flex-row w-1/2 gap-2 mt-3 ml-auto', fullWidth && '!w-full')}>
<InputField
value={tempValue}
autoFocus={true}
Expand Down
13 changes: 10 additions & 3 deletions apps/web/lib/features/task/task-progress-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@ import { ITeamTask, Nullable } from '@app/interfaces';
import { timerSecondsState } from '@app/stores';
import { ProgressBar } from 'lib/components';
import { useRecoilValue } from 'recoil';
import RadialProgress from 'lib/components/radial-progress';

export function TaskProgressBar({
isAuthUser,
task,
activeAuthTask,
showPercents
showPercents,
radial
}: // memberInfo,
{
isAuthUser: boolean | undefined;
task: Nullable<ITeamTask>;
activeAuthTask: boolean;
showPercents?: boolean;
memberInfo?: I_TeamMemberCardHook;
radial?: boolean;
}) {
const seconds = useRecoilValue(timerSecondsState);
const { getEstimation /*, addSeconds*/ } = useTaskStatistics(isAuthUser && activeAuthTask ? seconds : 0);
Expand All @@ -36,9 +39,13 @@ export function TaskProgressBar({
const progress = getEstimation(
null,
task,
/*addSeconds || */ totalWorkedTasksTimer || 0,
/*addSeconds || */ totalWorkedTasksTimer || 1,
task?.estimate || 0 //<-- task?.estimate || currentMember?.lastWorkedTask?.estimate || 0 - removed as when certain task's timer was active it was affecting the timers with no estimations. Was taking user's previous task's estimation
);

return <ProgressBar width="100%" progress={`${progress || 0}%`} showPercents={showPercents} />;
return radial ? (
<RadialProgress percentage={progress} />
) : (
<ProgressBar width="100%" progress={`${progress || 0}%`} showPercents={showPercents} />
);
}
49 changes: 47 additions & 2 deletions apps/web/lib/features/task/task-times.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ type Props = {
memberInfo?: I_TeamMemberCardHook | OT_Member | any;
showDaily?: boolean;
showTotal?: boolean;
isBlock?: boolean;
} & IClassName;

export function TaskTimes({ className, task, memberInfo, showDaily = true, showTotal = true }: Props) {
export function TaskTimes({ className, task, memberInfo, showDaily = true, showTotal = true, isBlock = false }: Props) {
// For public page
const { activeTeam } = useOrganizationTeams();
const currentMember = activeTeam?.members.find((member) => member.id === memberInfo?.member?.id || memberInfo?.id);
Expand All @@ -38,7 +39,11 @@ export function TaskTimes({ className, task, memberInfo, showDaily = true, showT

return (
<div className={clsxm(className)}>
<TimeInfo showDaily={showDaily} showTotal={showTotal} daily={{ h: dh, m: dm }} total={{ h, m }} />
{isBlock ? (
<TimeBlockInfo showDaily={showDaily} showTotal={showTotal} daily={{ h: dh, m: dm }} total={{ h, m }} />
) : (
<TimeInfo showDaily={showDaily} showTotal={showTotal} daily={{ h: dh, m: dm }} total={{ h, m }} />
)}
</div>
);
}
Expand Down Expand Up @@ -83,6 +88,46 @@ function TimeInfo({
);
}

function TimeBlockInfo({
daily,
total,
showDaily = true,
showTotal = true
}: {
daily: { h: number; m: number };
total: { h: number; m: number };
showDaily?: boolean;
showTotal?: boolean;
}) {
const { t } = useTranslation();
return (
<div className="flex gap-3">
{showDaily && (
<div className=" text-base font-normal flex flex-col items-center ">
<span className="text-[#7B8089]">{t('common.TODAY')}:</span>
<Text className="text-lg font-semibold">
{daily.h}h : {daily.m}m
</Text>
</div>
)}

{showTotal && (
<div
className={clsxm(
'font-normal text-base flex flex-col items-center '
// showDaily && ['text-sm']
)}
>
<span className="text-[#7B8089]">{t('common.TOTAL')}:</span>
<Text className="text-lg font-semibold">
{total.h}h : {total.m}m
</Text>
</div>
)}
</div>
);
}

export function TodayWorkedTime({ className, memberInfo }: Omit<Props, 'task' | 'activeAuthTask'>) {
// Get current timer seconds
const { activeTeam } = useOrganizationTeams();
Expand Down
52 changes: 52 additions & 0 deletions apps/web/lib/features/team-members-block-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import { OT_Member } from '@app/interfaces';
import { Transition } from '@headlessui/react';
import { UserTeamBlock } from './team/user-team-block';

interface Props {
teamMembers: OT_Member[];
publicTeam: boolean;
currentUser: OT_Member | undefined;
teamsFetching: boolean;
}

const TeamMembersBlockView: React.FC<Props> = ({ teamMembers: members, publicTeam = false, currentUser }) => {
return (
<div className="mt-7">
{/* Current authenticated user members */}
<Transition
show={!!currentUser}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
{/* <UserTeamBlock member={currentUser} publicTeam={publicTeam} /> */}
</Transition>
<div className="flex w-full items-center">
{members.map((member) => {
return (
<div className="p-1 w-full md:w-1/2 lg:w-1/4" key={member.id}>
<Transition
key={member.id}
show={true}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<UserTeamBlock member={member} publicTeam={publicTeam} />
</Transition>
</div>
);
})}
</div>
</div>
);
};

export default TeamMembersBlockView;
Loading

0 comments on commit 7bea142

Please sign in to comment.