Skip to content

Commit 6670c0e

Browse files
committed
COMP-327: Enforcement Action combinations (front)
1 parent 714f9d1 commit 6670c0e

File tree

2 files changed

+170
-93
lines changed

2 files changed

+170
-93
lines changed
Lines changed: 159 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useEffect } from "react";
1+
import { FC, useEffect, useCallback, memo } from "react";
22
import { Box, Stack } from "@mui/material";
33
import ControlledAutoComplete from "@/components/Shared/Controlled/ControlledAutoComplete";
44
import { BCDesignTokens } from "epic.theme";
@@ -10,14 +10,14 @@ import { ComplianceFinding } from "@/models/ComplianceFinding";
1010
import { InspectionRequirementType } from "@/models/InspectionRequirementType";
1111
import { Agency } from "@/models/Agency";
1212
import ControlledCheckbox from "@/components/Shared/Controlled/ControlledCheckbox";
13-
import { useFormContext } from "react-hook-form";
14-
import { useWatch } from "react-hook-form";
15-
import ControlledToggleButtonGroup from "@/components/Shared/Controlled/ControlledToggleButtonGroup";
13+
import { useFormContext, useWatch } from "react-hook-form";
1614
import {
15+
ComplianceFindingEnum,
1716
EnforcementActionEnum,
1817
REGULATORY_CONSIDERATION_TYPE_ID,
1918
REQUIREMENT_TYPE_ID,
2019
} from "./RequirementUtils";
20+
import ControlledToggleButtonGroup from "@/components/Shared/Controlled/ControlledToggleButtonGroup";
2121

2222
type RequirementFormLeftProps = {
2323
inspectionRequirementTypesList: InspectionRequirementType[];
@@ -32,39 +32,139 @@ type RequirementFormLeftProps = {
3232
isRegulatoryConsiderationExists?: boolean;
3333
};
3434

35-
const RequirementFormLeft: FC<RequirementFormLeftProps> = ({
36-
inspectionRequirementTypesList,
37-
enforcementActionsList,
38-
complianceFindingsList,
39-
topicList,
40-
agencyList,
41-
appHeaderHeight,
42-
onRequirementTypeChange,
43-
isRegulatoryConsiderationExists,
44-
}) => {
45-
const { control } = useFormContext();
46-
const isReferredToAnotherAgency = useWatch({
47-
control,
48-
name: "isReferredToAnotherAgency",
49-
defaultValue: false,
50-
});
35+
const useRequirementForm = (enforcementActionsList: EnforcementAction[]) => {
36+
const { control, setValue } = useFormContext();
5137

52-
const selectedRequirementType = useWatch({
38+
const formValues = useWatch({
5339
control,
54-
name: "requirementType",
40+
name: [
41+
"isReferredToAnotherAgency",
42+
"requirementType",
43+
"enforcementAction",
44+
"complianceFinding",
45+
],
5546
});
5647

57-
const enforcementAction = useWatch({
58-
control,
59-
name: "enforcementAction",
60-
});
48+
const [
49+
isReferredToAnotherAgency,
50+
selectedRequirementType,
51+
enforcementAction,
52+
complianceFinding,
53+
] = formValues;
6154

6255
useEffect(() => {
63-
onRequirementTypeChange?.(selectedRequirementType);
64-
}, [selectedRequirementType, onRequirementTypeChange]);
56+
if (complianceFinding?.id === ComplianceFindingEnum.IN) {
57+
const notApplicable = enforcementActionsList.find(
58+
(action) => action.id === EnforcementActionEnum.NOT_APPLICABLE
59+
);
60+
if (notApplicable) {
61+
setValue("enforcementAction", notApplicable);
62+
}
63+
}
64+
}, [complianceFinding, enforcementActionsList, setValue]);
65+
66+
return {
67+
isReferredToAnotherAgency,
68+
selectedRequirementType,
69+
enforcementAction,
70+
complianceFinding,
71+
};
72+
};
73+
74+
const RequirementTypeSection = memo(
75+
({
76+
inspectionRequirementTypesList,
77+
isRegulatoryConsiderationExists,
78+
}: {
79+
inspectionRequirementTypesList: InspectionRequirementType[];
80+
isRegulatoryConsiderationExists?: boolean;
81+
}) => (
82+
<ControlledToggleButtonGroup
83+
name="requirementType"
84+
options={inspectionRequirementTypesList}
85+
aria-label="requirement type"
86+
disabled={isRegulatoryConsiderationExists}
87+
/>
88+
)
89+
);
90+
91+
const ComplianceSection = memo(
92+
({
93+
complianceFindingsList,
94+
enforcementActionsList,
95+
}: {
96+
complianceFindingsList: ComplianceFinding[];
97+
enforcementActionsList: EnforcementAction[];
98+
}) => {
99+
const { enforcementAction } = useRequirementForm(enforcementActionsList);
100+
101+
return (
102+
<Stack direction="row" gap={2}>
103+
<ControlledAutoComplete
104+
sx={{ width: "50%" }}
105+
name="complianceFinding"
106+
label="Compliance Finding"
107+
options={complianceFindingsList}
108+
getOptionLabel={(option) => option.name}
109+
getOptionKey={(option) => option.id}
110+
isOptionEqualToValue={(option, value) => option.id === value.id}
111+
fullWidth
112+
/>
113+
<Stack direction="column" sx={{ width: "50%" }}>
114+
<ControlledAutoComplete
115+
name="enforcementAction"
116+
label="Enforcement Action"
117+
options={enforcementActionsList}
118+
getOptionLabel={(option) => option.name}
119+
getOptionKey={(option) => option.id}
120+
isOptionEqualToValue={(option, value) =>
121+
option.id.toString() === value.id.toString()
122+
}
123+
fullWidth
124+
sx={{ marginBottom: "-0.5rem" }}
125+
/>
126+
{enforcementAction?.id === EnforcementActionEnum.ORDER && (
127+
<ControlledCheckbox
128+
name="isReferralToAdministrativePenalty"
129+
label="Add Referral to Administrative Penalty"
130+
fontSize="small"
131+
/>
132+
)}
133+
</Stack>
134+
</Stack>
135+
);
136+
}
137+
);
138+
139+
const RequirementFormLeft: FC<RequirementFormLeftProps> = memo(
140+
({
141+
inspectionRequirementTypesList,
142+
enforcementActionsList,
143+
complianceFindingsList,
144+
topicList,
145+
agencyList,
146+
appHeaderHeight,
147+
onRequirementTypeChange,
148+
isRegulatoryConsiderationExists,
149+
}) => {
150+
const {
151+
isReferredToAnotherAgency,
152+
selectedRequirementType,
153+
enforcementAction,
154+
} = useRequirementForm(enforcementActionsList);
155+
156+
const handleRequirementTypeChange = useCallback(
157+
(requirementType: InspectionRequirementType | null) => {
158+
onRequirementTypeChange?.(requirementType);
159+
},
160+
[onRequirementTypeChange]
161+
);
65162

66-
return (
67-
<>
163+
useEffect(() => {
164+
handleRequirementTypeChange(selectedRequirementType);
165+
}, [selectedRequirementType, handleRequirementTypeChange]);
166+
167+
return (
68168
<Box
69169
sx={{
70170
background: BCDesignTokens.surfaceColorBackgroundLightGray,
@@ -74,11 +174,9 @@ const RequirementFormLeft: FC<RequirementFormLeftProps> = ({
74174
boxSizing: "border-box",
75175
}}
76176
>
77-
<ControlledToggleButtonGroup
78-
name="requirementType"
79-
options={inspectionRequirementTypesList}
80-
aria-label="requirement type"
81-
disabled={isRegulatoryConsiderationExists}
177+
<RequirementTypeSection
178+
inspectionRequirementTypesList={inspectionRequirementTypesList}
179+
isRegulatoryConsiderationExists={isRegulatoryConsiderationExists}
82180
/>
83181
<ControlledTextField
84182
name="requirementSummary"
@@ -102,60 +200,31 @@ const RequirementFormLeft: FC<RequirementFormLeftProps> = ({
102200
fullWidth
103201
/>
104202
{selectedRequirementType?.id === REGULATORY_CONSIDERATION_TYPE_ID && (
105-
<>
106-
<ControlledCheckbox
107-
name="isReferredToAnotherAgency"
108-
label="Mark if issue was referred to another Agency"
109-
/>
110-
{isReferredToAnotherAgency && (
111-
<ControlledAutoComplete
112-
name="agency"
113-
label="Agency"
114-
options={agencyList}
115-
getOptionLabel={(option) => option.name}
116-
getOptionKey={(option) => option.id}
117-
isOptionEqualToValue={(option, value) =>
118-
option.id.toString() === value.id.toString()
119-
}
120-
fullWidth
121-
/>
122-
)}
123-
</>
203+
<ControlledCheckbox
204+
name="isReferredToAnotherAgency"
205+
label="Mark if issue was referred to another Agency"
206+
/>
124207
)}
125208
{selectedRequirementType?.id === REQUIREMENT_TYPE_ID && (
126-
<Stack direction={"row"} gap={2}>
127-
<ControlledAutoComplete
128-
sx={{ width: "50%" }}
129-
name="complianceFinding"
130-
label="Compliance Finding"
131-
options={complianceFindingsList}
132-
getOptionLabel={(option) => option.name}
133-
getOptionKey={(option) => option.id}
134-
isOptionEqualToValue={(option, value) => option.id === value.id}
135-
fullWidth
136-
/>
137-
<Stack direction={"column"} sx={{ width: "50%" }}>
138-
<ControlledAutoComplete
139-
name="enforcementAction"
140-
label="Enforcement Action"
141-
options={enforcementActionsList}
142-
getOptionLabel={(option) => option.name}
143-
getOptionKey={(option) => option.id}
144-
isOptionEqualToValue={(option, value) =>
145-
option.id.toString() === value.id.toString()
146-
}
147-
fullWidth
148-
sx={{ marginBottom: "-0.5rem" }}
149-
/>
150-
{enforcementAction?.id === EnforcementActionEnum.ORDER && (
151-
<ControlledCheckbox
152-
name="isReferralToAdministrativePenalty"
153-
label="Add Referral to Administrative Penalty"
154-
fontSize="small"
155-
/>
156-
)}
157-
</Stack>
158-
</Stack>
209+
<ComplianceSection
210+
complianceFindingsList={complianceFindingsList}
211+
enforcementActionsList={enforcementActionsList}
212+
/>
213+
)}
214+
{(isReferredToAnotherAgency ||
215+
enforcementAction?.id ===
216+
EnforcementActionEnum.REFER_TO_ANOTHER_AGENCY) && (
217+
<ControlledAutoComplete
218+
name="agency"
219+
label="Agency"
220+
options={agencyList}
221+
getOptionLabel={(option) => option.name}
222+
getOptionKey={(option) => option.id}
223+
isOptionEqualToValue={(option, value) =>
224+
option.id.toString() === value.id.toString()
225+
}
226+
fullWidth
227+
/>
159228
)}
160229
<ControlledRichTextEditor
161230
label="Findings"
@@ -164,8 +233,8 @@ const RequirementFormLeft: FC<RequirementFormLeftProps> = ({
164233
marginBottom="0"
165234
/>
166235
</Box>
167-
</>
168-
);
169-
};
236+
);
237+
}
238+
);
170239

171240
export default RequirementFormLeft;

compliance-web/src/components/App/Inspections/Profile/Requirements/RequirementUtils.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@ export const REQUIREMENT_TYPE_ID = "REQ";
1111
export const REGULATORY_CONSIDERATION_TYPE_ID = "REG";
1212

1313
export enum EnforcementActionEnum {
14+
NOT_APPLICABLE = "2",
1415
ORDER = "5",
1516
REFERRAL_TO_ADMINISTRATIVE_PENALTY = "6",
17+
REFER_TO_ANOTHER_AGENCY = "7",
18+
}
19+
20+
export enum ComplianceFindingEnum {
21+
IN = "1",
1622
}
1723

1824
export const RequirementFormSchema = yup.object().shape({
@@ -27,9 +33,10 @@ export const RequirementFormSchema = yup.object().shape({
2733
then: (schema) => schema,
2834
otherwise: (schema) => schema.strip(),
2935
}),
30-
agency: yup.object<Agency>().nullable().when(['requirementType', 'isReferredToAnotherAgency'], {
31-
is: (requirementType: InspectionRequirementType, isReferred: boolean) =>
32-
requirementType?.id === REGULATORY_CONSIDERATION_TYPE_ID && isReferred,
36+
agency: yup.object<Agency>().nullable().when(['requirementType', 'isReferredToAnotherAgency', 'enforcementAction'], {
37+
is: (requirementType: InspectionRequirementType, isReferred: boolean, enforcementAction: EnforcementAction) =>
38+
(requirementType?.id === REGULATORY_CONSIDERATION_TYPE_ID && isReferred) ||
39+
(requirementType?.id === REQUIREMENT_TYPE_ID && enforcementAction?.id === EnforcementActionEnum.REFER_TO_ANOTHER_AGENCY),
3340
then: (schema) => schema.required("Agency is required"),
3441
otherwise: (schema) => schema.strip(),
3542
}),
@@ -98,6 +105,7 @@ export const formatRequirementAPIData = (
98105
topic_id: formData.topic?.id ?? 0,
99106
enforcement_action_ids: formData.enforcementAction?.id ? [formData.enforcementAction.id] : [],
100107
compliance_finding_id: formData.complianceFinding?.id ?? undefined,
108+
agency_id: formData.agency?.id ?? undefined,
101109
findings: formData.findings?.html ?? "",
102110
requirement_source_details: requirementSourceDetails,
103111
};

0 commit comments

Comments
 (0)