From 84a7df61d2f552d2a80fefc80a624faa22f64895 Mon Sep 17 00:00:00 2001 From: Wayne Date: Sun, 21 Jul 2024 18:45:58 +0900 Subject: [PATCH] Add FT check for timesheet entry --- src/app/api/timesheets/index.ts | 2 ++ src/app/api/timesheets/utils.ts | 20 +++++++++++-- src/components/LeaveModal/LeaveCalendar.tsx | 15 ++++++++-- src/components/LeaveModal/LeaveModal.tsx | 2 ++ src/components/Logo/Logo.tsx | 6 ++-- .../TimeLeaveModal/TimeLeaveModal.tsx | 6 ++-- .../TimesheetAmendment/TimesheetAmendment.tsx | 18 +++++++++-- .../UserWorkspacePage/UserWorkspacePage.tsx | 11 ++++++- .../UserWorkspaceWrapper.tsx | 30 ++++++++++++++----- src/config/authConfig.ts | 7 +++-- 10 files changed, 93 insertions(+), 24 deletions(-) diff --git a/src/app/api/timesheets/index.ts b/src/app/api/timesheets/index.ts index ff0f5ad..9f0a0f3 100644 --- a/src/app/api/timesheets/index.ts +++ b/src/app/api/timesheets/index.ts @@ -13,6 +13,7 @@ export type TeamTimeSheets = { timeEntries: RecordTimesheetInput; staffId: string; name: string; + employType: string | null; }; }; @@ -21,6 +22,7 @@ export type TeamLeaves = { leaveEntries: RecordLeaveInput; staffId: string; name: string; + employType: string | null; }; }; diff --git a/src/app/api/timesheets/utils.ts b/src/app/api/timesheets/utils.ts index 81d798d..10b128b 100644 --- a/src/app/api/timesheets/utils.ts +++ b/src/app/api/timesheets/utils.ts @@ -3,6 +3,7 @@ import { HolidaysResult } from "../holidays"; import { LeaveEntry, RecordTimeLeaveInput, TimeEntry } from "./actions"; import { convertDateArrayToString } from "@/app/utils/formatUtil"; import compact from "lodash/compact"; +import dayjs from "dayjs"; export type TimeEntryError = { [field in keyof TimeEntry]?: string; @@ -80,6 +81,7 @@ export const validateLeaveEntry = ( export const validateTimeLeaveRecord = ( records: RecordTimeLeaveInput, companyHolidays: HolidaysResult[], + isFullTime?: boolean, ): { [date: string]: string } | undefined => { const errors: { [date: string]: string } = {}; @@ -91,14 +93,18 @@ export const validateTimeLeaveRecord = ( ); Object.keys(records).forEach((date) => { + const dayJsObj = dayjs(date); + const isHoliday = + holidays.has(date) || dayJsObj.day() === 0 || dayJsObj.day() === 6; + const entries = records[date]; // Check each entry for (const entry of entries) { let entryError; if (entry.type === "leaveEntry") { - entryError = validateLeaveEntry(entry, holidays.has(date)); + entryError = validateLeaveEntry(entry, isHoliday); } else { - entryError = validateTimeEntry(entry, holidays.has(date)); + entryError = validateTimeEntry(entry, isHoliday); } if (entryError) { @@ -111,6 +117,8 @@ export const validateTimeLeaveRecord = ( const totalHourError = checkTotalHours( entries.filter((e) => e.type === "timeEntry") as TimeEntry[], entries.filter((e) => e.type === "leaveEntry") as LeaveEntry[], + isHoliday, + isFullTime, ); if (totalHourError) { @@ -124,6 +132,8 @@ export const validateTimeLeaveRecord = ( export const checkTotalHours = ( timeEntries: TimeEntry[], leaves: LeaveEntry[], + isHoliday?: boolean, + isFullTime?: boolean, ): string | undefined => { const leaveHours = leaves.reduce((acc, entry) => acc + entry.inputHours, 0); @@ -137,6 +147,12 @@ export const checkTotalHours = ( if (totalInputHours + leaveHours > DAILY_NORMAL_MAX_HOURS) { return "The daily normal hours (timesheet hours + leave hours) cannot be more than {{DAILY_NORMAL_MAX_HOURS}}. Please use other hours for exceeding hours or decrease the leave hours."; + } else if ( + isFullTime && + !isHoliday && + totalInputHours + leaveHours !== DAILY_NORMAL_MAX_HOURS + ) { + return "The daily normal hours (timesheet hours + leave hours) for full-time staffs should be {{DAILY_NORMAL_MAX_HOURS}}."; } else if ( totalInputHours + totalOtHours + leaveHours > TIMESHEET_DAILY_MAX_HOURS diff --git a/src/components/LeaveModal/LeaveCalendar.tsx b/src/components/LeaveModal/LeaveCalendar.tsx index be3341b..447f4a7 100644 --- a/src/components/LeaveModal/LeaveCalendar.tsx +++ b/src/components/LeaveModal/LeaveCalendar.tsx @@ -34,6 +34,7 @@ export interface Props { allProjects: ProjectWithTasks[]; leaveRecords: RecordLeaveInput; timesheetRecords: RecordTimesheetInput; + isFullTime: boolean; } interface EventClickArg { @@ -53,6 +54,7 @@ const LeaveCalendar: React.FC = ({ leaveTypes, timesheetRecords, leaveRecords, + isFullTime, }) => { const { t } = useTranslation(["home", "common"]); @@ -215,6 +217,10 @@ const LeaveCalendar: React.FC = ({ if (!date) { throw Error("Invalid date"); } + const dayJsObj = dayjs(date); + const holiday = getHolidayForDate(date, companyHolidays); + const isHoliday = holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6; + const leaves = localLeaveRecords[date] || []; const timesheets = timesheetRecords[date] || []; @@ -224,11 +230,16 @@ const LeaveCalendar: React.FC = ({ "id", ); - const totalHourError = checkTotalHours(timesheets, leavesWithNewEntry); + const totalHourError = checkTotalHours( + timesheets, + leavesWithNewEntry, + Boolean(isHoliday), + isFullTime, + ); if (totalHourError) throw Error(totalHourError); }, - [localLeaveRecords, timesheetRecords], + [companyHolidays, isFullTime, localLeaveRecords, timesheetRecords], ); const handleSaveLeave = useCallback( diff --git a/src/components/LeaveModal/LeaveModal.tsx b/src/components/LeaveModal/LeaveModal.tsx index 7ae85ba..3739bd7 100644 --- a/src/components/LeaveModal/LeaveModal.tsx +++ b/src/components/LeaveModal/LeaveModal.tsx @@ -35,6 +35,7 @@ const LeaveModal: React.FC = ({ allProjects, leaveRecords, timesheetRecords, + isFullTime, }) => { const { t } = useTranslation("home"); const isMobile = useIsMobile(); @@ -42,6 +43,7 @@ const LeaveModal: React.FC = ({ const title = t("Record leave"); const content = ( = ({ width, height }) => {