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 49c592a064..067ed1e3e4 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/Editor.tsx @@ -31,6 +31,7 @@ export const ChecklistComponent: React.FC = (props) => { img: props.node?.data?.img || "", options: props.options, text: props.node?.data?.text || "", + exclusiveOrOption: props.exclusiveOrOption || undefined, ...parseBaseNodeData(props.node?.data), }, onSubmit: ({ options, groupedOptions, ...values }) => { 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 388c021dac..e0acc53085 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Editor/Options.tsx @@ -2,6 +2,7 @@ import Delete from "@mui/icons-material/Delete"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import IconButton from "@mui/material/IconButton"; +import MenuItem from "@mui/material/MenuItem"; import adjust from "ramda/src/adjust"; import compose from "ramda/src/compose"; import remove from "ramda/src/remove"; @@ -9,8 +10,11 @@ import React from "react"; import { FormikHookReturn } from "types"; import ListManager from "ui/editor/ListManager/ListManager"; import ModalSectionContent from "ui/editor/ModalSectionContent"; +import SelectInput from "ui/editor/SelectInput/SelectInput"; import Input from "ui/shared/Input/Input"; import InputRow from "ui/shared/InputRow"; +import InputRowItem from "ui/shared/InputRowItem"; +import InputRowLabel from "ui/shared/InputRowLabel"; import { Option } from "../../shared"; import type { Group } from "../model"; @@ -146,6 +150,33 @@ export const Options: React.FC<{ formik: FormikHookReturn }> = ({ formik }) => { editorExtraProps={{ showValueField: !!formik.values.fn }} /> )} + {/* TODO: only show if more than one option */} + {formik.values.options && ( + + + Exclusive or option + + { + formik.setFieldValue("exclusiveOrOption", e.target.value); + // TODO: make it take effect + }} + value={formik.values.exclusiveOrOption || ""} + > + {formik.values?.options?.map((option: Option) => { + const optionTitle = option?.data?.text; + return ( + + {optionTitle} + + ); + })} + + + + + )} ); }; diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx index 23d9bdd2e4..d823065ef8 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx @@ -62,6 +62,7 @@ const VisibleChecklist: React.FC = (props) => { img, previouslySubmittedData, id, + exclusiveOrOption, } = props; const formik = useFormik<{ checked: Array }>({ diff --git a/editor.planx.uk/src/@planx/components/Checklist/model.ts b/editor.planx.uk/src/@planx/components/Checklist/model.ts index 1ac40a10ee..09f169cf59 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/model.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/model.ts @@ -23,6 +23,7 @@ export interface Checklist extends BaseNodeData { allRequired?: boolean; categories?: Array; neverAutoAnswer?: boolean; + exclusiveOrOption?: string; } interface ChecklistExpandableProps { @@ -102,8 +103,11 @@ export const checklistValidationSchema = ({ allRequired, options, groupedOptions, -}: Checklist) => - array() + exclusiveOrOption, +}: Checklist) => { + const flatOptions = getFlatOptions({ options, groupedOptions }); + + return array() .required() .test({ name: "atLeastOneChecked", @@ -119,8 +123,27 @@ export const checklistValidationSchema = ({ if (!allRequired) { return true; } - const flatOptions = getFlatOptions({ options, groupedOptions }); const allChecked = checked && checked.length === flatOptions.length; return Boolean(allChecked); }, + }) + .test({ + name: "notExclusiveOrSelection", + message: `Cannot select "${exclusiveOrOption}" alongside other options`, + // TODO: something more like 'Select countries you will be travelling to, or select ‘No, I will not be travelling to any of these countries’ + test: (checked?: Array) => { + const multipleSelectedOptionsIncludesExclusiveOr = + exclusiveOrOption && + flatOptions.some((option) => { + const optionHasBeenPicked = checked?.includes(option.id); + return ( + checked && + optionHasBeenPicked && + checked.length > 1 && + option.data.text === exclusiveOrOption + ); + }); + return !multipleSelectedOptionsIncludesExclusiveOr; + }, }); +}; diff --git a/editor.planx.uk/src/@planx/components/Checklist/types.ts b/editor.planx.uk/src/@planx/components/Checklist/types.ts index 76ef9d47bd..920eee7d4d 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/types.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/types.ts @@ -14,6 +14,7 @@ export interface ChecklistProps extends Checklist { fn?: string; img?: string; text: string; + exclusiveOrOption?: Option; } & BaseNodeData; }; }