diff --git a/src/components/pages/PreviewStep/PreviewStep.stories.tsx b/src/components/pages/PreviewStep/PreviewStep.stories.tsx new file mode 100644 index 0000000..6c5f8fc --- /dev/null +++ b/src/components/pages/PreviewStep/PreviewStep.stories.tsx @@ -0,0 +1,163 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { PreviewStep } from './PreviewStep'; +import type { PreviewStepPackage, PreviewStepProvider } from './PreviewStep'; +import { Navigation } from '../../organisms/Navigation'; +import Box from '@mui/material/Box'; + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +const FALogo = () => ( + + + + +); + +const nav = ( + } + items={[ + { label: 'FAQ', href: '/faq' }, + { label: 'Contact Us', href: '/contact' }, + { label: 'Log in', href: '/login' }, + ]} + /> +); + +const mockProvider: PreviewStepProvider = { + name: 'H.Parsons Funeral Directors', + location: 'Wentworth, NSW', + imageUrl: 'https://placehold.co/120x80/E8E0D6/8B6F47?text=H.Parsons', + rating: 4.6, + reviewCount: 7, +}; + +const mockPackage: PreviewStepPackage = { + name: 'Everyday Funeral Package', + price: 2700, + sections: [ + { + heading: 'Essentials', + items: [ + { name: 'Accommodation', price: 500 }, + { name: 'Death registration certificate', price: 150 }, + { name: 'Doctor fee for Cremation', price: 150 }, + { name: 'NSW Government Levy - Cremation', price: 83 }, + { name: 'Professional Mortuary Care', price: 1200 }, + { name: 'Professional Service Fee', price: 1120 }, + ], + }, + { + heading: 'Complimentary Items', + items: [ + { name: 'Dressing Fee', price: 0 }, + { name: 'Viewing Fee', price: 0 }, + ], + }, + ], + total: 2700, + extras: { + heading: 'Extras', + items: [ + { name: 'Allowance for Flowers', price: 150, isAllowance: true }, + { name: 'Allowance for Master of Ceremonies', price: 500, isAllowance: true }, + { name: 'After Business Hours Service Surcharge', price: 150 }, + { name: 'Coffin Bearing by Funeral Directors', price: 1500 }, + ], + }, + terms: + 'This package includes a funeral service at a chapel or a church with a funeral procession. Pricing may vary based on additional selections.', +}; + +// ─── Meta ──────────────────────────────────────────────────────────────────── + +const meta: Meta = { + title: 'Pages/PreviewStep', + component: PreviewStep, + tags: ['autodocs'], + parameters: { + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +// ─── Default (at-need) ───────────────────────────────────────────────────── + +/** At-need flow — Continue CTA only, no explore option */ +export const Default: Story = { + args: { + provider: mockProvider, + selectedPackage: mockPackage, + navigation: nav, + onContinue: () => alert('Continue with this package'), + onBack: () => alert('Back'), + }, +}; + +// ─── Pre-planning ─────────────────────────────────────────────────────────── + +/** Pre-planning flow — shows "Explore other options" tertiary CTA */ +export const PrePlanning: Story = { + args: { + provider: mockProvider, + selectedPackage: mockPackage, + navigation: nav, + isPrePlanning: true, + onContinue: () => alert('Continue'), + onBack: () => alert('Back'), + onExplore: () => alert('Explore other options'), + }, +}; + +// ─── Loading ──────────────────────────────────────────────────────────────── + +/** Continue button in loading state */ +export const Loading: Story = { + args: { + provider: mockProvider, + selectedPackage: mockPackage, + navigation: nav, + loading: true, + onContinue: () => {}, + onBack: () => alert('Back'), + }, +}; + +// ─── Minimal package ──────────────────────────────────────────────────────── + +/** Basic package with fewer inclusions */ +export const MinimalPackage: Story = { + args: { + provider: mockProvider, + selectedPackage: { + name: 'Essential Cremation', + price: 1800, + sections: [ + { + heading: 'Essentials', + items: [ + { name: 'Death registration certificate', price: 150 }, + { name: 'Professional Mortuary Care', price: 800 }, + { name: 'Professional Service Fee', price: 850 }, + ], + }, + ], + total: 1800, + }, + navigation: nav, + onContinue: () => alert('Continue'), + onBack: () => alert('Back'), + }, +}; diff --git a/src/components/pages/PreviewStep/PreviewStep.tsx b/src/components/pages/PreviewStep/PreviewStep.tsx new file mode 100644 index 0000000..31f36c5 --- /dev/null +++ b/src/components/pages/PreviewStep/PreviewStep.tsx @@ -0,0 +1,228 @@ +import React from 'react'; +import Box from '@mui/material/Box'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import type { SxProps, Theme } from '@mui/material/styles'; +import { WizardLayout } from '../../templates/WizardLayout'; +import { ProviderCardCompact } from '../../molecules/ProviderCardCompact'; +import { PackageDetail } from '../../organisms/PackageDetail'; +import type { PackageSection } from '../../organisms/PackageDetail'; +import { Typography } from '../../atoms/Typography'; +import { Button } from '../../atoms/Button'; +import { Divider } from '../../atoms/Divider'; + +// ─── Types ─────────────────────────────────────────────────────────────────── + +/** Provider summary for the compact card */ +export interface PreviewStepProvider { + /** Provider name */ + name: string; + /** Location */ + location: string; + /** Image URL */ + imageUrl?: string; + /** Rating */ + rating?: number; + /** Review count */ + reviewCount?: number; +} + +/** Selected package data for the preview */ +export interface PreviewStepPackage { + /** Package display name */ + name: string; + /** Package price */ + price: number; + /** Line item sections */ + sections: PackageSection[]; + /** Total */ + total?: number; + /** Extras section */ + extras?: PackageSection; + /** Terms */ + terms?: string; +} + +/** A step in the "What's next?" checklist */ +export interface NextStepItem { + /** Step number (1-based) */ + number: number; + /** Step description */ + label: string; +} + +/** Props for the PreviewStep page component */ +export interface PreviewStepProps { + /** Provider summary */ + provider: PreviewStepProvider; + /** Selected package details */ + selectedPackage: PreviewStepPackage; + /** What's next checklist items */ + nextSteps?: NextStepItem[]; + /** Callback for the primary CTA */ + onContinue: () => void; + /** Callback for the back button */ + onBack: () => void; + /** Callback for "Explore other options" (pre-planning only) */ + onExplore?: () => void; + /** Whether Continue is loading */ + loading?: boolean; + /** Whether this is a pre-planning flow */ + isPrePlanning?: boolean; + /** Navigation bar */ + navigation?: React.ReactNode; + /** MUI sx prop */ + sx?: SxProps; +} + +// ─── Default checklist ────────────────────────────────────────────────────── + +const DEFAULT_NEXT_STEPS: NextStepItem[] = [ + { number: 1, label: 'Create your account to save your selections' }, + { number: 2, label: 'Choose a date and time for the service' }, + { number: 3, label: 'Select a venue' }, + { number: 4, label: 'Choose a coffin' }, + { number: 5, label: 'Review and confirm your arrangement' }, +]; + +// ─── Component ─────────────────────────────────────────────────────────────── + +/** + * Step 4 — Package preview page for the FA arrangement wizard. + * + * Informational review step — no form fields. Shows the selected + * package breakdown and a "What's next?" orientation checklist to + * reduce anxiety about the remaining steps. + * + * List + Detail split: provider info + checklist + CTAs (left), + * PackageDetail breakdown (right). + * + * Pre-planning users see an additional "Explore other options" CTA. + * + * Pure presentation component — props in, callbacks out. + * + * Spec: documentation/steps/steps/04_preview.yaml + */ +export const PreviewStep: React.FC = ({ + provider, + selectedPackage, + nextSteps = DEFAULT_NEXT_STEPS, + onContinue, + onBack, + onExplore, + loading = false, + isPrePlanning = false, + navigation, + sx, +}) => { + return ( + + } + > + {/* Provider compact card */} + + + + + {/* Page heading */} + + Your selected package + + + Here's what's included. You'll be able to customise everything in the next + steps. + + + {/* What's next? checklist */} + + + What happens next + + + {nextSteps.map((step) => ( + + + + {step.number} + + + + + ))} + + + + + + {/* Action buttons */} + + {isPrePlanning && onExplore && ( + + )} + + + + ); +}; + +PreviewStep.displayName = 'PreviewStep'; +export default PreviewStep; diff --git a/src/components/pages/PreviewStep/index.ts b/src/components/pages/PreviewStep/index.ts new file mode 100644 index 0000000..7b3a4cd --- /dev/null +++ b/src/components/pages/PreviewStep/index.ts @@ -0,0 +1,2 @@ +export { default } from './PreviewStep'; +export * from './PreviewStep';