Add SummaryStep, PaymentStep, ConfirmationStep (wizard steps 13-15)

SummaryStep (step 13):
- Accordion sections with edit IconButtons linking back to each step
- dl/dt/dd definition list for label-value pairs
- Total bar with prominent price display (aria-live)
- Share plan icon button, deposit display
- Pre-planning: "Save your plan" CTA; at-need: "Confirm" CTA

PaymentStep (step 14):
- Payment plan (full/deposit) shown before method (amount before how)
- ToggleButtonGroup for plan + method selection
- Card: PayWay iframe slot with placeholder; Bank: account details display
- Terms checkbox with service agreement + privacy links
- Security reassurance (lock icon, no-surprise copy)

ConfirmationStep (step 15):
- Terminal page — no back button, no progress indicator
- At-need: "submitted" + callback timeframe + arranger contact
- Pre-planning: "saved" + return-anytime + family-ready copy
- Muted success icon (not celebratory), next-steps link buttons
- VenueCard selected prop also staged (from step 7 work)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 15:08:41 +11:00
parent 77bac1478f
commit 36757bcdb0
9 changed files with 1182 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
import type { Meta, StoryObj } from '@storybook/react';
import { ConfirmationStep } from './ConfirmationStep';
import { Navigation } from '../../organisms/Navigation';
import Box from '@mui/material/Box';
// ─── Helpers ─────────────────────────────────────────────────────────────────
const FALogo = () => (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Box
component="img"
src="/brandlogo/logo-full.svg"
alt="Funeral Arranger"
sx={{ height: 28, display: { xs: 'none', md: 'block' } }}
/>
<Box
component="img"
src="/brandlogo/logo-short.svg"
alt="Funeral Arranger"
sx={{ height: 28, display: { xs: 'block', md: 'none' } }}
/>
</Box>
);
const nav = (
<Navigation
logo={<FALogo />}
items={[
{ label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' },
]}
/>
);
// ─── Meta ────────────────────────────────────────────────────────────────────
const meta: Meta<typeof ConfirmationStep> = {
title: 'Pages/ConfirmationStep',
component: ConfirmationStep,
tags: ['autodocs'],
parameters: {
layout: 'fullscreen',
},
};
export default meta;
type Story = StoryObj<typeof ConfirmationStep>;
// ─── At-need (default) ──────────────────────────────────────────────────────
/** At-need confirmation — arranger will call */
export const Default: Story = {
render: () => (
<ConfirmationStep
email="jane.smith@example.com"
phone="0412 345 678"
callbackTimeframe="within 2 hours"
onViewPlan={() => alert('View plan')}
nextSteps={[
{ label: 'Start detailed arrangement', onClick: () => alert('Arrangement') },
{ label: 'Go to dashboard', onClick: () => alert('Dashboard') },
]}
navigation={nav}
/>
),
};
// ─── Pre-planning ───────────────────────────────────────────────────────────
/** Pre-planning confirmation — plan saved, return anytime */
export const PrePlanning: Story = {
render: () => (
<ConfirmationStep
isPrePlanning
email="jane.smith@example.com"
onViewPlan={() => alert('View plan')}
nextSteps={[{ label: 'Go to dashboard', onClick: () => alert('Dashboard') }]}
navigation={nav}
/>
),
};
// ─── Minimal ────────────────────────────────────────────────────────────────
/** Minimal — no next steps, no view plan */
export const Minimal: Story = {
render: () => <ConfirmationStep email="jane.smith@example.com" navigation={nav} />,
};

View File

@@ -0,0 +1,152 @@
import React from 'react';
import Box from '@mui/material/Box';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import type { SxProps, Theme } from '@mui/material/styles';
import { WizardLayout } from '../../templates/WizardLayout';
import { Typography } from '../../atoms/Typography';
import { Button } from '../../atoms/Button';
// ─── Types ───────────────────────────────────────────────────────────────────
/** Next step link shown on the confirmation page */
export interface ConfirmationLink {
label: string;
href?: string;
onClick?: () => void;
}
/** Props for the ConfirmationStep page component */
export interface ConfirmationStepProps {
/** Whether this is a pre-planning flow (different copy) */
isPrePlanning?: boolean;
/** User's email address (shown in confirmation text) */
email?: string;
/** User's phone number (shown in at-need confirmation) */
phone?: string;
/** Expected callback timeframe (at-need) */
callbackTimeframe?: string;
/** Navigation links to next steps */
nextSteps?: ConfirmationLink[];
/** Callback for "View your plan" */
onViewPlan?: () => void;
/** Navigation bar */
navigation?: React.ReactNode;
/** Hide the help bar */
hideHelpBar?: boolean;
/** MUI sx prop */
sx?: SxProps<Theme>;
}
// ─── Component ───────────────────────────────────────────────────────────────
/**
* Step 15 — Confirmation / Plan View for the FA arrangement wizard.
*
* Terminal confirmation page. Different copy for at-need vs pre-planning.
* Confirming and orienting — not celebratory.
*
* At-need: "Your arrangement has been submitted" + callback info
* Pre-planning: "Your plan has been saved" + return-anytime info
*
* No progress indicator. No back button. Links to post-plan flows.
*
* Pure presentation component — props in, callbacks out.
*
* Spec: documentation/steps/steps/15_view.yaml
*/
export const ConfirmationStep: React.FC<ConfirmationStepProps> = ({
isPrePlanning = false,
email,
phone,
callbackTimeframe = 'within 2 hours',
nextSteps = [],
onViewPlan,
navigation,
hideHelpBar,
sx,
}) => {
return (
<WizardLayout variant="centered-form" navigation={navigation} hideHelpBar={hideHelpBar} sx={sx}>
<Box sx={{ textAlign: 'center', py: 4 }}>
{/* Success icon — muted, not celebratory */}
<CheckCircleOutlineIcon
sx={{
fontSize: 64,
color: 'var(--fa-color-brand-500)',
mb: 3,
opacity: 0.8,
}}
aria-hidden
/>
{/* Heading */}
<Typography variant="display3" component="h1" sx={{ mb: 2 }} tabIndex={-1}>
{isPrePlanning ? 'Your plan has been saved' : 'Your arrangement has been submitted'}
</Typography>
{/* Body text */}
{isPrePlanning ? (
<Box sx={{ maxWidth: 480, mx: 'auto', mb: 4 }}>
<Typography variant="body1" color="text.secondary">
You can return and update it anytime.
{email && ` We've sent a copy to ${email}.`}
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mt: 2 }}>
When the time comes, your family can contact us and we&apos;ll have everything ready.
</Typography>
</Box>
) : (
<Box sx={{ maxWidth: 480, mx: 'auto', mb: 4 }}>
<Typography variant="body1" color="text.secondary">
A funeral arranger will call you
{phone && ` on ${phone}`} {callbackTimeframe} to confirm the details.
{email && ` A confirmation has been sent to ${email}.`}
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mt: 2 }}>
If you need to make changes before then, call us on{' '}
<Box
component="a"
href="tel:1300000000"
sx={{
color: 'var(--fa-color-text-brand)',
textDecoration: 'underline',
fontSize: 'inherit',
}}
>
1300 000 000
</Box>
.
</Typography>
</Box>
)}
{/* View plan CTA */}
{onViewPlan && (
<Button variant="contained" size="large" onClick={onViewPlan} sx={{ mb: 4 }}>
View your plan
</Button>
)}
{/* Next steps */}
{nextSteps.length > 0 && (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, alignItems: 'center' }}>
{nextSteps.map((link) => (
<Button
key={link.label}
variant="text"
color="secondary"
onClick={link.onClick}
href={link.href}
>
{link.label}
</Button>
))}
</Box>
)}
</Box>
</WizardLayout>
);
};
ConfirmationStep.displayName = 'ConfirmationStep';
export default ConfirmationStep;

View File

@@ -0,0 +1,2 @@
export { ConfirmationStep, default } from './ConfirmationStep';
export type { ConfirmationStepProps, ConfirmationLink } from './ConfirmationStep';