|
- "use client";
-
- import Check from "@mui/icons-material/Check";
- import Close from "@mui/icons-material/Close";
- import Button from "@mui/material/Button";
- import Stack from "@mui/material/Stack";
- import Tab from "@mui/material/Tab";
- import Tabs, { TabsProps } from "@mui/material/Tabs";
- import { useRouter } from "next/navigation";
- import React, { useCallback, useState } from "react";
- import { useTranslation } from "react-i18next";
- import ProjectClientDetails from "./ProjectClientDetails";
- import TaskSetup from "./TaskSetup";
- import StaffAllocation from "./StaffAllocation";
- import Milestone from "./Milestone";
- import { Task, TaskTemplate } from "@/app/api/tasks";
- import {
- FieldErrors,
- FormProvider,
- SubmitErrorHandler,
- SubmitHandler,
- useForm,
- } from "react-hook-form";
- import { CreateProjectInputs, saveProject } from "@/app/api/projects/actions";
- import { Error } from "@mui/icons-material";
- import {
- BuildingType,
- ContractType,
- FundingType,
- LocationType,
- ProjectCategory,
- ServiceType,
- WorkNature,
- } from "@/app/api/projects";
- import { StaffResult } from "@/app/api/staff";
- import { Typography } from "@mui/material";
- import { Grade } from "@/app/api/grades";
- import { Customer } from "@/app/api/customer";
-
- export interface Props {
- allTasks: Task[];
- projectCategories: ProjectCategory[];
- taskTemplates: TaskTemplate[];
- teamLeads: StaffResult[];
- allCustomers: Customer[];
- fundingTypes: FundingType[];
- serviceTypes: ServiceType[];
- contractTypes: ContractType[];
- locationTypes: LocationType[];
- buildingTypes: BuildingType[];
- workNatures: WorkNature[];
- allStaffs: StaffResult[];
-
- // Mocked
- grades: Grade[];
- }
-
- const hasErrorsInTab = (
- tabIndex: number,
- errors: FieldErrors<CreateProjectInputs>,
- ) => {
- switch (tabIndex) {
- case 0:
- return (
- errors.projectName || errors.projectCode || errors.projectDescription
- );
- default:
- false;
- }
- };
-
- const CreateProject: React.FC<Props> = ({
- allTasks,
- projectCategories,
- taskTemplates,
- teamLeads,
- grades,
- allCustomers,
- contractTypes,
- fundingTypes,
- locationTypes,
- serviceTypes,
- buildingTypes,
- workNatures,
- allStaffs,
- }) => {
- const [serverError, setServerError] = useState("");
- const [tabIndex, setTabIndex] = useState(0);
- const { t } = useTranslation();
- const router = useRouter();
-
- const handleCancel = () => {
- router.back();
- };
-
- const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
- (_e, newValue) => {
- setTabIndex(newValue);
- },
- [],
- );
-
- const onSubmit = useCallback<SubmitHandler<CreateProjectInputs>>(
- async (data) => {
- try {
- setServerError("");
- await saveProject(data);
- router.replace("/projects");
- } catch (e) {
- setServerError(t("An error has occurred. Please try again later."));
- }
- },
- [router, t],
- );
-
- const onSubmitError = useCallback<SubmitErrorHandler<CreateProjectInputs>>(
- (errors) => {
- // Set the tab so that the focus will go there
- if (
- errors.projectName ||
- errors.projectDescription ||
- errors.projectCode
- ) {
- setTabIndex(0);
- }
- },
- [],
- );
-
- const formProps = useForm<CreateProjectInputs>({
- defaultValues: {
- taskGroups: {},
- allocatedStaffIds: [],
- milestones: {},
- totalManhour: 0,
- manhourPercentageByGrade: grades.reduce((acc, grade) => {
- return { ...acc, [grade.id]: 1 / grades.length };
- }, {}),
- },
- });
-
- const errors = formProps.formState.errors;
-
- return (
- <FormProvider {...formProps}>
- <Stack
- spacing={2}
- component="form"
- onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
- >
- <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable">
- <Tab
- label={t("Project and Client Details")}
- icon={
- hasErrorsInTab(0, errors) ? (
- <Error sx={{ marginInlineEnd: 1 }} color="error" />
- ) : undefined
- }
- iconPosition="end"
- />
- <Tab label={t("Project Task Setup")} iconPosition="end" />
- <Tab label={t("Staff Allocation and Resource")} iconPosition="end" />
- <Tab label={t("Milestone")} iconPosition="end" />
- </Tabs>
- {
- <ProjectClientDetails
- buildingTypes={buildingTypes}
- workNatures={workNatures}
- contractTypes={contractTypes}
- fundingTypes={fundingTypes}
- locationTypes={locationTypes}
- serviceTypes={serviceTypes}
- allCustomers={allCustomers}
- projectCategories={projectCategories}
- teamLeads={teamLeads}
- isActive={tabIndex === 0}
- />
- }
- {
- <TaskSetup
- allTasks={allTasks}
- taskTemplates={taskTemplates}
- isActive={tabIndex === 1}
- />
- }
- {
- <StaffAllocation
- isActive={tabIndex === 2}
- allTasks={allTasks}
- grades={grades}
- allStaffs={allStaffs}
- />
- }
- {<Milestone allTasks={allTasks} isActive={tabIndex === 3} />}
- {serverError && (
- <Typography variant="body2" color="error" alignSelf="flex-end">
- {serverError}
- </Typography>
- )}
- <Stack direction="row" justifyContent="flex-end" gap={1}>
- <Button
- variant="outlined"
- startIcon={<Close />}
- onClick={handleCancel}
- >
- {t("Cancel")}
- </Button>
- <Button variant="contained" startIcon={<Check />} type="submit">
- {t("Confirm")}
- </Button>
- </Stack>
- </Stack>
- </FormProvider>
- );
- };
-
- export default CreateProject;
|