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 fa60443d44..73710bb574 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/Public.tsx @@ -1,28 +1,153 @@ -import { useStore } from "pages/FlowEditor/lib/store"; -import React from "react"; +import Grid from "@mui/material/Grid"; +import { visuallyHidden } from "@mui/utils"; +import { + ChecklistLayout, + checklistValidationSchema, +} from "@planx/components/Checklist/model"; +import Card from "@planx/components/shared/Preview/Card"; +import { CardHeader } from "@planx/components/shared/Preview/CardHeader/CardHeader"; +import { getIn, useFormik } from "formik"; +import { partition } from "lodash"; +import React, { useEffect } from "react"; +import FullWidthWrapper from "ui/public/FullWidthWrapper"; +import ErrorWrapper from "ui/shared/ErrorWrapper"; +import { object } from "yup"; +import { Option } from "../../shared"; import { Props } from "../types"; -import { AutoAnsweredChecklist } from "./components/AutoAnsweredChecklist"; -import { VisibleChecklist } from "./components/VisibleChecklist"; +import { ChecklistItems } from "./components/ChecklistItems"; +import { ExclusiveChecklistItem } from "./components/ExclusiveChecklistItem"; +import { GroupedChecklistOptions } from "./components/GroupedChecklistOptions"; +import { toggleNonExclusiveCheckbox } from "./helpers"; +import { useExclusiveOption } from "./hooks/useExclusiveOption"; +import { useSortedOptions } from "./hooks/useSortedOptions"; const ChecklistComponent: React.FC = (props) => { - const autoAnswerableOptions = useStore( - (state) => state.autoAnswerableOptions + const { + description = "", + groupedOptions, + handleSubmit, + howMeasured, + info, + options, + policyRef, + text, + img, + previouslySubmittedData, + id, + autoAnswers, + } = props; + + const formik = useFormik<{ checked: Array }>({ + initialValues: { + checked: previouslySubmittedData?.answers || [], + }, + onSubmit: (values) => { + handleSubmit?.({ answers: values.checked }); + }, + validateOnBlur: false, + validateOnChange: false, + validationSchema: object({ + checked: checklistValidationSchema(props), + }), + }); + + const { setCheckedFieldValue, layout } = useSortedOptions( + options, + groupedOptions, + formik, ); - if (props.neverAutoAnswer) { - return ; - } + const [exclusiveOptions, nonExclusiveOptions]: Option[][] = partition( + options, + (option) => option.data.exclusive, + ); + + const { + exclusiveOrOption, + exclusiveOptionIsChecked, + toggleExclusiveCheckbox, + } = useExclusiveOption(exclusiveOptions, formik); - let idsThatCanBeAutoAnswered: string[] | undefined; - if (props.id) idsThatCanBeAutoAnswered = autoAnswerableOptions(props.id); - if (idsThatCanBeAutoAnswered) { - return ( - + const changeCheckbox = (id: string) => () => { + const currentCheckedIds = formik.values.checked; + + const currentCheckboxIsExclusiveOption = + exclusiveOrOption && id === exclusiveOrOption.id; + + if (currentCheckboxIsExclusiveOption) { + const newCheckedIds = toggleExclusiveCheckbox(id); + setCheckedFieldValue(newCheckedIds); + return; + } + const newCheckedIds = toggleNonExclusiveCheckbox( + id, + currentCheckedIds, + exclusiveOrOption, ); + setCheckedFieldValue(newCheckedIds); + }; + + // Auto-answered Checklists still set a breadcrumb even though they render null + useEffect(() => { + if (autoAnswers) { + handleSubmit?.({ + answers: autoAnswers, + auto: true, + }); + } + }, [autoAnswers]); + + // Auto-answered Checklists are not publicly visible + if (autoAnswers) { + return null; } - return ; + return ( + + + + + + {text} + + {exclusiveOrOption && ( + + )} + {groupedOptions && ( + + )} + + + + + ); }; export default ChecklistComponent; diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/components/AutoAnsweredChecklist.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/components/AutoAnsweredChecklist.tsx deleted file mode 100644 index bca1b81cc4..0000000000 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/components/AutoAnsweredChecklist.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React, { useEffect } from "react"; - -import { Props } from "../../types"; - -// An auto-answered Checklist won't be seen by the user, but still leaves a breadcrumb -export const AutoAnsweredChecklist: React.FC< - Props & { answerIds: string[] } -> = (props) => { - useEffect(() => { - props.handleSubmit?.({ - answers: props.answerIds, - auto: true, - }); - }, [props]); - - return null; -}; diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/components/ChecklistItems.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/components/ChecklistItems.tsx index 16f676ea8e..1ebbd7675a 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/components/ChecklistItems.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/components/ChecklistItems.tsx @@ -6,7 +6,7 @@ import React from "react"; import FormWrapper from "ui/public/FormWrapper"; import ChecklistItem from "ui/shared/ChecklistItem/ChecklistItem"; -import { ChecklistLayout } from "./VisibleChecklist"; +import { ChecklistLayout } from "../../model"; interface Props { nonExclusiveOptions: Option[]; @@ -50,7 +50,7 @@ export const ChecklistItems = ({ checkbox /> - ) + ), )} ); diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/components/VisibleChecklist.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/components/VisibleChecklist.tsx deleted file mode 100644 index a2d730a1f5..0000000000 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/components/VisibleChecklist.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import Grid from "@mui/material/Grid"; -import { visuallyHidden } from "@mui/utils"; -import { checklistValidationSchema } from "@planx/components/Checklist/model"; -import Card from "@planx/components/shared/Preview/Card"; -import { CardHeader } from "@planx/components/shared/Preview/CardHeader/CardHeader"; -import { getIn, useFormik } from "formik"; -import { partition } from "lodash"; -import React from "react"; -import FullWidthWrapper from "ui/public/FullWidthWrapper"; -import ErrorWrapper from "ui/shared/ErrorWrapper"; -import { object } from "yup"; - -import { Option } from "../../../shared"; -import { Props } from "../../types"; -import { useExclusiveOption } from "../hooks/useExclusiveOption"; -import { useSortedOptions } from "../hooks/useSortedOptions"; -import { ChecklistItems } from "./../components/ChecklistItems"; -import { ExclusiveChecklistItem } from "./../components/ExclusiveChecklistItem"; -import { toggleNonExclusiveCheckbox } from "./../helpers"; -import { GroupedChecklistOptions } from "./GroupedChecklistOptions"; - -export enum ChecklistLayout { - Basic, - Grouped, - Images, -} - -export const VisibleChecklist: React.FC = (props) => { - const { - description = "", - groupedOptions, - handleSubmit, - howMeasured, - info, - options, - policyRef, - text, - img, - previouslySubmittedData, - id, - } = props; - - const formik = useFormik<{ checked: Array }>({ - initialValues: { - checked: previouslySubmittedData?.answers || [], - }, - onSubmit: (values) => { - handleSubmit?.({ answers: values.checked }); - }, - validateOnBlur: false, - validateOnChange: false, - validationSchema: object({ - checked: checklistValidationSchema(props), - }), - }); - - const { setCheckedFieldValue, layout } = useSortedOptions( - options, - groupedOptions, - formik - ); - - const [exclusiveOptions, nonExclusiveOptions]: Option[][] = partition( - options, - (option) => option.data.exclusive - ); - - const { - exclusiveOrOption, - exclusiveOptionIsChecked, - toggleExclusiveCheckbox, - } = useExclusiveOption(exclusiveOptions, formik); - - const changeCheckbox = (id: string) => () => { - const currentCheckedIds = formik.values.checked; - - const currentCheckboxIsExclusiveOption = - exclusiveOrOption && id === exclusiveOrOption.id; - - if (currentCheckboxIsExclusiveOption) { - const newCheckedIds = toggleExclusiveCheckbox(id); - setCheckedFieldValue(newCheckedIds); - return; - } - const newCheckedIds = toggleNonExclusiveCheckbox( - id, - currentCheckedIds, - exclusiveOrOption - ); - setCheckedFieldValue(newCheckedIds); - }; - - return ( - - - - - - {text} - - {exclusiveOrOption && ( - - )} - {groupedOptions && ( - - )} - - - - - ); -}; diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx index 896dfe5d15..cc4a72156b 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/Public.test.tsx @@ -4,7 +4,7 @@ import { setup } from "testUtils"; import { vi } from "vitest"; import { axe } from "vitest-axe"; -import { ChecklistLayout } from "../components/VisibleChecklist"; +import { ChecklistLayout } from "../../model"; import Checklist from "../Public"; import { groupedOptions, options } from "./mockOptions"; import { pressContinue, pressOption } from "./testUtils"; @@ -20,7 +20,7 @@ describe("Checklist Component - Grouped Layout", () => { text="home type?" handleSubmit={handleSubmit} groupedOptions={groupedOptions} - /> + />, ); await user.click(screen.getByText("Section 1")); @@ -44,7 +44,7 @@ describe("Checklist Component - Grouped Layout", () => { handleSubmit={handleSubmit} previouslySubmittedData={{ answers: ["S1_Option1", "S3_Option1"] }} groupedOptions={groupedOptions} - /> + />, ); expect(screen.getByTestId("group-0-expanded")).toBeTruthy(); @@ -65,7 +65,7 @@ describe("Checklist Component - Grouped Layout", () => { description="" text="home type?" groupedOptions={groupedOptions} - /> + />, ); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -81,7 +81,7 @@ describe("Checklist Component - Grouped Layout", () => { text="home type?" handleSubmit={handleSubmit} groupedOptions={groupedOptions} - /> + />, ); const [section1Button, section2Button, section3Button] = screen.getAllByRole("button"); @@ -138,7 +138,7 @@ describe("Checklist Component - Basic & Images Layout", () => { text="home type?" handleSubmit={handleSubmit} options={options[type]} - /> + />, ); expect(screen.getByRole("heading")).toHaveTextContent("home type?"); @@ -166,7 +166,7 @@ describe("Checklist Component - Basic & Images Layout", () => { handleSubmit={handleSubmit} previouslySubmittedData={{ answers: ["flat_id", "house_id"] }} options={options[type]} - /> + />, ); await user.click(screen.getByTestId("continue-button")); @@ -183,7 +183,7 @@ describe("Checklist Component - Basic & Images Layout", () => { description="" text="home type?" options={options[type]} - /> + />, ); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -199,7 +199,7 @@ describe("Checklist Component - Basic & Images Layout", () => { text="home type?" handleSubmit={handleSubmit} options={options[type]} - /> + />, ); await user.tab(); diff --git a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/mockOptions.ts b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/mockOptions.ts index a5fc1a0074..e655712b6b 100644 --- a/editor.planx.uk/src/@planx/components/Checklist/Public/tests/mockOptions.ts +++ b/editor.planx.uk/src/@planx/components/Checklist/Public/tests/mockOptions.ts @@ -1,8 +1,6 @@ import { Option } from "@planx/components/shared"; -import { Group } from "../../model"; -import { ChecklistLayout } from "../components/VisibleChecklist"; - +import { ChecklistLayout, Group } from "../../model"; export const options: { [key in ChecklistLayout]?: Array