From f15193c1cf18ef595d1dc178cec0573bf41fe4d4 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Wed, 1 Mar 2023 09:26:16 +0100 Subject: [PATCH] feat: sections overview page with dynamic status tags (#1491) --- .../src/@planx/components/Section/Public.tsx | 130 +++++++++++++++++- .../pages/FlowEditor/lib/store/navigation.ts | 13 +- 2 files changed, 130 insertions(+), 13 deletions(-) diff --git a/editor.planx.uk/src/@planx/components/Section/Public.tsx b/editor.planx.uk/src/@planx/components/Section/Public.tsx index 122da0971f..a2bb77ec9e 100644 --- a/editor.planx.uk/src/@planx/components/Section/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Section/Public.tsx @@ -1,16 +1,136 @@ +import Box from "@mui/material/Box"; +import { styled } from "@mui/material/styles"; +import Typography from "@mui/material/Typography"; import type { PublicProps } from "@planx/components/ui"; -import { useEffect } from "react"; +import { hasFeatureFlag } from "lib/featureFlags"; +import { useStore } from "pages/FlowEditor/lib/store"; +import React, { useEffect } from "react"; +import Card from "../shared/Preview/Card"; +import QuestionHeader from "../shared/Preview/QuestionHeader"; import type { Section } from "./model"; export type Props = PublicProps
; +enum SectionStatus { + NotStarted = "CANNOT START YET", + ReadyToStart = "READY TO START", + Completed = "COMPLETED", + NeedsUpdated = "NEEDS UPDATED", // future reconciliation scenario, not used yet +} + export default function Component(props: Props) { + const showSection = hasFeatureFlag("NAVIGATION_UI"); + + const [ + flowName, + currentSectionIndex, + sectionCount, + sectionNodes, + currentCard, + upcomingCardIds, + ] = useStore((state) => [ + state.flowName, + state.currentSectionIndex, + state.sectionCount, + state.sectionNodes, + state.currentCard(), + state.upcomingCardIds(), + ]); + useEffect(() => { - props.handleSubmit?.({ - auto: true, // hides this node when navigating through cards in a flow - }); + // if the feature flag is toggled off, hide this node (by auto-answering it) when navigating through a flow + !showSection && + props.handleSubmit?.({ + auto: true, + }); }, []); - return null; + const getStatus = ( + sectionId: string, + currentCardId: string | undefined, + upcomingCardIds: string[] | undefined + ): SectionStatus => { + if (currentCardId === sectionId) { + return SectionStatus.ReadyToStart; + } else if (upcomingCardIds?.includes(sectionId)) { + return SectionStatus.NotStarted; + } else { + return SectionStatus.Completed; + } + }; + + return !showSection ? null : ( + + + + + Application incomplete. + + + {`You have completed ${ + Object.keys(sectionNodes)[0] === currentCard?.id + ? 0 + : currentSectionIndex + } of ${sectionCount} sections`} + + + + {Object.entries(sectionNodes).map(([sectionId, sectionNode]) => ( + +
{sectionNode.data.title}
+
+ + {getStatus(sectionId, currentCard?.id, upcomingCardIds)} + +
+
+ ))} +
+
+ ); } + +const Tag = styled("div")(({ theme }) => ({ + backgroundColor: "lightgrey", + paddingTop: theme.spacing(0.5), + paddingBottom: theme.spacing(0.5), + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), +})); + +const Grid = styled("dl")(({ theme }) => ({ + display: "grid", + gridTemplateColumns: "1fr 175px", + gridRowGap: "5px", + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + "& > *": { + borderBottom: "1px solid grey", + paddingBottom: theme.spacing(2), + paddingTop: theme.spacing(2), + verticalAlign: "top", + margin: 0, + }, + "& ul": { + listStylePosition: "inside", + padding: 0, + margin: 0, + }, + "& dt": { + // left column + fontWeight: 500, + }, + "& dd:nth-of-type(1n)": { + // right column + textAlign: "center", + }, +})); + +interface DescriptionListProps { + children: React.ReactNode; +} + +const DescriptionList: React.FC = ({ children }) => { + return {children}; +}; diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts index 8ca2dd1702..f4a554dbce 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/navigation.ts @@ -73,15 +73,12 @@ export const navigationStore: StateCreator< const breadcrumbIds = Object.keys(breadcrumbs); const sectionIds = Object.keys(sectionNodes); - const mostRecentSectionId = findLast( - breadcrumbIds, - (breadcrumbId: string) => sectionIds.includes(breadcrumbId) - ); - // This should not happen - if we have sections, we should have a most recent section - // Failing noisily for now will help identify issues whilst this is being developed & tested - // TODO: Fail more gracefully once feature is complete - if (!mostRecentSectionId) throw Error("Error finding mostRecentSectionId"); + // Fallback to the first sectionId, which allows us to have a mostRecentSectionId on the first node ("Card") before it exists in breadcrumbs (eg "Continue" hasn't been clicked yet) + const mostRecentSectionId = + findLast(breadcrumbIds, (breadcrumbId: string) => + sectionIds.includes(breadcrumbId) + ) || sectionIds[0]; // Update section const currentSectionTitle = sectionNodes[mostRecentSectionId].data.title;