| @@ -1,3 +1,4 @@ | |||||
| import { fetchAllCustomers, fetchAllSubsidiaries } from "@/app/api/customer"; | |||||
| import { | import { | ||||
| fetchProjectBuildingTypes, | fetchProjectBuildingTypes, | ||||
| fetchProjectCategories, | fetchProjectCategories, | ||||
| @@ -31,6 +32,8 @@ const Projects: React.FC = async () => { | |||||
| fetchProjectServiceTypes(); | fetchProjectServiceTypes(); | ||||
| fetchProjectBuildingTypes(); | fetchProjectBuildingTypes(); | ||||
| fetchProjectWorkNatures(); | fetchProjectWorkNatures(); | ||||
| fetchAllCustomers(); | |||||
| fetchAllSubsidiaries(); | |||||
| preloadTeamLeads(); | preloadTeamLeads(); | ||||
| preloadStaff(); | preloadStaff(); | ||||
| @@ -35,7 +35,7 @@ import { | |||||
| import { StaffResult } from "@/app/api/staff"; | import { StaffResult } from "@/app/api/staff"; | ||||
| import { Typography } from "@mui/material"; | import { Typography } from "@mui/material"; | ||||
| import { Grade } from "@/app/api/grades"; | import { Grade } from "@/app/api/grades"; | ||||
| import { Customer } from "@/app/api/customer"; | |||||
| import { Customer, Subsidiary } from "@/app/api/customer"; | |||||
| export interface Props { | export interface Props { | ||||
| allTasks: Task[]; | allTasks: Task[]; | ||||
| @@ -43,6 +43,7 @@ export interface Props { | |||||
| taskTemplates: TaskTemplate[]; | taskTemplates: TaskTemplate[]; | ||||
| teamLeads: StaffResult[]; | teamLeads: StaffResult[]; | ||||
| allCustomers: Customer[]; | allCustomers: Customer[]; | ||||
| allSubsidiaries: Subsidiary[]; | |||||
| fundingTypes: FundingType[]; | fundingTypes: FundingType[]; | ||||
| serviceTypes: ServiceType[]; | serviceTypes: ServiceType[]; | ||||
| contractTypes: ContractType[]; | contractTypes: ContractType[]; | ||||
| @@ -76,6 +77,7 @@ const CreateProject: React.FC<Props> = ({ | |||||
| teamLeads, | teamLeads, | ||||
| grades, | grades, | ||||
| allCustomers, | allCustomers, | ||||
| allSubsidiaries, | |||||
| contractTypes, | contractTypes, | ||||
| fundingTypes, | fundingTypes, | ||||
| locationTypes, | locationTypes, | ||||
| @@ -171,6 +173,7 @@ const CreateProject: React.FC<Props> = ({ | |||||
| locationTypes={locationTypes} | locationTypes={locationTypes} | ||||
| serviceTypes={serviceTypes} | serviceTypes={serviceTypes} | ||||
| allCustomers={allCustomers} | allCustomers={allCustomers} | ||||
| allSubsidiaries={allSubsidiaries} | |||||
| projectCategories={projectCategories} | projectCategories={projectCategories} | ||||
| teamLeads={teamLeads} | teamLeads={teamLeads} | ||||
| isActive={tabIndex === 0} | isActive={tabIndex === 0} | ||||
| @@ -10,7 +10,7 @@ import { | |||||
| fetchProjectWorkNatures, | fetchProjectWorkNatures, | ||||
| } from "@/app/api/projects"; | } from "@/app/api/projects"; | ||||
| import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | ||||
| import { fetchAllCustomers } from "@/app/api/customer"; | |||||
| import { fetchAllCustomers, fetchAllSubsidiaries } from "@/app/api/customer"; | |||||
| const CreateProjectWrapper: React.FC = async () => { | const CreateProjectWrapper: React.FC = async () => { | ||||
| const [ | const [ | ||||
| @@ -19,6 +19,7 @@ const CreateProjectWrapper: React.FC = async () => { | |||||
| projectCategories, | projectCategories, | ||||
| teamLeads, | teamLeads, | ||||
| allCustomers, | allCustomers, | ||||
| allSubsidiaries, | |||||
| contractTypes, | contractTypes, | ||||
| fundingTypes, | fundingTypes, | ||||
| locationTypes, | locationTypes, | ||||
| @@ -32,6 +33,7 @@ const CreateProjectWrapper: React.FC = async () => { | |||||
| fetchProjectCategories(), | fetchProjectCategories(), | ||||
| fetchTeamLeads(), | fetchTeamLeads(), | ||||
| fetchAllCustomers(), | fetchAllCustomers(), | ||||
| fetchAllSubsidiaries(), | |||||
| fetchProjectContractTypes(), | fetchProjectContractTypes(), | ||||
| fetchProjectFundingTypes(), | fetchProjectFundingTypes(), | ||||
| fetchProjectLocationTypes(), | fetchProjectLocationTypes(), | ||||
| @@ -47,6 +49,7 @@ const CreateProjectWrapper: React.FC = async () => { | |||||
| projectCategories={projectCategories} | projectCategories={projectCategories} | ||||
| taskTemplates={taskTemplates} | taskTemplates={taskTemplates} | ||||
| teamLeads={teamLeads} | teamLeads={teamLeads} | ||||
| allSubsidiaries={allSubsidiaries} | |||||
| allCustomers={allCustomers} | allCustomers={allCustomers} | ||||
| contractTypes={contractTypes} | contractTypes={contractTypes} | ||||
| fundingTypes={fundingTypes} | fundingTypes={fundingTypes} | ||||
| @@ -43,7 +43,8 @@ const MilestoneSection: React.FC<Props> = ({ taskGroupId }) => { | |||||
| t, | t, | ||||
| i18n: { language }, | i18n: { language }, | ||||
| } = useTranslation(); | } = useTranslation(); | ||||
| const { getValues, setValue } = useFormContext<CreateProjectInputs>(); | |||||
| const { getValues, setValue, formState } = | |||||
| useFormContext<CreateProjectInputs>(); | |||||
| const [payments, setPayments] = useState<PaymentRow[]>( | const [payments, setPayments] = useState<PaymentRow[]>( | ||||
| getValues("milestones")[taskGroupId]?.payments || [], | getValues("milestones")[taskGroupId]?.payments || [], | ||||
| ); | ); | ||||
| @@ -223,6 +224,9 @@ const MilestoneSection: React.FC<Props> = ({ taskGroupId }) => { | |||||
| </Button> | </Button> | ||||
| ); | ); | ||||
| const startDate = getValues("milestones")[taskGroupId]?.startDate; | |||||
| const endDate = getValues("milestones")[taskGroupId]?.endDate; | |||||
| return ( | return ( | ||||
| <Stack gap={1}> | <Stack gap={1}> | ||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | <Typography variant="overline" display="block" marginBlockEnd={1}> | ||||
| @@ -237,7 +241,7 @@ const MilestoneSection: React.FC<Props> = ({ taskGroupId }) => { | |||||
| <FormControl fullWidth> | <FormControl fullWidth> | ||||
| <DatePicker | <DatePicker | ||||
| label={t("Stage Start Date")} | label={t("Stage Start Date")} | ||||
| value={dayjs(getValues("milestones")[taskGroupId]?.startDate)} | |||||
| value={startDate ? dayjs(startDate) : null} | |||||
| onChange={(date) => { | onChange={(date) => { | ||||
| if (!date) return; | if (!date) return; | ||||
| const milestones = getValues("milestones"); | const milestones = getValues("milestones"); | ||||
| @@ -256,7 +260,7 @@ const MilestoneSection: React.FC<Props> = ({ taskGroupId }) => { | |||||
| <FormControl fullWidth> | <FormControl fullWidth> | ||||
| <DatePicker | <DatePicker | ||||
| label={t("Stage End Date")} | label={t("Stage End Date")} | ||||
| value={dayjs(getValues("milestones")[taskGroupId]?.endDate)} | |||||
| value={endDate ? dayjs(endDate) : null} | |||||
| onChange={(date) => { | onChange={(date) => { | ||||
| if (!date) return; | if (!date) return; | ||||
| const milestones = getValues("milestones"); | const milestones = getValues("milestones"); | ||||
| @@ -27,7 +27,7 @@ import { | |||||
| WorkNature, | WorkNature, | ||||
| } from "@/app/api/projects"; | } from "@/app/api/projects"; | ||||
| import { StaffResult } from "@/app/api/staff"; | import { StaffResult } from "@/app/api/staff"; | ||||
| import { Contact, Customer } from "@/app/api/customer"; | |||||
| import { Contact, Customer, Subsidiary } from "@/app/api/customer"; | |||||
| import Link from "next/link"; | import Link from "next/link"; | ||||
| import React, { useEffect, useMemo, useState } from "react"; | import React, { useEffect, useMemo, useState } from "react"; | ||||
| import { fetchCustomer } from "@/app/api/customer/actions"; | import { fetchCustomer } from "@/app/api/customer/actions"; | ||||
| @@ -39,6 +39,7 @@ interface Props { | |||||
| projectCategories: ProjectCategory[]; | projectCategories: ProjectCategory[]; | ||||
| teamLeads: StaffResult[]; | teamLeads: StaffResult[]; | ||||
| allCustomers: Customer[]; | allCustomers: Customer[]; | ||||
| allSubsidiaries: Subsidiary[]; | |||||
| serviceTypes: ServiceType[]; | serviceTypes: ServiceType[]; | ||||
| contractTypes: ContractType[]; | contractTypes: ContractType[]; | ||||
| fundingTypes: FundingType[]; | fundingTypes: FundingType[]; | ||||
| @@ -52,6 +53,7 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||||
| projectCategories, | projectCategories, | ||||
| teamLeads, | teamLeads, | ||||
| allCustomers, | allCustomers, | ||||
| allSubsidiaries, | |||||
| serviceTypes, | serviceTypes, | ||||
| contractTypes, | contractTypes, | ||||
| fundingTypes, | fundingTypes, | ||||
| @@ -69,6 +71,13 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||||
| getValues, | getValues, | ||||
| } = useFormContext<CreateProjectInputs>(); | } = useFormContext<CreateProjectInputs>(); | ||||
| const subsidiaryMap = useMemo<{ | |||||
| [id: Subsidiary["id"]]: Subsidiary; | |||||
| }>( | |||||
| () => allSubsidiaries.reduce((acc, sub) => ({ ...acc, [sub.id]: sub }), {}), | |||||
| [allSubsidiaries], | |||||
| ); | |||||
| const selectedCustomerId = watch("clientId"); | const selectedCustomerId = watch("clientId"); | ||||
| const selectedCustomer = useMemo( | const selectedCustomer = useMemo( | ||||
| () => allCustomers.find((c) => c.id === selectedCustomerId), | () => allCustomers.find((c) => c.id === selectedCustomerId), | ||||
| @@ -482,14 +491,20 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||||
| name="clientSubsidiaryId" | name="clientSubsidiaryId" | ||||
| render={({ field }) => ( | render={({ field }) => ( | ||||
| <Select label={t("Client Lead")} {...field}> | <Select label={t("Client Lead")} {...field}> | ||||
| {customerSubsidiaryIds.map((subsidiaryId, index) => ( | |||||
| <MenuItem | |||||
| key={`${subsidiaryId}-${index}`} | |||||
| value={subsidiaryId} | |||||
| > | |||||
| {subsidiaryId} | |||||
| </MenuItem> | |||||
| ))} | |||||
| {customerSubsidiaryIds | |||||
| .filter((subId) => subsidiaryMap[subId]) | |||||
| .map((subsidiaryId, index) => { | |||||
| const subsidiary = subsidiaryMap[subsidiaryId]; | |||||
| return ( | |||||
| <MenuItem | |||||
| key={`${subsidiaryId}-${index}`} | |||||
| value={subsidiaryId} | |||||
| > | |||||
| {`${subsidiary.code} - ${subsidiary.name}`} | |||||
| </MenuItem> | |||||
| ); | |||||
| })} | |||||
| </Select> | </Select> | ||||
| )} | )} | ||||
| /> | /> | ||||