- 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>
250 lines
8.0 KiB
TypeScript
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}
|
|
/>
|
|
);
|
|
},
|
|
};
|