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:
@@ -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} />,
|
||||
};
|
||||
152
src/components/pages/ConfirmationStep/ConfirmationStep.tsx
Normal file
152
src/components/pages/ConfirmationStep/ConfirmationStep.tsx
Normal 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'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;
|
||||
2
src/components/pages/ConfirmationStep/index.ts
Normal file
2
src/components/pages/ConfirmationStep/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { ConfirmationStep, default } from './ConfirmationStep';
|
||||
export type { ConfirmationStepProps, ConfirmationLink } from './ConfirmationStep';
|
||||
Reference in New Issue
Block a user