From 5d090833409eb087880d9cdad9ce51bea9ffb09d Mon Sep 17 00:00:00 2001 From: Wayne Date: Wed, 8 May 2024 23:26:32 +0900 Subject: [PATCH] Add ot hours to timesheet --- src/app/api/timesheets/actions.ts | 3 ++- src/app/api/timesheets/utils.ts | 15 ++++++++++----- src/components/LeaveModal/LeaveModal.tsx | 12 +++++++++++- .../TimesheetModal/TimesheetModal.tsx | 12 +++++++++++- .../TimesheetTable/EntryInputTable.tsx | 17 +++++++++++++---- .../TimesheetTable/TimesheetTable.tsx | 5 ++++- 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/app/api/timesheets/actions.ts b/src/app/api/timesheets/actions.ts index c836e6e..cd32d06 100644 --- a/src/app/api/timesheets/actions.ts +++ b/src/app/api/timesheets/actions.ts @@ -11,7 +11,8 @@ export interface TimeEntry { projectId?: ProjectResult["id"]; taskGroupId?: TaskGroup["id"]; taskId?: Task["id"]; - inputHours: number; + inputHours?: number; + otHours?: number; remark?: string; } diff --git a/src/app/api/timesheets/utils.ts b/src/app/api/timesheets/utils.ts index 68ee075..c305e26 100644 --- a/src/app/api/timesheets/utils.ts +++ b/src/app/api/timesheets/utils.ts @@ -8,19 +8,24 @@ export const isValidTimeEntry = (entry: Partial): string => { // Test for errors let error: keyof TimeEntry | "" = ""; + // Either normal or other hours need to be inputted + if (!entry.inputHours && !entry.otHours) { + error = "inputHours"; + } else if (entry.inputHours && entry.inputHours <= 0) { + error = "inputHours"; + } else if (entry.otHours && entry.otHours <= 0) { + error = "otHours"; + } + // If there is a project id, there should also be taskGroupId, taskId, inputHours if (entry.projectId) { if (!entry.taskGroupId) { error = "taskGroupId"; } else if (!entry.taskId) { error = "taskId"; - } else if (!entry.inputHours || !(entry.inputHours >= 0)) { - error = "inputHours"; } } else { - if (!entry.inputHours || !(entry.inputHours >= 0)) { - error = "inputHours"; - } else if (!entry.remark) { + if (!entry.remark) { error = "remark"; } } diff --git a/src/components/LeaveModal/LeaveModal.tsx b/src/components/LeaveModal/LeaveModal.tsx index b163003..c55c1c0 100644 --- a/src/components/LeaveModal/LeaveModal.tsx +++ b/src/components/LeaveModal/LeaveModal.tsx @@ -6,6 +6,7 @@ import { CardActions, CardContent, Modal, + ModalProps, SxProps, Typography, } from "@mui/material"; @@ -86,8 +87,17 @@ const LeaveModal: React.FC = ({ onClose(); }, [defaultValues, formProps, onClose]); + const onModalClose = useCallback>( + (_, reason) => { + if (reason !== "backdropClick") { + onClose(); + } + }, + [onClose], + ); + return ( - + = ({ onClose(); }, [defaultValues, formProps, onClose]); + const onModalClose = useCallback>( + (_, reason) => { + if (reason !== "backdropClick") { + onClose(); + } + }, + [onClose], + ); + return ( - + = ({ { field: "projectId", headerName: t("Project Code and Name"), - width: 400, + width: 300, editable: true, valueFormatter(params) { const project = assignedProjects.find((p) => p.id === params.value); @@ -310,7 +310,17 @@ const EntryInputTable: React.FC = ({ editable: true, type: "number", valueFormatter(params) { - return manhourFormatter.format(params.value); + return manhourFormatter.format(params.value || 0); + }, + }, + { + field: "otHours", + headerName: t("Other Hours"), + width: 150, + editable: true, + type: "number", + valueFormatter(params) { + return manhourFormatter.format(params.value || 0); }, }, { @@ -336,10 +346,9 @@ const EntryInputTable: React.FC = ({ useEffect(() => { setValue(day, [ ...entries - .filter((e) => !e._isNew && !e._error && e.id && e.inputHours) + .filter((e) => !e._isNew && !e._error && e.id) .map(({ isPlanned, _error, _isNew, ...entry }) => ({ id: entry.id!, - inputHours: entry.inputHours!, ...entry, })), ]); diff --git a/src/components/TimesheetTable/TimesheetTable.tsx b/src/components/TimesheetTable/TimesheetTable.tsx index a2ab876..4a39162 100644 --- a/src/components/TimesheetTable/TimesheetTable.tsx +++ b/src/components/TimesheetTable/TimesheetTable.tsx @@ -75,7 +75,10 @@ const DayRow: React.FC<{ const dayJsObj = dayjs(day); const [open, setOpen] = useState(false); - const totalHours = entries.reduce((acc, entry) => acc + entry.inputHours, 0); + const totalHours = entries.reduce( + (acc, entry) => acc + (entry.inputHours || 0) + (entry.otHours || 0), + 0, + ); return ( <>