|
- import React, { useCallback, 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 {
- 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";
-
- interface Props {
- isOpen: boolean;
- onClose: () => void;
- allProjects: ProjectWithTasks[];
- assignedProjects: AssignedProject[];
- username: string;
- defaultTimesheets?: RecordTimesheetInput;
- }
-
- const modalSx: SxProps = {
- position: "absolute",
- top: "50%",
- left: "50%",
- transform: "translate(-50%, -50%)",
- width: { xs: "calc(100% - 2rem)", sm: "90%" },
- maxHeight: "90%",
- maxWidth: 1200,
- };
-
- const TimesheetModal: React.FC<Props> = ({
- isOpen,
- onClose,
- allProjects,
- assignedProjects,
- username,
- defaultTimesheets,
- }) => {
- const { t } = useTranslation("home");
-
- const defaultValues = useMemo(() => {
- const today = dayjs();
- return Array(7)
- .fill(undefined)
- .reduce<RecordTimesheetInput>((acc, _, index) => {
- const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT);
- return {
- ...acc,
- [date]: defaultTimesheets?.[date] ?? [],
- };
- }, {});
- }, [defaultTimesheets]);
-
- const formProps = useForm<RecordTimesheetInput>({ defaultValues });
-
- const onSubmit = useCallback<SubmitHandler<RecordTimesheetInput>>(
- async (data) => {
- const savedRecords = await saveTimesheet(data, username);
-
- const today = dayjs();
- const newFormValues = Array(7)
- .fill(undefined)
- .reduce<RecordTimesheetInput>((acc, _, index) => {
- const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT);
- return {
- ...acc,
- [date]: savedRecords[date] ?? [],
- };
- }, {});
-
- formProps.reset(newFormValues);
- onClose();
- },
- [formProps, onClose, username],
- );
-
- const onCancel = useCallback(() => {
- formProps.reset(defaultValues);
- onClose();
- }, [defaultValues, formProps, onClose]);
-
- const onModalClose = useCallback<NonNullable<ModalProps["onClose"]>>(
- (_, reason) => {
- if (reason !== "backdropClick") {
- onClose();
- }
- },
- [onClose],
- );
-
- return (
- <Modal open={isOpen} onClose={onModalClose}>
- <Card sx={modalSx}>
- <FormProvider {...formProps}>
- <CardContent
- component="form"
- onSubmit={formProps.handleSubmit(onSubmit)}
- >
- <Typography variant="overline" display="block" marginBlockEnd={1}>
- {t("Timesheet Input")}
- </Typography>
- <Box
- sx={{
- marginInline: -3,
- marginBlock: 4,
- }}
- >
- <TimesheetTable
- assignedProjects={assignedProjects}
- allProjects={allProjects}
- />
- </Box>
- <CardActions sx={{ justifyContent: "flex-end" }}>
- <Button
- variant="outlined"
- startIcon={<Close />}
- onClick={onCancel}
- >
- {t("Cancel")}
- </Button>
- <Button variant="contained" startIcon={<Check />} type="submit">
- {t("Save")}
- </Button>
- </CardActions>
- </CardContent>
- </FormProvider>
- </Card>
- </Modal>
- );
- };
-
- export default TimesheetModal;
|