Skip to content

Commit

Permalink
[Feat]: Timesheet-Duration-Display (#3352)
Browse files Browse the repository at this point in the history
* feat: add DisplayTimeForTimesheet and TotalTimeDisplay components for formatted timesheet duration

* fix: coderabbitai

* feat: total duration by date

* fix: conflit and display date time

* fix: deepscan
  • Loading branch information
Innocent-Akim authored Nov 21, 2024
1 parent 63381f1 commit e8d0801
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 13 deletions.
2 changes: 1 addition & 1 deletion apps/web/app/hooks/features/useTimelogFilterOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ export function useTimelogFilterOptions() {
setStatusState,
handleSelectRowTimesheet,
selectTimesheet,
setSelectTimesheet
setSelectTimesheet,
};
}
23 changes: 12 additions & 11 deletions apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ import {
import { useTranslations } from 'next-intl';
import { formatDate } from '@/app/helpers';
import { GroupedTimesheet, useTimesheet } from '@/app/hooks/features/useTimesheet';
import { TaskNameInfoDisplay } from '../../task/task-displays';
import { DisplayTimeForTimesheet, TaskNameInfoDisplay, TotalDurationByDate, TotalTimeDisplay } from '../../task/task-displays';
import { TimesheetStatus } from '@/app/interfaces';
import dayjs from 'dayjs';

export const columns: ColumnDef<TimeSheet>[] = [
{
Expand Down Expand Up @@ -249,10 +248,11 @@ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) {
'h-[48px] flex justify-between items-center w-full',
'bg-[#ffffffcc] dark:bg-dark--theme rounded-md border-1',
'border-gray-400 px-5 text-[#71717A] font-medium'
)}
>
)}>
<span>{formatDate(plan.date)}</span>
<span>64:30h</span>
<TotalDurationByDate
timesheetLog={plan.tasks}
createdAt={formatDate(plan.date)} />
</div>

<Accordion type="single" collapsible>
Expand Down Expand Up @@ -283,8 +283,8 @@ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) {
variant={'outline'}
className="flex items-center gap-x-2 h-[25px] rounded-md bg-[#E4E4E7] dark:bg-gray-800"
>
<span className="text-[#5f5f61]">Total</span>
<span className="text-[#868688]">24:30h</span>
<span className="text-[#5f5f61]">{t('timer.TOTAL_HOURS')}</span>
<TotalTimeDisplay timesheetLog={rows} />
</Badge>
</div>
<div className={clsxm('flex items-center gap-2 p-x-1 capitalize')}>
Expand Down Expand Up @@ -339,10 +339,11 @@ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) {
{task.timesheet.status}
</Badge>
</div>
<span className="flex-1 font-medium">
{dayjs(task.timesheet.createdAt).format('HH:mm:ss')}
</span>
<TaskActionMenu idTasks={task.id} />
<DisplayTimeForTimesheet
duration={task.timesheet.duration}
/>
<TaskActionMenu
idTasks={task.id} />
</div>
))}
</AccordionContent>
Expand Down
60 changes: 59 additions & 1 deletion apps/web/lib/features/task/task-displays.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ITeamTask, Nullable } from '@app/interfaces';
import { ITeamTask, Nullable, TimesheetLog } from '@app/interfaces';
import { clsxm } from '@app/utils';
import { Tooltip } from 'lib/components';
import { TaskIssueStatus } from './task-issue';
import { formatDate, secondsToTime } from '@/app/helpers';
import { ClockIcon } from "@radix-ui/react-icons"
import React from 'react';

type Props = {
task: Nullable<ITeamTask>;
Expand Down Expand Up @@ -61,3 +64,58 @@ export function TaskNameInfoDisplay({
</Tooltip>
);
}

const formatTime = (hours: number, minutes: number) => (
<div className="flex items-center">
<span>{String(hours).padStart(2, '0')}</span>
<span>:</span>
<span>{String(minutes).padStart(2, '0')}</span>
</div>
);

export const DisplayTimeForTimesheet = ({ duration }: { duration: number }) => {
if (duration < 0) {
console.warn('Negative duration provided to DisplayTimeForTimesheet');
duration = 0;
}
const { h: hours, m: minute } = secondsToTime(duration || 0);
return (
<div className='flex items-center font-medium gap-x-1'>
<ClockIcon className='text-green-400 text-[14px] h-4 w-4' />
<div className='flex items-center'>
{formatTime(hours, minute)}
</div>
</div>
)

}

export const TotalTimeDisplay = React.memo(({ timesheetLog }: { timesheetLog: TimesheetLog[] }) => {
const totalDuration = Array.isArray(timesheetLog)
? timesheetLog.reduce((acc, curr) => acc + (curr.timesheet?.duration || 0), 0)
: 0;
const { h: hours, m: minute } = secondsToTime(totalDuration || 0);
return (
<div className="flex items-center text-[#868688]">
{formatTime(hours, minute)}
</div>)
});
TotalTimeDisplay.displayName = 'TotalTimeDisplay';


export const TotalDurationByDate = React.memo(
({ timesheetLog, createdAt }: { timesheetLog: TimesheetLog[]; createdAt: Date | string }) => {
const targetDateISO = new Date(createdAt).toISOString();
const filteredLogs = timesheetLog.filter(
(item) => formatDate(item.timesheet.createdAt) === formatDate(targetDateISO));
const totalDurationInSeconds = filteredLogs.reduce(
(total, log) => total + (log.timesheet?.duration || 0), 0);
const { h: hours, m: minutes } = secondsToTime(totalDurationInSeconds);
return (
<div className="flex items-center text-[#868688]">
{formatTime(hours, minutes)}
</div>
);
}
);
TotalDurationByDate.displayName = 'TotalDurationByDate';

0 comments on commit e8d0801

Please sign in to comment.