Files
Parsons/src/components/pages/UnverifiedPackageT3/UnverifiedPackageT3.stories.tsx
Richie 68889af9c2 Add UnverifiedPackageT2/T3 pages, FuneralFinder pre-planning timeframe, PackageDetail variants
- UnverifiedPackageT3: package step for unverified providers (no image,
  estimated pricing disclaimer, "Make an enquiry" CTA, nearby verified
  providers section)
- UnverifiedPackageT2: same but with "Itemised Pricing Unavailable" notice
  replacing the line-item breakdown
- PackageDetail: new props — arrangeLabel, priceDisclaimer, itemizedUnavailable
- FuneralFinderV3: pre-planning follow-up question ("How soon might you
  need this?"), responsive sizing fixes, compulsory validation
- HomePage: fix finder container width (flex stretch + 500px cap)
- .gitignore: exclude Claude/Playwright artifacts, working docs, screenshots

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:35:28 +11:00

250 lines
8.0 KiB
TypeScript

import { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { UnverifiedPackageT3 } from './UnverifiedPackageT3';
import type {
UnverifiedPackageT3Data,
UnverifiedPackageT3Provider,
NearbyVerifiedPackage,
} from './UnverifiedPackageT3';
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' },
{ label: 'Log in', href: '/login' },
]}
/>
);
const mockProvider: UnverifiedPackageT3Provider = {
name: 'H.Parsons Funeral Directors',
location: 'Wentworth, NSW',
rating: 4.6,
reviewCount: 7,
};
const matchedPackages: UnverifiedPackageT3Data[] = [
{
id: 'everyday',
name: 'Everyday Funeral Package',
price: 2700,
description:
'This package includes a funeral service at a chapel or a church with a funeral procession. It includes many of the most commonly selected funeral options.',
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: 'After Hours Prayers', price: 1920 },
{ name: 'Coffin Bearing by Funeral Directors', price: 1500 },
{ name: 'Digital Recording', price: 500 },
],
},
terms:
'This package includes a funeral service at a chapel or a church with a funeral procession. Pricing may vary based on additional selections.',
},
];
const nearbyVerifiedPackages: NearbyVerifiedPackage[] = [
{
id: 'rankins-standard',
packageName: 'Standard Cremation Package',
price: 2450,
providerName: 'Rankins Funerals',
location: 'Warrawong, NSW',
rating: 4.8,
reviewCount: 23,
},
{
id: 'easy-essential',
packageName: 'Essential Funeral Service',
price: 1950,
providerName: 'Easy Funerals',
location: 'Sydney, NSW',
rating: 4.5,
reviewCount: 42,
},
{
id: 'killick-classic',
packageName: 'Classic Farewell Package',
price: 3100,
providerName: 'Killick Family Funerals',
location: 'Shellharbour, NSW',
rating: 4.9,
reviewCount: 15,
},
];
// ─── Meta ────────────────────────────────────────────────────────────────────
const meta: Meta<typeof UnverifiedPackageT3> = {
title: 'Pages/UnverifiedPackageT3',
component: UnverifiedPackageT3,
tags: ['autodocs'],
parameters: {
layout: 'fullscreen',
},
};
export default meta;
type Story = StoryObj<typeof UnverifiedPackageT3>;
// ─── Interactive (default) ──────────────────────────────────────────────────
/** Matched + other packages — select a package, see detail, click Make Arrangement */
export const Default: Story = {
render: () => {
const [selectedId, setSelectedId] = useState<string | null>(null);
return (
<UnverifiedPackageT3
provider={mockProvider}
packages={matchedPackages}
nearbyPackages={nearbyVerifiedPackages}
selectedPackageId={selectedId}
onSelectPackage={setSelectedId}
onArrange={() => alert('Open ArrangementDialog')}
onProviderClick={() => alert('Open provider profile')}
onBack={() => alert('Back')}
navigation={nav}
/>
);
},
};
// ─── With selection ─────────────────────────────────────────────────────────
/** Package already selected — detail panel visible */
export const WithSelection: Story = {
render: () => {
const [selectedId, setSelectedId] = useState<string | null>('everyday');
return (
<UnverifiedPackageT3
provider={mockProvider}
packages={matchedPackages}
nearbyPackages={nearbyVerifiedPackages}
selectedPackageId={selectedId}
onSelectPackage={setSelectedId}
onArrange={() => alert('Open ArrangementDialog')}
onProviderClick={() => alert('Open provider profile')}
onBack={() => alert('Back')}
navigation={nav}
/>
);
},
};
// ─── No other packages (all match) ─────────────────────────────────────────
/** No nearby verified packages — only this provider's packages */
export const NoNearbyPackages: Story = {
render: () => {
const [selectedId, setSelectedId] = useState<string | null>(null);
return (
<UnverifiedPackageT3
provider={mockProvider}
packages={matchedPackages}
selectedPackageId={selectedId}
onSelectPackage={setSelectedId}
onArrange={() => alert('Open ArrangementDialog')}
onProviderClick={() => alert('Open provider profile')}
onBack={() => alert('Back')}
navigation={nav}
/>
);
},
};
// ─── Pre-planning ───────────────────────────────────────────────────────────
/** Pre-planning flow — softer copy */
export const PrePlanning: Story = {
render: () => {
const [selectedId, setSelectedId] = useState<string | null>(null);
return (
<UnverifiedPackageT3
provider={mockProvider}
packages={matchedPackages}
nearbyPackages={nearbyVerifiedPackages}
selectedPackageId={selectedId}
onSelectPackage={setSelectedId}
onArrange={() => alert('Open ArrangementDialog')}
onProviderClick={() => alert('Open provider profile')}
onBack={() => alert('Back')}
navigation={nav}
isPrePlanning
/>
);
},
};
// ─── Validation error ───────────────────────────────────────────────────────
/** Error shown when no package selected */
export const WithError: Story = {
render: () => {
const [selectedId, setSelectedId] = useState<string | null>(null);
return (
<UnverifiedPackageT3
provider={mockProvider}
packages={matchedPackages}
selectedPackageId={selectedId}
onSelectPackage={setSelectedId}
onArrange={() => {}}
onBack={() => alert('Back')}
error="Please choose a package to continue."
navigation={nav}
/>
);
},
};