Skip to content

Commit

Permalink
chore: update Confirmation banner description to use rich text & rewo…
Browse files Browse the repository at this point in the history
…rd details (#3545)
  • Loading branch information
jessicamcinchak authored Aug 22, 2024
1 parent 259b74f commit c9d5939
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import React from "react";

import Wrapper from "../fixtures/Wrapper";
import Editor from "./Editor";
import Confirmation from "./Public";
import Confirmation, { Presentational } from "./Public";

const meta = {
title: "PlanX Components/Confirmation",
component: Confirmation,
} satisfies Meta<typeof Confirmation>;
component: Presentational,
} satisfies Meta<typeof Presentational>;

export default meta;

Expand All @@ -20,7 +20,8 @@ export const Basic = {
description: `A payment receipt has been emailed to you. You will also
receive an email to confirm when your application has been received.`,
color: { background: "rgba(1, 99, 96, 0.1)", text: "#000" },
details: {
sessionId: "123-t3st-456",
applicableDetails: {
"Planning Application Reference": "LBL–LDCP-2138261",
"Property Address": "45, Greenfield Road, London SE22 7FF",
"Application type":
Expand Down Expand Up @@ -48,6 +49,7 @@ export const Basic = {
<br/><br/>
What did you think of this service? Please give us your feedback using the link in the footer below.
`,
data: [],
},
} satisfies Story;

Expand Down
12 changes: 8 additions & 4 deletions editor.planx.uk/src/@planx/components/Confirmation/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Confirmation, parseNextSteps, Step } from "./model";

export type Props = EditorProps<TYPES.Confirmation, Confirmation>;

function StepEditor(props: ListManagerEditorProps<Step>) {
function NextStepEditor(props: ListManagerEditorProps<Step>) {
return (
<Box width="100%">
<InputRow>
Expand Down Expand Up @@ -55,10 +55,14 @@ export default function ConfirmationEditor(props: Props) {
const type = TYPES.Confirmation;
const formik = useFormik({
initialValues: {
color: props.node?.color || {
text: "#000",
background: "rgba(1, 99, 96, 0.1)",
},
heading: props.node?.data?.heading || "Application sent",
description:
props.node?.data?.description ||
`A payment receipt has been emailed to you. You will also receive an email to confirm when your application has been received.`,
`<p>A payment receipt has been emailed to you. You will also receive an email to confirm when your application has been received.</p>`,
moreInfo:
props.node?.data?.moreInfo ||
`<h2>You will be contacted</h2>
Expand Down Expand Up @@ -95,7 +99,7 @@ export default function ConfirmationEditor(props: Props) {
/>
</InputRow>
<InputRow>
<Input
<RichTextInput
placeholder="Description"
name="description"
value={formik.values.description}
Expand All @@ -112,7 +116,7 @@ export default function ConfirmationEditor(props: Props) {
onChange={(steps: Step[]) => {
formik.setFieldValue("nextSteps", steps);
}}
Editor={StepEditor}
Editor={NextStepEditor}
newValue={() => ({ title: "", description: "" })}
/>
</ModalSectionContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ jest.mock("@opensystemslab/planx-core", () => {
it("should not have any accessibility violations", async () => {
const { container } = setup(
<ConfirmationComponent
color={{ text: "#000", background: "rgba(1, 99, 96, 0.1)" }}
heading="heading"
description="description"
details={{ key1: "something", key2: "something else" }}
nextSteps={[
{ title: "title1", description: "description1" },
{ title: "title2", description: "description2" },
Expand Down
112 changes: 81 additions & 31 deletions editor.planx.uk/src/@planx/components/Confirmation/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { QuestionAndResponses } from "@opensystemslab/planx-core/types";
import Card from "@planx/components/shared/Preview/Card";
import { SummaryListTable } from "@planx/components/shared/Preview/SummaryList";
import { PublicProps } from "@planx/components/ui";
import { useStore } from "pages/FlowEditor/lib/store";
import { objectWithoutNullishValues } from "lib/objectHelpers";
import { Store, useStore } from "pages/FlowEditor/lib/store";
import React, { useEffect, useState } from "react";
import Banner from "ui/public/Banner";
import FileDownload from "ui/public/FileDownload";
Expand All @@ -19,11 +20,38 @@ export type Props = PublicProps<Confirmation>;
export default function ConfirmationComponent(props: Props) {
const [data, setData] = useState<QuestionAndResponses[]>([]);

const [sessionId, saveToEmail, $public] = useStore((state) => [
state.sessionId,
state.saveToEmail,
state.$public,
]);
const [sessionId, saveToEmail, $public, passport, govUkPayment, flowName] =
useStore((state) => [
state.sessionId,
state.saveToEmail,
state.$public,
state.computePassport(),
state.govUkPayment,
state.flowName,
]);

const details = {
"Application reference": sessionId,
"Property address": passport.data?._address?.title,
"Application type": [
flowName.replace("Apply", "Application"),
getWorkStatus(passport),
]
.filter(Boolean)
.join(" - "),
"GOV.UK payment reference": govUkPayment?.payment_id,
"Paid at":
govUkPayment?.created_date &&
new Date(govUkPayment.created_date).toLocaleDateString("en-gb", {
day: "numeric",
month: "long",
year: "numeric",
}),
};
const applicableDetails = objectWithoutNullishValues(details) as Record<
string,
string
>;

useEffect(() => {
const makeCsvData = async () => {
Expand All @@ -40,6 +68,23 @@ export default function ConfirmationComponent(props: Props) {
}
});

return (
<Presentational
{...props}
applicableDetails={applicableDetails}
data={data}
sessionId={sessionId}
/>
);
}

interface PresentationalProps extends Props {
sessionId: string;
applicableDetails: Record<string, string>;
data: QuestionAndResponses[];
}

export function Presentational(props: PresentationalProps) {
return (
<Box width="100%">
<Banner
Expand All @@ -49,25 +94,24 @@ export default function ConfirmationComponent(props: Props) {
iconTitle={"Success"}
>
{props.description && (
<Box mt={4}>
<Typography maxWidth="formWrap">{props.description}</Typography>
<Box mt={2} maxWidth="formWrap">
<ReactMarkdownOrHtml source={props.description} openLinksOnNewTab />
</Box>
)}
</Banner>
<Card>
{props.details && (
<SummaryListTable>
{Object.entries(props.details).map((item) => (
<>
<Box component="dt">{item[0]}</Box>
<Box component="dd">{item[1]}</Box>
</>
))}
</SummaryListTable>
)}

{<FileDownload data={data} filename={sessionId || "application"} />}

<SummaryListTable>
{Object.entries(props.applicableDetails).map(([k, v], i) => (
<React.Fragment key={`detail-${i}`}>
<Box component="dt">{k}</Box>
<Box component="dd">{v}</Box>
</React.Fragment>
))}
</SummaryListTable>
<FileDownload
data={props.data}
filename={props.sessionId || "application"}
/>
{props.nextSteps && Boolean(props.nextSteps?.length) && (
<Box pt={3}>
<Typography variant="h2" mb={2}>
Expand All @@ -76,7 +120,6 @@ export default function ConfirmationComponent(props: Props) {
<NumberedList items={props.nextSteps} heading="h2" />
</Box>
)}

{props.moreInfo && (
<>
<Box py={1}>
Expand All @@ -85,18 +128,25 @@ export default function ConfirmationComponent(props: Props) {
<hr />
</>
)}

{props.contactInfo && (
<>
<Box py={1}>
<Typography variant="h2" component="h3" gutterBottom>
Contact us
</Typography>
<ReactMarkdownOrHtml source={props.contactInfo} />
</Box>
</>
<Box py={1}>
<Typography variant="h2" component="h3" gutterBottom>
Contact us
</Typography>
<ReactMarkdownOrHtml source={props.contactInfo} openLinksOnNewTab />
</Box>
)}
</Card>
</Box>
);
}

// TODO - Retire in favor of ODP Schema application type descriptions or fallback to flowName
function getWorkStatus(passport: Store.passport): string | undefined {
switch (passport?.data?.["application.type"]?.toString()) {
case "ldc.existing":
return "existing";
case "ldc.proposed":
return "proposed";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export interface Confirmation {
heading?: string;
description?: string;
color?: { text: string; background: string };
details?: { [key: string]: string };
nextSteps?: Step[];
moreInfo?: string;
contactInfo?: string;
Expand Down
56 changes: 7 additions & 49 deletions editor.planx.uk/src/pages/Preview/Node.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {
ComponentType as TYPES,
DEFAULT_FLAG_CATEGORY,
GOV_PAY_PASSPORT_KEY,
GovUKPayment,
} from "@opensystemslab/planx-core/types";
import { ComponentType as TYPES } from "@opensystemslab/planx-core/types";
import AddressInput from "@planx/components/AddressInput/Public";
import Calculate from "@planx/components/Calculate/Public";
import Checklist from "@planx/components/Checklist/Public";
Expand Down Expand Up @@ -31,7 +29,6 @@ import Send from "@planx/components/Send/Public";
import SetValue from "@planx/components/SetValue/Public";
import TaskList from "@planx/components/TaskList/Public";
import TextInput from "@planx/components/TextInput/Public";
import { objectWithoutNullishValues } from "lib/objectHelpers";
import mapAccum from "ramda/src/mapAccum";
import React from "react";

Expand Down Expand Up @@ -87,6 +84,7 @@ const Node: React.FC<any> = (props: Props) => {
switch (props.node.type) {
case TYPES.Calculate:
return <Calculate {...allProps} />;

case TYPES.Checklist: {
const childNodes = childNodesOf(props.node.id);
return (
Expand Down Expand Up @@ -114,43 +112,10 @@ const Node: React.FC<any> = (props: Props) => {
/>
);
}
case TYPES.Confirmation: {
const payment: GovUKPayment | undefined =
passport.data?.[GOV_PAY_PASSPORT_KEY];

const details = {
"Planning application reference": payment?.reference ?? sessionId,

"Property address": passport.data?._address?.title,

"Application type": [
flowName.replace("Apply", "Application"),
getWorkStatus(passport),
]
.filter(Boolean)
.join(" - "),

// XXX: If there is no payment we can't alternatively show Date.now() because it
// will change after page refresh. BOPS submission time needs to be queryable.
Submitted: payment?.created_date
? new Date(payment.created_date).toLocaleDateString("en-gb", {
day: "numeric",
month: "long",
year: "numeric",
})
: undefined,

"GOV.UK Payment reference": payment?.payment_id,
};

return (
<Confirmation
{...allProps}
details={objectWithoutNullishValues(details)}
color={{ text: "#000", background: "rgba(1, 99, 96, 0.1)" }}
/>
);
}
case TYPES.Confirmation:
return <Confirmation {...allProps} />;

case TYPES.Content:
return <Content {...allProps} />;

Expand Down Expand Up @@ -209,6 +174,7 @@ const Node: React.FC<any> = (props: Props) => {
/>
);
}

case TYPES.Review:
return <Review {...allProps} />;

Expand Down Expand Up @@ -267,6 +233,7 @@ const Node: React.FC<any> = (props: Props) => {
case TYPES.Answer:
case undefined:
return null;

default:
console.error({ nodeNotFound: props });
return exhaustiveCheck(props.node.type);
Expand All @@ -277,13 +244,4 @@ function exhaustiveCheck(type: never): never {
throw new Error(`Missing type ${type}`);
}

function getWorkStatus(passport: Store.passport): string | undefined {
switch (passport?.data?.["application.type"]?.toString()) {
case "ldc.existing":
return "existing";
case "ldc.proposed":
return "proposed";
}
}

export default Node;

0 comments on commit c9d5939

Please sign in to comment.