From e9ff2134700ff00779dcb887b8c577f9a7cea664 Mon Sep 17 00:00:00 2001 From: AKILIMAILI CIZUNGU Innocent <51681130+Innocent-Akim@users.noreply.github.com> Date: Sat, 28 Dec 2024 19:22:48 +0200 Subject: [PATCH] [Feat]: Add Selection/Deselection Functionality based on ID (#3488) * feat: Add selection/deselection functionality based on ID with full data handling * fix: deepscan --- .../components/RejectSelectedModal.tsx | 12 +++++++-- .../hooks/features/useTimelogFilterOptions.ts | 20 +++++++-------- apps/web/app/hooks/features/useTimesheet.ts | 16 ++++++------ .../calendar/table-time-sheet.tsx | 25 +++++++++++-------- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/apps/web/app/[locale]/timesheet/[memberId]/components/RejectSelectedModal.tsx b/apps/web/app/[locale]/timesheet/[memberId]/components/RejectSelectedModal.tsx index 44dc52055..6e82b567b 100644 --- a/apps/web/app/[locale]/timesheet/[memberId]/components/RejectSelectedModal.tsx +++ b/apps/web/app/[locale]/timesheet/[memberId]/components/RejectSelectedModal.tsx @@ -1,3 +1,4 @@ +import { useTimesheet } from '@/app/hooks/features/useTimesheet'; import { clsxm } from '@/app/utils'; import { Modal } from '@/lib/components'; import { useTranslations } from 'next-intl'; @@ -32,13 +33,20 @@ export function RejectSelectedModal({ }: IRejectSelectedModalProps) { const [isSubmitting, setIsSubmitting] = useState(false); const [reason, setReason] = useState(''); + const { updateTimesheetStatus, setSelectTimesheetId } = useTimesheet({}); + const t = useTranslations(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { - await onReject(reason); - closeModal(); + updateTimesheetStatus({ + status: 'DENIED', + ids: selectTimesheetId || [], + }).then(() => { + closeModal(); + setSelectTimesheetId([]) + }).catch((error) => console.error(error)); } finally { setIsSubmitting(false); } diff --git a/apps/web/app/hooks/features/useTimelogFilterOptions.ts b/apps/web/app/hooks/features/useTimelogFilterOptions.ts index 01fa63bc1..242352156 100644 --- a/apps/web/app/hooks/features/useTimelogFilterOptions.ts +++ b/apps/web/app/hooks/features/useTimelogFilterOptions.ts @@ -13,7 +13,7 @@ export function useTimelogFilterOptions() { const [timesheetGroupByDays, setTimesheetGroupByDays] = useAtom(timesheetGroupByDayState); const [puTimesheetStatus, setPuTimesheetStatus] = useAtom(timesheetUpdateStatus) const [selectedItems, setSelectedItems] = React.useState<{ status: string; date: string }[]>([]); - const [selectTimesheetId, setSelectTimesheetId] = React.useState([]) + const [selectTimesheetId, setSelectTimesheetId] = React.useState([]) const employee = employeeState; const project = projectState; @@ -48,22 +48,20 @@ export function useTimelogFilterOptions() { }); }; - const handleSelectRowTimesheet = (items: string) => { + const handleSelectRowTimesheet = (items: TimesheetLog) => { setSelectTimesheetId((prev) => prev.includes(items) ? prev.filter((filter) => filter !== items) : [...prev, items]) } const handleSelectRowByStatusAndDate = (logs: TimesheetLog[], isChecked: boolean) => { - setSelectTimesheetId((prev) => { - const logIds = logs.map((item) => item.id); + setSelectTimesheetId((prev: TimesheetLog[]) => { + const isLogIncluded = (log: TimesheetLog, list: TimesheetLog[]) => + list.some((item) => item.id === log.id); + if (!isChecked) { - const allSelected = logIds.every(id => prev.includes(id)); - if (allSelected) { - return prev.filter((id) => !logIds.includes(id)); - } else { - return [...new Set([...prev, ...logIds])]; - } + return prev.filter((prevLog) => !logs.some((log) => log.id === prevLog.id)); } - return [...new Set([...prev, ...logIds])]; + const newLogs = logs.filter((log) => !isLogIncluded(log, prev)); + return [...prev, ...newLogs]; }); }; diff --git a/apps/web/app/hooks/features/useTimesheet.ts b/apps/web/app/hooks/features/useTimesheet.ts index 56cdb231a..d06e4db2b 100644 --- a/apps/web/app/hooks/features/useTimesheet.ts +++ b/apps/web/app/hooks/features/useTimesheet.ts @@ -128,7 +128,7 @@ export function useTimesheet({ }: TimesheetParams) { const { user } = useAuthenticateUser(); const [timesheet, setTimesheet] = useAtom(timesheetRapportState); - const { employee, project, task, statusState, timesheetGroupByDays, puTimesheetStatus, isUserAllowedToAccess, normalizeText } = useTimelogFilterOptions(); + const { employee, project, task, statusState, timesheetGroupByDays, puTimesheetStatus, isUserAllowedToAccess, normalizeText, setSelectTimesheetId } = useTimelogFilterOptions(); const { loading: loadingTimesheet, queryCall: queryTimesheet } = useQuery(getTaskTimesheetLogsApi); const { loading: loadingDeleteTimesheet, queryCall: queryDeleteTimesheet } = useQuery(deleteTaskTimesheetLogsApi); const { loading: loadingUpdateTimesheetStatus, queryCall: queryUpdateTimesheetStatus } = useQuery(updateStatusTimesheetFromApi) @@ -198,13 +198,14 @@ export function useTimesheet({ } try { const response = await queryUpdateTimesheet(timesheet); - setTimesheet(prevTimesheet => - prevTimesheet.map(item => + setTimesheet((prevTimesheet) => { + const updatedTimesheets = prevTimesheet.map((item) => item.id === response.data.id - ? response.data + ? { ...item, ...response.data } : item - ) - ); + ); + return updatedTimesheets; + }); } catch (error) { console.error('Error updating timesheet:', error); throw error; @@ -365,6 +366,7 @@ export function useTimesheet({ loadingUpdateTimesheet, groupByDate, isManage, - normalizeText + normalizeText, + setSelectTimesheetId }; } 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 c47f736ec..66fcee16f 100644 --- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx +++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx @@ -64,7 +64,7 @@ export function DataTableTimeSheet({ data, user }: { data?: GroupedTimesheet[], const isManage = isUserAllowedToAccess(user); const handleConfirm = () => { try { - deleteTaskTimesheet({ logIds: selectTimesheetId }) + deleteTaskTimesheet({ logIds: selectTimesheetId?.map((select) => select.id).filter((id) => id !== undefined) }) .then(() => { setSelectTimesheetId([]); closeAlertConfirmation() @@ -86,10 +86,13 @@ export function DataTableTimeSheet({ data, user }: { data?: GroupedTimesheet[], switch (action) { case 'Approved': if (selectTimesheetId.length > 0) { - await updateTimesheetStatus({ + updateTimesheetStatus({ status: 'APPROVED', - ids: selectTimesheetId - }) + ids: selectTimesheetId.map((select) => + select.timesheetId) + .filter((timesheetId) => timesheetId !== undefined) + }).then(() => setSelectTimesheetId([])) + .catch((error) => console.error(error)) } break; case 'Denied': @@ -115,7 +118,9 @@ export function DataTableTimeSheet({ data, user }: { data?: GroupedTimesheet[], countID={selectTimesheetId.length} /> + select.timesheetId) + .filter((timesheetId) => timesheetId !== undefined)} onReject={() => { // Pending implementation }} @@ -187,7 +192,7 @@ export function DataTableTimeSheet({ data, user }: { data?: GroupedTimesheet[], handleSelectRowByStatusAndDate={ () => handleSelectRowByStatusAndDate( rows, - !rows.every(row => selectTimesheetId.includes(row.id)) + !rows.every(row => selectTimesheetId.includes(row)) ) } data={rows} @@ -209,8 +214,8 @@ export function DataTableTimeSheet({ data, user }: { data?: GroupedTimesheet[], > handleSelectRowTimesheet(task.id)} - checked={selectTimesheetId.includes(task.id)} + onCheckedChange={() => handleSelectRowTimesheet(task)} + checked={selectTimesheetId.includes(task)} />
void, date?: string, - selectedIds: string[] + selectedIds: TimesheetLog[] }) => { @@ -544,7 +549,7 @@ const HeaderRow = ({ Employee: null, Status: null, }); - const isAllSelected = data.length > 0 && data.every(row => selectedIds.includes(row.id)); + const isAllSelected = data.length > 0 && data.every(row => selectedIds.includes(row)); const handleSort = (key: string) => { const newOrder = sortState[key] === "ASC" ? "DESC" : "ASC";