SummaryStep: visual cart layout with arrangement details and share dialog
- Visual cart-style cards with image thumbnails for provider, venue, crematorium, coffin (replaces accordion text lists) - Arrangement details section at top: arranger name, deceased name, service tradition, preferred dates/times - Location pin icons on all location-based cards - Allowance display: fully covered shows "Included in your package", partially covered shows price/allowance/remaining breakdown - Share dialog: "Share this plan" button opens DialogShell with multi-email input, add/remove recipients, send confirmation state - Included services as checkmark list, extras as priced list (consistent tick logic — only in sections with no priced items) - Full-width CTA, deposit deferred to payment step - Edit buttons with pencil icon in secondary colour Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { SummaryStep } from './SummaryStep';
|
||||
import type { SummarySection } from './SummaryStep';
|
||||
import type { SummarySection, ArrangementDetails } from './SummaryStep';
|
||||
import { Navigation } from '../../organisms/Navigation';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
@@ -33,52 +33,78 @@ const nav = (
|
||||
/>
|
||||
);
|
||||
|
||||
const sampleDetails: ArrangementDetails = {
|
||||
arrangerName: 'Sarah Mitchell',
|
||||
deceasedName: 'Robert Mitchell',
|
||||
serviceTradition: 'Non-denominational',
|
||||
preferredDates: ['Tuesday 15 April', 'Wednesday 16 April'],
|
||||
preferredTime: 'Morning',
|
||||
editStepId: 'date_time',
|
||||
};
|
||||
|
||||
const sampleSections: SummarySection[] = [
|
||||
{
|
||||
id: 'provider',
|
||||
title: 'Funeral Provider',
|
||||
editStepId: 'providers',
|
||||
items: [
|
||||
{ label: 'Provider', value: 'H. Parsons Funeral Directors' },
|
||||
{ label: 'Package', value: 'Essential Service Package', price: 4950 },
|
||||
],
|
||||
imageUrl: 'https://placehold.co/320x200/F5F5F0/8B8B7E?text=H.+Parsons',
|
||||
name: 'H. Parsons Funeral Directors',
|
||||
subtitle: 'Essential Service Package',
|
||||
location: 'Mackay, QLD',
|
||||
price: 4950,
|
||||
},
|
||||
{
|
||||
id: 'venue',
|
||||
title: 'Service Venue',
|
||||
editStepId: 'venue',
|
||||
imageUrl: 'https://placehold.co/320x200/F5F5F0/8B8B7E?text=West+Chapel',
|
||||
name: 'West Chapel',
|
||||
location: 'Strathfield, NSW',
|
||||
price: 900,
|
||||
items: [
|
||||
{ label: 'Venue', value: 'West Chapel, Strathfield', price: 900 },
|
||||
{ label: 'Photo presentation', value: 'Included', price: 150 },
|
||||
{ label: 'Livestream', value: 'Included', price: 200 },
|
||||
{ label: 'Photo presentation', price: 150 },
|
||||
{ label: 'Livestream', price: 200 },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'crematorium',
|
||||
title: 'Crematorium',
|
||||
editStepId: 'crematorium',
|
||||
items: [
|
||||
{ label: 'Crematorium', value: 'Warrill Park Crematorium', price: 850 },
|
||||
{ label: 'Following hearse', value: 'Yes' },
|
||||
],
|
||||
imageUrl: 'https://placehold.co/320x200/F5F5F0/8B8B7E?text=Warrill+Park',
|
||||
name: 'Warrill Park Crematorium',
|
||||
location: 'Ipswich, QLD',
|
||||
price: 850,
|
||||
},
|
||||
{
|
||||
id: 'coffin',
|
||||
title: 'Coffin',
|
||||
editStepId: 'coffins',
|
||||
imageUrl: 'https://images.unsplash.com/photo-1618220179428-22790b461013?w=320&h=200&fit=crop',
|
||||
name: 'Richmond Rosewood Coffin',
|
||||
colourName: 'Natural Oak',
|
||||
colourHex: '#D4A76A',
|
||||
price: 1750,
|
||||
allowanceAmount: 500,
|
||||
},
|
||||
{
|
||||
id: 'included',
|
||||
title: 'Included Services',
|
||||
editStepId: 'included_services',
|
||||
items: [
|
||||
{ label: 'Coffin', value: 'Cedar Classic', price: 2800 },
|
||||
{ label: 'Handles', value: 'Brass Bar Handle', price: 0 },
|
||||
{ label: 'Lining', value: 'White Satin', price: 0 },
|
||||
{ label: 'Dressing and preparation' },
|
||||
{ label: 'Viewing', value: 'Same venue' },
|
||||
{ label: 'Funeral announcement' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'services',
|
||||
title: 'Additional Services',
|
||||
editStepId: 'additional_services',
|
||||
id: 'extras',
|
||||
title: 'Optional Extras',
|
||||
editStepId: 'extras',
|
||||
items: [
|
||||
{ label: 'Funeral announcement', value: 'Included' },
|
||||
{ label: 'Bearing', value: 'Family and friends' },
|
||||
{ label: 'Catering', priceLabel: 'Price on application' },
|
||||
{ label: 'Live musician', value: 'Vocalist', price: 450 },
|
||||
{ label: 'Coffin bearing', value: 'Family and friends' },
|
||||
{ label: 'Newspaper notice', price: 250 },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -99,35 +125,61 @@ type Story = StoryObj<typeof SummaryStep>;
|
||||
|
||||
// ─── At-need (default) ──────────────────────────────────────────────────────
|
||||
|
||||
/** Full summary for at-need flow */
|
||||
/** Full summary for at-need flow with allowances */
|
||||
export const Default: Story = {
|
||||
render: () => (
|
||||
<SummaryStep
|
||||
arrangementDetails={sampleDetails}
|
||||
sections={sampleSections}
|
||||
totalPrice={9850}
|
||||
depositAmount={2000}
|
||||
totalPrice={9050}
|
||||
totalAllowances={500}
|
||||
onConfirm={() => alert('Confirmed — proceed to payment')}
|
||||
onBack={() => alert('Back')}
|
||||
onSaveAndExit={() => alert('Save')}
|
||||
onEdit={(stepId) => alert(`Edit: ${stepId}`)}
|
||||
onShare={() => alert('Share plan')}
|
||||
onShareByEmail={(emails) => alert(`Share to: ${emails.join(', ')}`)}
|
||||
navigation={nav}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
// ─── Coffin fully covered ───────────────────────────────────────────────────
|
||||
|
||||
/** Coffin fully covered by allowance */
|
||||
export const FullyCovered: Story = {
|
||||
render: () => {
|
||||
const sections = sampleSections.map((s) =>
|
||||
s.id === 'coffin' ? { ...s, price: 900, allowanceAmount: 1000 } : s,
|
||||
);
|
||||
return (
|
||||
<SummaryStep
|
||||
arrangementDetails={sampleDetails}
|
||||
sections={sections}
|
||||
totalPrice={7500}
|
||||
onConfirm={() => alert('Confirmed')}
|
||||
onBack={() => alert('Back')}
|
||||
onEdit={(stepId) => alert(`Edit: ${stepId}`)}
|
||||
onShareByEmail={(emails) => alert(`Share to: ${emails.join(', ')}`)}
|
||||
navigation={nav}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
// ─── Pre-planning ───────────────────────────────────────────────────────────
|
||||
|
||||
/** Pre-planning variant — "Save your plan" CTA, no payment */
|
||||
/** Pre-planning variant — "Save your plan" CTA */
|
||||
export const PrePlanning: Story = {
|
||||
render: () => (
|
||||
<SummaryStep
|
||||
arrangementDetails={sampleDetails}
|
||||
sections={sampleSections}
|
||||
totalPrice={9850}
|
||||
totalPrice={9050}
|
||||
totalAllowances={500}
|
||||
onConfirm={() => alert('Plan saved')}
|
||||
onBack={() => alert('Back')}
|
||||
onEdit={(stepId) => alert(`Edit: ${stepId}`)}
|
||||
onShare={() => alert('Share plan')}
|
||||
onShareByEmail={(emails) => alert(`Share to: ${emails.join(', ')}`)}
|
||||
isPrePlanning
|
||||
navigation={nav}
|
||||
/>
|
||||
@@ -140,8 +192,9 @@ export const PrePlanning: Story = {
|
||||
export const Loading: Story = {
|
||||
render: () => (
|
||||
<SummaryStep
|
||||
arrangementDetails={sampleDetails}
|
||||
sections={sampleSections}
|
||||
totalPrice={9850}
|
||||
totalPrice={9050}
|
||||
onConfirm={() => {}}
|
||||
loading
|
||||
navigation={nav}
|
||||
|
||||
Reference in New Issue
Block a user