diff --git a/editor.planx.uk/src/@planx/components/PlanningConstraints/Modal.tsx b/editor.planx.uk/src/@planx/components/PlanningConstraints/Modal.tsx index 29b2027ce7..e8a5537cc8 100644 --- a/editor.planx.uk/src/@planx/components/PlanningConstraints/Modal.tsx +++ b/editor.planx.uk/src/@planx/components/PlanningConstraints/Modal.tsx @@ -29,6 +29,11 @@ interface OverrideEntitiesModalProps { ) => void; } +const ERROR_MESSAGES = { + checklist: "Select at least one option", + input: "Enter a value", +}; + export const OverrideEntitiesModal = ({ showModal, setShowModal, @@ -38,7 +43,15 @@ export const OverrideEntitiesModal = ({ inaccurateConstraints, setInaccurateConstraints, }: OverrideEntitiesModalProps) => { - const [errors, setErrors] = useState | undefined>(); + const [checkedOptions, setCheckedOptions] = useState( + inaccurateConstraints?.[fn]?.["entities"], + ); + const [showChecklistError, setShowChecklistError] = useState(false); + const [textInput, setTextInput] = useState( + inaccurateConstraints?.[fn]?.["reason"], + ); + const [showInputError, setShowInputError] = useState(false); + const title = `Which ${ metadata?.plural?.toLowerCase() || "entities" } are inaccurate?`; @@ -47,35 +60,57 @@ export const OverrideEntitiesModal = ({ if (reason && reason == "backdropClick") { return; } + // Clear any non-submitted inputs + setCheckedOptions(undefined); + setTextInput(undefined); setShowModal(false); }; - // Directly update inaccurateConstraints in state when options are selected/deselected const changeCheckbox = - (id: string, fn: Constraint["fn"]) => + (id: string) => (_checked: React.MouseEvent | undefined) => { let newCheckedIds; - if (inaccurateConstraints?.[fn]?.["entities"]?.includes(id)) { - newCheckedIds = inaccurateConstraints?.[fn]?.["entities"]?.filter( - (e) => e !== id, - ); + if (checkedOptions?.includes(id)) { + newCheckedIds = checkedOptions.filter((e) => e !== id); } else { - newCheckedIds = [ - ...(inaccurateConstraints?.[fn]?.["entities"] || []), - id, - ]; + newCheckedIds = [...(checkedOptions || []), id]; } + if (newCheckedIds.length > 0) { + setShowChecklistError(false); + } + setCheckedOptions(newCheckedIds); + }; + + const changeInput = (e: React.ChangeEvent) => { + if (e.target.value.length > 1) { + setShowInputError(false); + } + setTextInput(e.target.value); + }; + + const validateAndSubmit = () => { + const invalidChecklist = !checkedOptions || checkedOptions.length === 0; + const invalidInput = !textInput || textInput.trim().length === 0; + + // All form fields are required to submit + if (invalidChecklist && invalidInput) { + setShowChecklistError(true); + setShowInputError(true); + } else if (invalidChecklist) { + setShowChecklistError(true); + } else if (invalidInput) { + setShowInputError(true); + } else { + // Update inaccurateConstraints in parent component state on valid Modal submit const newInaccurateConstraints = { ...inaccurateConstraints, - ...{ [fn]: { entities: newCheckedIds, reason: "" } }, + ...{ [fn]: { entities: checkedOptions, reason: textInput } }, }; setInaccurateConstraints(newInaccurateConstraints); - }; - - const validateAndSubmit = () => { - setShowModal(false); + setShowModal(false); + } }; return ( @@ -130,7 +165,9 @@ export const OverrideEntitiesModal = ({ id={`checklist-label-inaccurate-entities`} > @@ -142,11 +179,9 @@ export const OverrideEntitiesModal = ({ id={`${e.entity}`} label={formatEntityName(e, metadata)} checked={ - inaccurateConstraints?.[fn]?.["entities"]?.includes( - `${e.entity}`, - ) || false + checkedOptions?.includes(`${e.entity}`) || false } - onChange={changeCheckbox(`${e.entity}`, fn)} + onChange={changeCheckbox(`${e.entity}`)} /> ))} @@ -155,8 +190,20 @@ export const OverrideEntitiesModal = ({ - - + + changeInput(e)} + />