Files
Parsons/src/components/organisms/ComparisonTable/ComparisonTable.stories.tsx
Richie 52fd0f199a Add package comparison feature: CompareBar, ComparisonTable, ComparisonPage
New components for side-by-side funeral package comparison:

- CompareBar molecule: floating bottom pill with fraction badge (1/3, 2/3, 3/3),
  contextual copy, Compare CTA. For ProvidersStep and PackagesStep.
- ComparisonTable organism: CSS Grid comparison with info card, floating verified
  badges, separate section tables (Essentials/Optionals/Extras) with left accent
  borders, row hover, horizontal scroll on narrow desktops, font hierarchy.
- ComparisonPage: WizardLayout wide-form with Share/Print actions. Desktop shows
  ComparisonTable, mobile shows mini-card tab rail + single package card view.
  Recommended package as separate prop (D038).

Also fixes PackageDetail: adds priceLabel pass-through (D039), updates stories
to Essentials/Optionals/Extras section naming (D035).

Decisions: D035-D039 logged. Audits: CompareBar 18/20, ComparisonTable 17/20.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 01:17:34 +10:00

374 lines
11 KiB
TypeScript

import type { Meta, StoryObj } from '@storybook/react';
import Box from '@mui/material/Box';
import { ComparisonTable } from './ComparisonTable';
import type { ComparisonPackage } from './ComparisonTable';
const DEMO_LOGO = 'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=72&h=72&fit=crop';
// ─── Mock data ──────────────────────────────────────────────────────────────
const pkgWollongong: ComparisonPackage = {
id: 'wollongong-everyday',
name: 'Everyday Funeral Package',
price: 6966,
provider: {
name: 'Wollongong City Funerals',
location: 'Wollongong',
logoUrl: DEMO_LOGO,
rating: 4.8,
reviewCount: 122,
verified: true,
},
sections: [
{
heading: 'Essentials',
items: [
{
name: 'Allowance for Coffin',
info: 'Allowance amount — upgrade options available.',
value: { type: 'allowance', amount: 1750 },
},
{
name: 'Cremation Certificate/Permit',
info: 'Statutory medical referee fee.',
value: { type: 'price', amount: 350 },
},
{
name: 'Crematorium: Mackay Family Crematorium',
info: 'Cremation facility fees.',
value: { type: 'price', amount: 660 },
},
{
name: 'Death Registration Certificate',
info: 'Lodgement with NSW Registry.',
value: { type: 'price', amount: 70 },
},
{
name: 'Dressing Fee',
info: 'Dressing and preparation of the deceased.',
value: { type: 'complimentary' },
},
{
name: 'NSW Government Levy — Cremation',
info: 'NSW Government cremation levy.',
value: { type: 'price', amount: 45.1 },
},
{
name: 'Professional Mortuary Care',
info: 'Preparation and care of the deceased.',
value: { type: 'price', amount: 440 },
},
{
name: 'Professional Service Fee',
info: 'Coordination of all funeral arrangements.',
value: { type: 'price', amount: 3650.9 },
},
{
name: 'Transportation Service Fee',
info: 'Transfer of the deceased.',
value: { type: 'complimentary' },
},
],
},
{
heading: 'Optionals',
items: [
{
name: 'Digital Recording of the Funeral Service',
info: 'Professional video recording.',
value: { type: 'complimentary' },
},
{ name: 'Online Notice', info: 'Online death notice.', value: { type: 'complimentary' } },
{
name: 'Viewing Fee',
info: 'One private family viewing.',
value: { type: 'complimentary' },
},
{
name: 'Flowers',
info: 'Seasonal floral arrangements.',
value: { type: 'complimentary' },
},
],
},
{
heading: 'Extras',
items: [
{
name: 'Allowance for Celebrant',
info: 'Professional celebrant or MC.',
value: { type: 'allowance', amount: 550 },
},
{ name: 'Catering', info: 'Post-service catering.', value: { type: 'poa' } },
{ name: 'Newspaper Notice', info: 'Published death notice.', value: { type: 'poa' } },
{
name: 'Saturday Service Fee',
info: 'Additional fee for Saturday services.',
value: { type: 'price', amount: 880 },
},
],
},
],
};
const pkgMackay: ComparisonPackage = {
id: 'mackay-everyday',
name: 'Everyday Funeral Package',
price: 5495.45,
provider: {
name: 'Mackay Family Funerals',
location: 'Inglewood',
logoUrl: DEMO_LOGO,
rating: 4.6,
reviewCount: 87,
verified: true,
},
sections: [
{
heading: 'Essentials',
items: [
{
name: 'Allowance for Coffin',
info: 'Allowance amount — upgrade options available.',
value: { type: 'allowance', amount: 1500 },
},
{
name: 'Cremation Certificate/Permit',
info: 'Statutory medical referee fee.',
value: { type: 'price', amount: 350 },
},
{
name: 'Crematorium: Mackay Family Crematorium',
info: 'Cremation facility fees.',
value: { type: 'price', amount: 660 },
},
{
name: 'Death Registration Certificate',
info: 'Lodgement with NSW Registry.',
value: { type: 'price', amount: 70 },
},
{ name: 'Dressing Fee', info: 'Dressing and preparation.', value: { type: 'included' } },
{
name: 'NSW Government Levy — Cremation',
info: 'NSW Government cremation levy.',
value: { type: 'price', amount: 45.1 },
},
{
name: 'Professional Mortuary Care',
info: 'Preparation and care.',
value: { type: 'price', amount: 440 },
},
{
name: 'Professional Service Fee',
info: 'Coordination of arrangements.',
value: { type: 'price', amount: 2430.35 },
},
{
name: 'Transportation Service Fee',
info: 'Transfer of the deceased.',
value: { type: 'price', amount: 0 },
},
],
},
{
heading: 'Optionals',
items: [
{
name: 'Digital Recording of the Funeral Service',
info: 'Professional video recording.',
value: { type: 'unknown' },
},
{ name: 'Online Notice', info: 'Online death notice.', value: { type: 'included' } },
{ name: 'Viewing Fee', info: 'One private family viewing.', value: { type: 'included' } },
{ name: 'Flowers', info: 'Seasonal floral arrangements.', value: { type: 'included' } },
],
},
{
heading: 'Extras',
items: [
{
name: 'Allowance for Celebrant',
info: 'Professional celebrant or MC.',
value: { type: 'allowance', amount: 450 },
},
{ name: 'Catering', info: 'Post-service catering.', value: { type: 'poa' } },
{
name: 'Saturday Service Fee',
info: 'Additional fee for Saturday services.',
value: { type: 'price', amount: 750 },
},
],
},
],
};
const pkgInglewood: ComparisonPackage = {
id: 'inglewood-everyday',
name: 'Everyday Funeral Package',
price: 7200,
provider: {
name: 'Inglewood Chapel',
location: 'Inglewood',
logoUrl: DEMO_LOGO,
rating: 4.2,
reviewCount: 45,
verified: false,
},
sections: [
{
heading: 'Essentials',
items: [
{
name: 'Allowance for Coffin',
info: 'Allowance amount — upgrade options available.',
value: { type: 'allowance', amount: 1800 },
},
{
name: 'Cremation Certificate/Permit',
info: 'Statutory medical referee fee.',
value: { type: 'price', amount: 350 },
},
{
name: 'Death Registration Certificate',
info: 'Lodgement with NSW Registry.',
value: { type: 'price', amount: 70 },
},
{
name: 'Professional Service Fee',
info: 'Coordination of arrangements.',
value: { type: 'price', amount: 3980 },
},
{
name: 'Transportation Service Fee',
info: 'Transfer of the deceased.',
value: { type: 'price', amount: 500 },
},
],
},
{
heading: 'Optionals',
items: [
{ name: 'Viewing Fee', info: 'One private family viewing.', value: { type: 'included' } },
{ name: 'Flowers', info: 'Seasonal floral arrangements.', value: { type: 'poa' } },
{
name: 'Digital Recording of the Funeral Service',
info: 'Professional video recording.',
value: { type: 'price', amount: 250 },
},
],
},
{
heading: 'Extras',
items: [
{ name: 'Catering', info: 'Post-service catering.', value: { type: 'poa' } },
{ name: 'Newspaper Notice', info: 'Published death notice.', value: { type: 'poa' } },
],
},
],
};
const pkgRecommended: ComparisonPackage = {
...pkgWollongong,
id: 'recommended-premium',
name: 'Premium Cremation Service',
price: 8450,
isRecommended: true,
provider: {
name: 'H. Parsons Funeral Directors',
location: 'Wentworth',
logoUrl: DEMO_LOGO,
rating: 4.9,
reviewCount: 203,
verified: true,
},
};
const pkgNoItemised: ComparisonPackage = {
id: 'no-data',
name: 'Basic Cremation',
price: 4500,
provider: {
name: 'Smith & Sons',
location: 'Bankstown',
verified: false,
},
sections: [],
itemizedAvailable: false,
};
// ─── Meta ───────────────────────────────────────────────────────────────────
const meta: Meta<typeof ComparisonTable> = {
title: 'Organisms/ComparisonTable',
component: ComparisonTable,
tags: ['autodocs'],
parameters: {
layout: 'fullscreen',
},
decorators: [
(Story) => (
<Box sx={{ p: { xs: 2, md: 4 }, maxWidth: 1200, mx: 'auto' }}>
<Story />
</Box>
),
],
};
export default meta;
type Story = StoryObj<typeof ComparisonTable>;
// --- Default (3 packages) ----------------------------------------------------
/** Three packages from different providers — full comparison */
export const Default: Story = {
args: {
packages: [pkgWollongong, pkgMackay, pkgInglewood],
onArrange: (id) => alert(`Arrange: ${id}`),
onRemove: (id) => alert(`Remove: ${id}`),
},
};
// --- Two Packages ------------------------------------------------------------
/** Minimal two-column comparison */
export const TwoPackages: Story = {
args: {
packages: [pkgWollongong, pkgMackay],
onArrange: (id) => alert(`Arrange: ${id}`),
onRemove: (id) => alert(`Remove: ${id}`),
},
};
// --- With Recommended --------------------------------------------------------
/** 3 user + 1 recommended = 4 columns — recommended has warm bg + badge */
export const WithRecommended: Story = {
args: {
packages: [pkgWollongong, pkgMackay, pkgInglewood, pkgRecommended],
onArrange: (id) => alert(`Arrange: ${id}`),
onRemove: (id) => alert(`Remove: ${id}`),
},
};
// --- Mixed Verified/Unverified -----------------------------------------------
/** Mix of verified (Make Arrangement) and unverified (Make Enquiry) providers */
export const MixedVerified: Story = {
args: {
packages: [pkgWollongong, pkgInglewood],
onArrange: (id) => alert(`Arrange: ${id}`),
onRemove: (id) => alert(`Remove: ${id}`),
},
};
// --- Missing Itemised Data ---------------------------------------------------
/** One provider has no itemised breakdown — cells show "—" */
export const MissingData: Story = {
args: {
packages: [pkgWollongong, pkgNoItemised, pkgMackay],
onArrange: (id) => alert(`Arrange: ${id}`),
onRemove: (id) => alert(`Remove: ${id}`),
},
};