From 01199b0d2a55c9e0f8d66e03aa1a5acfc0f6b5ce Mon Sep 17 00:00:00 2001 From: Innocent-akim Date: Fri, 22 Nov 2024 16:03:48 +0200 Subject: [PATCH] fix: simplify and improve readability of conditional rendering in timesheet display --- .../[memberId]/components/FrequencySelect.tsx | 15 ++++---- .../[locale]/timesheet/[memberId]/page.tsx | 36 ++++++++++--------- .../hooks/features/useTimelogFilterOptions.ts | 5 ++- apps/web/app/hooks/features/useTimesheet.ts | 26 ++++++++------ apps/web/app/stores/time-logs.ts | 5 +-- .../calendar/table-time-sheet.tsx | 25 +++++++++---- 6 files changed, 69 insertions(+), 43 deletions(-) diff --git a/apps/web/app/[locale]/timesheet/[memberId]/components/FrequencySelect.tsx b/apps/web/app/[locale]/timesheet/[memberId]/components/FrequencySelect.tsx index ef2f316d1..40f8be758 100644 --- a/apps/web/app/[locale]/timesheet/[memberId]/components/FrequencySelect.tsx +++ b/apps/web/app/[locale]/timesheet/[memberId]/components/FrequencySelect.tsx @@ -22,6 +22,8 @@ import { DatePicker } from "@components/ui/DatePicker"; import { cn } from "@/lib/utils"; import { format } from "date-fns"; import { PiCalendarDotsThin } from "react-icons/pi"; +import { useLocalStorageState, useTimelogFilterOptions } from "@/app/hooks"; +import { TimesheetFilterByDays } from "@/app/interfaces"; interface DatePickerInputProps { date: Date | null; @@ -29,24 +31,25 @@ interface DatePickerInputProps { } export function FrequencySelect() { - const [selectedValue, setSelectedValue] = React.useState(undefined); + const [] = useLocalStorageState('timesheet-group-by-day', 'Daily') + const { setTimesheetGroupByDays, timesheetGroupByDays } = useTimelogFilterOptions(); const handleSelectChange = (value: string) => { - setSelectedValue(value); + setTimesheetGroupByDays(value as TimesheetFilterByDays); }; return ( diff --git a/apps/web/app/[locale]/timesheet/[memberId]/page.tsx b/apps/web/app/[locale]/timesheet/[memberId]/page.tsx index 0f5b0243b..1d5019ad7 100644 --- a/apps/web/app/[locale]/timesheet/[memberId]/page.tsx +++ b/apps/web/app/[locale]/timesheet/[memberId]/page.tsx @@ -8,7 +8,7 @@ import { withAuthentication } from 'lib/app/authenticator'; import { Breadcrumb, Container } from 'lib/components'; import { MainLayout } from 'lib/layout'; -import { useAuthenticateUser, useLocalStorageState, useModal, useOrganizationTeams } from '@app/hooks'; +import { useAuthenticateUser, useLocalStorageState, useModal, useOrganizationTeams, useTimelogFilterOptions } from '@app/hooks'; import { clsxm } from '@app/utils'; import { fullWidthState } from '@app/stores/fullWidth'; import { useAtomValue } from 'jotai'; @@ -43,25 +43,30 @@ const TimeSheet = React.memo(function TimeSheetPage({ params }: { params: { memb from: startOfDay(new Date()), to: endOfDay(new Date()) }); - - const { timesheet, statusTimesheet, timesheetGroupByMonth, timesheetGroupByWeek } = useTimesheet({ + const { timesheet, statusTimesheet } = useTimesheet({ startDate: dateRange.from ?? '', endDate: dateRange.to ?? '' }); const lowerCaseSearch = useMemo(() => search?.toLowerCase() ?? '', [search]); - const filterDataTimesheet = useMemo( - () => - timesheetGroupByWeek.filter((v) => - v.tasks.some( - (task) => - task.task?.title?.toLowerCase()?.includes(lowerCaseSearch) || - task.employee?.fullName?.toLowerCase()?.includes(lowerCaseSearch) || - task.project?.name?.toLowerCase()?.includes(lowerCaseSearch) - ) - ), - [timesheet, timesheetGroupByMonth, timesheetGroupByWeek, lowerCaseSearch] - ); + const filterDataTimesheet = useMemo(() => { + const filteredTimesheet = + timesheet + .filter((v) => + v.tasks.some( + (task) => + task.task?.title?.toLowerCase()?.includes(lowerCaseSearch) || + task.employee?.fullName?.toLowerCase()?.includes(lowerCaseSearch) || + task.project?.name?.toLowerCase()?.includes(lowerCaseSearch) + ) + ); + + return filteredTimesheet; + }, [ + timesheet, + lowerCaseSearch, + ]); + const { isOpen: isManualTimeModalOpen, @@ -166,7 +171,6 @@ const TimeSheet = React.memo(function TimeSheetPage({ params }: { params: { memb /> - { if (!items?.length) return []; type GroupedMap = Record; - const groupedByDate = items.reduce((acc, item) => { if (!item?.timesheet?.createdAt) { console.warn('Skipping item with missing timesheet or createdAt:', item); @@ -115,15 +114,13 @@ const groupByMonth = (items: TimesheetLog[]): GroupedTimesheet[] => { .sort((a, b) => b.date.localeCompare(a.date)); }; - - export function useTimesheet({ startDate, endDate, }: TimesheetParams) { const { user } = useAuthenticateUser(); const [timesheet, setTimesheet] = useAtom(timesheetRapportState); - const { employee, project, task, statusState, selectTimesheet: logIds } = useTimelogFilterOptions(); + const { employee, project, task, statusState, selectTimesheet: logIds, timesheetGroupByDays } = useTimelogFilterOptions(); const { loading: loadingTimesheet, queryCall: queryTimesheet } = useQuery(getTaskTimesheetLogsApi); const { loading: loadingDeleteTimesheet, queryCall: queryDeleteTimesheet } = useQuery(deleteTaskTimesheetLogsApi) @@ -222,22 +219,29 @@ export function useTimesheet({ }, [user, queryDeleteTimesheet, logIds, handleDeleteTimesheet] // deepscan-disable-line ); + const timesheetElementGroup = useMemo(() => { + if (timesheetGroupByDays === 'Daily') { + return groupByDate(timesheet); + } + if (timesheetGroupByDays === 'Weekly') { + return groupByWeek(timesheet); + } + return groupByMonth(timesheet); + }, [timesheetGroupByDays, timesheet]); + useEffect(() => { getTaskTimesheet({ startDate, endDate }); - }, [getTaskTimesheet, startDate, endDate]); - - + }, [getTaskTimesheet, startDate, endDate, timesheetGroupByDays]); return { loadingTimesheet, - timesheet: groupByDate(timesheet), - timesheetGroupByWeek: groupByWeek(timesheet), - timesheetGroupByMonth: groupByMonth(timesheet), + timesheet: timesheetElementGroup, getTaskTimesheet, loadingDeleteTimesheet, deleteTaskTimesheet, getStatusTimesheet, + timesheetGroupByDays, statusTimesheet: getStatusTimesheet(timesheet.flatMap((data) => data)) }; } diff --git a/apps/web/app/stores/time-logs.ts b/apps/web/app/stores/time-logs.ts index 41354870f..3292d8690 100644 --- a/apps/web/app/stores/time-logs.ts +++ b/apps/web/app/stores/time-logs.ts @@ -1,6 +1,6 @@ import { ITimerLogsDailyReport } from '@app/interfaces/timer/ITimerLogs'; import { atom } from 'jotai'; -import { IProject, ITeamTask, OT_Member, TimesheetLog } from '../interfaces'; +import { IProject, ITeamTask, OT_Member, TimesheetFilterByDays, TimesheetLog } from '../interfaces'; interface IFilterOption { value: string; @@ -16,4 +16,5 @@ export const timesheetFilterProjectState = atom([]); export const timesheetFilterTaskState = atom([]); export const timesheetFilterStatusState = atom([]); -export const timesheetDeleteState = atom([]) +export const timesheetDeleteState = atom([]); +export const timesheetGroupByDayState = atom('Daily') 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 968a65abc..dfe99c529 100644 --- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx +++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx @@ -153,7 +153,7 @@ export const columns: ColumnDef[] = [ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) { const { isOpen, openModal, closeModal } = useModal(); const { deleteTaskTimesheet, loadingDeleteTimesheet, getStatusTimesheet } = useTimesheet({}); - const { handleSelectRowTimesheet, selectTimesheet, setSelectTimesheet } = useTimelogFilterOptions(); + const { handleSelectRowTimesheet, selectTimesheet, setSelectTimesheet, timesheetGroupByDays } = useTimelogFilterOptions(); const [isDialogOpen, setIsDialogOpen] = React.useState(false); const handleConfirm = () => { try { @@ -235,20 +235,29 @@ export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) { isOpen={isOpen} />
- {data?.map((plan, index) => ( -
+ {data?.map((plan, index) => { + return
- {formatDate(plan.date)} +
+ + {timesheetGroupByDays === 'Daily' + ? '' + : timesheetGroupByDays === 'Weekly' + ? `Week ${index + 1}` + : ''} + + {formatDate(plan.date)} +
+ createdAt={formatDate(plan.date)} + />
- {Object.entries(getStatusTimesheet(plan.tasks)).map(([status, rows]) => (
- ))} + } + + )}