From e8d0801bcc3e515ee035527e08e1ca9b353381c7 Mon Sep 17 00:00:00 2001 From: AKILIMAILI CIZUNGU Innocent <51681130+Innocent-Akim@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:48:57 +0200 Subject: [PATCH] [Feat]: Timesheet-Duration-Display (#3352) * 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 --- .../hooks/features/useTimelogFilterOptions.ts | 2 +- .../calendar/table-time-sheet.tsx | 23 +++---- apps/web/lib/features/task/task-displays.tsx | 60 ++++++++++++++++++- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/apps/web/app/hooks/features/useTimelogFilterOptions.ts b/apps/web/app/hooks/features/useTimelogFilterOptions.ts index ca39217a3..c246038a8 100644 --- a/apps/web/app/hooks/features/useTimelogFilterOptions.ts +++ b/apps/web/app/hooks/features/useTimelogFilterOptions.ts @@ -31,6 +31,6 @@ export function useTimelogFilterOptions() { setStatusState, handleSelectRowTimesheet, selectTimesheet, - setSelectTimesheet + setSelectTimesheet, }; } diff --git a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx index 52fb005b5..592c24c89 100644 --- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx +++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx @@ -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[] = [ { @@ -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' - )} - > + )}> {formatDate(plan.date)} - 64:30h + @@ -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" > - Total - 24:30h + {t('timer.TOTAL_HOURS')} +
@@ -339,10 +339,11 @@ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) { {task.timesheet.status}
- - {dayjs(task.timesheet.createdAt).format('HH:mm:ss')} - - + + ))} diff --git a/apps/web/lib/features/task/task-displays.tsx b/apps/web/lib/features/task/task-displays.tsx index 1f37c924a..0bca22f27 100644 --- a/apps/web/lib/features/task/task-displays.tsx +++ b/apps/web/lib/features/task/task-displays.tsx @@ -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; @@ -61,3 +64,58 @@ export function TaskNameInfoDisplay({ ); } + +const formatTime = (hours: number, minutes: number) => ( +
+ {String(hours).padStart(2, '0')} + : + {String(minutes).padStart(2, '0')} +
+); + +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 ( +
+ +
+ {formatTime(hours, minute)} +
+
+ ) + +} + +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 ( +
+ {formatTime(hours, minute)} +
) +}); +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 ( +
+ {formatTime(hours, minutes)} +
+ ); + } +); +TotalDurationByDate.displayName = 'TotalDurationByDate';