From ef50330b963c0746360680bd1bde453278bc3527 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:55:29 +0000 Subject: [PATCH] add validation for allRequired and maxItems --- .../components/Checklist/Editor/Editor.tsx | 31 ++++++++--- .../components/Checklist/Editor/Options.tsx | 55 ++++++++++--------- .../components/Checklist/Public/helpers.ts | 9 ++- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx index 1fe4a6f19c..3ba495ce53 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx @@ -7,11 +7,12 @@ import { ModalFooter } from "ui/editor/ModalFooter"; import ModalSection from "ui/editor/ModalSection"; import ModalSectionContent from "ui/editor/ModalSectionContent"; import RichTextInput from "ui/editor/RichTextInput/RichTextInput"; +import ErrorWrapper from "ui/shared/ErrorWrapper"; import Input from "ui/shared/Input/Input"; import InputRow from "ui/shared/InputRow"; import { Switch } from "ui/shared/Switch"; -import { parseBaseNodeData } from "../../shared"; +import { Option, parseBaseNodeData } from "../../shared"; import { ICONS } from "../../shared/icons"; import type { Checklist } from "../model"; import { toggleExpandableChecklist } from "../model"; @@ -39,7 +40,7 @@ export const ChecklistEditor: React.FC = (props) => { : groupedOptions?.flatMap((group) => group.children); const filteredOptions = (sourceOptions || []).filter( - (option) => option.data.text, + (option) => option.data.text ); const processedOptions = filteredOptions.map((option) => ({ @@ -66,14 +67,22 @@ export const ChecklistEditor: React.FC = (props) => { }), }, }, - processedOptions, + processedOptions ); } else { alert(JSON.stringify({ type, ...values, options }, null, 2)); } }, - validate: ({ options, groupedOptions, ...values }) => { + validate: ({ options, groupedOptions, allRequired, ...values }) => { const errors: FormikErrors = {}; + + const exclusiveOptions: Option[] | undefined = options?.filter( + (option) => option.data.exclusive + ); + if (allRequired && exclusiveOptions && exclusiveOptions.length > 0) { + errors.allRequired = + 'Cannot configure exclusive "or" option alongside "all required" setting'; + } // Account for flat or expandable Checklist options options = options || groupedOptions?.map((group) => group.children)?.flat(); @@ -81,6 +90,10 @@ export const ChecklistEditor: React.FC = (props) => { errors.fn = "At least one option must set a data value when the checklist has a data field"; } + if (exclusiveOptions && exclusiveOptions.length > 1) { + errors.options = + "There should be a maximum of one exclusive option configured"; + } return errors; }, }); @@ -160,19 +173,20 @@ export const ChecklistEditor: React.FC = (props) => { onChange={() => formik.setFieldValue( "allRequired", - !formik.values.allRequired, + !formik.values.allRequired ) } label="All required" /> + formik.setFieldValue( "neverAutoAnswer", - !formik.values.neverAutoAnswer, + !formik.values.neverAutoAnswer ) } label="Always put to user (forgo automation)" @@ -180,8 +194,9 @@ export const ChecklistEditor: React.FC = (props) => { - - + + + diff --git a/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx b/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx index 7aa2c9a50b..c5fa9ee02b 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx @@ -12,6 +12,7 @@ import React from "react"; import { FormikHookReturn } from "types"; import ListManager from "ui/editor/ListManager/ListManager"; import ModalSectionContent from "ui/editor/ModalSectionContent"; +import ErrorWrapper from "ui/shared/ErrorWrapper"; import Input from "ui/shared/Input/Input"; import InputRow from "ui/shared/InputRow"; @@ -164,32 +165,34 @@ export const Options: React.FC<{ formik: FormikHookReturn }> = ({ formik }) => { )} {exclusiveOrOptionManagerShouldRender ? ( - { - const newCombinedOptions = [ - ...nonExclusiveOptions, - ...newExclusiveOptions, - ]; - formik.setFieldValue("options", newCombinedOptions); - }} - newValueLabel='add "or" option' - maxItems={1} - disableDragAndDrop - newValue={() => - ({ - data: { - text: "", - description: "", - val: "", - exclusive: true, - }, - }) as Option - } - Editor={BaseOptionsEditor} - editorExtraProps={{ showValueField: !!formik.values.fn }} - /> - + + { + const newCombinedOptions = [ + ...nonExclusiveOptions, + ...newExclusiveOptions, + ]; + formik.setFieldValue("options", newCombinedOptions); + }} + newValueLabel='add "or" option' + maxItems={1} + disableDragAndDrop + newValue={() => + ({ + data: { + text: "", + description: "", + val: "", + exclusive: true, + }, + }) as Option + } + Editor={BaseOptionsEditor} + editorExtraProps={{ showValueField: !!formik.values.fn }} + /> + + ) : ( <> )} diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/helpers.ts b/editor.planx.uk/src/@planx/components/Checklist/Public/helpers.ts index d057c281a3..986465fa46 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/helpers.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/helpers.ts @@ -53,7 +53,10 @@ export const toggleNonExclusiveCheckbox = ( thisCheckboxId, currentlyCheckedOptionIds ); - return newCheckedOptionIds.filter( - (id: string) => exclusiveOrOption && id !== exclusiveOrOption.id - ); + if (exclusiveOrOption) { + return newCheckedOptionIds.filter( + (id: string) => exclusiveOrOption && id !== exclusiveOrOption.id + ); + } + return newCheckedOptionIds; };