import React, { useCallback, useEffect, useMemo } from "react"; import { Box, Button, Card, CardActions, CardContent, Modal, ModalProps, SxProps, Typography, } from "@mui/material"; import TimesheetTable from "../TimesheetTable"; import { useTranslation } from "react-i18next"; import { Check, Close } from "@mui/icons-material"; import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { RecordLeaveInput, RecordTimesheetInput, saveTimesheet, } from "@/app/api/timesheets/actions"; import dayjs from "dayjs"; import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; import { AssignedProject, ProjectWithTasks } from "@/app/api/projects"; import FullscreenModal from "../FullscreenModal"; import MobileTimesheetTable from "../TimesheetTable/MobileTimesheetTable"; import useIsMobile from "@/app/utils/useIsMobile"; import { HolidaysResult } from "@/app/api/holidays"; import { DAILY_NORMAL_MAX_HOURS, TIMESHEET_DAILY_MAX_HOURS, validateTimesheet, } from "@/app/api/timesheets/utils"; import ErrorAlert from "../ErrorAlert"; interface Props { isOpen: boolean; onClose: () => void; allProjects: ProjectWithTasks[]; assignedProjects: AssignedProject[]; username: string; defaultTimesheets?: RecordTimesheetInput; leaveRecords: RecordLeaveInput; companyHolidays: HolidaysResult[]; fastEntryEnabled?: boolean; } const modalSx: SxProps = { position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: { xs: "calc(100% - 2rem)", sm: "90%" }, maxHeight: "90%", maxWidth: 1400, }; const TimesheetModal: React.FC = ({ isOpen, onClose, allProjects, assignedProjects, username, defaultTimesheets, leaveRecords, companyHolidays, fastEntryEnabled, }) => { const { t } = useTranslation("home"); const defaultValues = useMemo(() => { const today = dayjs(); return Array(7) .fill(undefined) .reduce((acc, _, index) => { const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT); return { ...acc, [date]: defaultTimesheets?.[date] ?? [], }; }, {}); }, [defaultTimesheets]); const formProps = useForm({ defaultValues }); useEffect(() => { formProps.reset(defaultValues); }, [defaultValues, formProps]); const onSubmit = useCallback>( async (data) => { const errors = validateTimesheet(data, leaveRecords, companyHolidays); if (errors) { Object.keys(errors).forEach((date) => formProps.setError(date, { message: errors[date], }), ); return; } const savedRecords = await saveTimesheet(data, username); const today = dayjs(); const newFormValues = Array(7) .fill(undefined) .reduce((acc, _, index) => { const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT); return { ...acc, [date]: savedRecords[date] ?? [], }; }, {}); formProps.reset(newFormValues); onClose(); }, [companyHolidays, formProps, leaveRecords, onClose, username], ); const onCancel = useCallback(() => { formProps.reset(defaultValues); onClose(); }, [defaultValues, formProps, onClose]); const onModalClose = useCallback>( (_, reason) => { if (reason !== "backdropClick") { onClose(); } }, [onClose], ); const errorComponent = ( { const error = formProps.formState.errors[date]?.message; return error ? `${date}: ${t(error, { TIMESHEET_DAILY_MAX_HOURS, DAILY_NORMAL_MAX_HOURS, })}` : undefined; })} /> ); const matches = useIsMobile(); return ( {!matches ? ( // Desktop version {t("Timesheet Input")} {errorComponent} ) : ( // Mobile version {t("Timesheet Input")} )} ); }; export default TimesheetModal;