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>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
import type { SxProps, Theme } from '@mui/material/styles';
|
||||
import { Typography } from '../../atoms/Typography';
|
||||
import { Button } from '../../atoms/Button';
|
||||
@@ -50,6 +51,12 @@ export interface PackageDetailProps {
|
||||
arrangeDisabled?: boolean;
|
||||
/** Whether the compare button is in loading state */
|
||||
compareLoading?: boolean;
|
||||
/** Custom label for the arrange CTA button (default: "Make Arrangement") */
|
||||
arrangeLabel?: string;
|
||||
/** Disclaimer shown below the price (e.g. for unverified/estimated pricing) */
|
||||
priceDisclaimer?: string;
|
||||
/** When true, replaces the itemised breakdown with an "Itemised Pricing Unavailable" notice */
|
||||
itemizedUnavailable?: boolean;
|
||||
/** MUI sx prop for the root element */
|
||||
sx?: SxProps<Theme>;
|
||||
}
|
||||
@@ -116,6 +123,9 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
|
||||
onCompare,
|
||||
arrangeDisabled = false,
|
||||
compareLoading = false,
|
||||
arrangeLabel = 'Make Arrangement',
|
||||
priceDisclaimer,
|
||||
itemizedUnavailable = false,
|
||||
sx,
|
||||
},
|
||||
ref,
|
||||
@@ -159,6 +169,32 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
|
||||
${price.toLocaleString('en-AU')}
|
||||
</Typography>
|
||||
|
||||
{/* Price disclaimer */}
|
||||
{priceDisclaimer && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
gap: 1,
|
||||
mt: 1.5,
|
||||
px: 1.5,
|
||||
py: 1,
|
||||
bgcolor: 'var(--fa-color-surface-cool, #F5F7FA)',
|
||||
borderRadius: 'var(--fa-border-radius-sm, 6px)',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<InfoOutlinedIcon
|
||||
sx={{ fontSize: 16, color: 'text.secondary', mt: '1px', flexShrink: 0 }}
|
||||
aria-hidden
|
||||
/>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ lineHeight: 1.4 }}>
|
||||
{priceDisclaimer}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* CTA buttons */}
|
||||
<Box
|
||||
sx={{ display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 1.5, mt: 2.5 }}
|
||||
@@ -170,7 +206,7 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
|
||||
disabled={arrangeDisabled}
|
||||
onClick={onArrange}
|
||||
>
|
||||
Make Arrangement
|
||||
{arrangeLabel}
|
||||
</Button>
|
||||
{onCompare && (
|
||||
<Button
|
||||
@@ -189,24 +225,55 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
|
||||
|
||||
{/* Package contents */}
|
||||
<Box sx={{ px: { xs: 2, sm: 3 }, py: 3 }}>
|
||||
{/* Main sections — included in the package price */}
|
||||
{sections.map((section, idx) => (
|
||||
<Box key={section.heading} sx={{ mb: idx < sections.length - 1 ? 3 : 0 }}>
|
||||
<SectionBlock section={section} />
|
||||
</Box>
|
||||
))}
|
||||
|
||||
{/* Total — separates included content from extras */}
|
||||
{total != null && <LineItem name="Total" price={total} variant="total" />}
|
||||
|
||||
{/* Extras — additional cost items after the total */}
|
||||
{extras && extras.items.length > 0 && (
|
||||
<>
|
||||
<Divider sx={{ my: 3 }} />
|
||||
<SectionBlock
|
||||
section={extras}
|
||||
subtext="These items can be added to your package at additional cost."
|
||||
{itemizedUnavailable ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
bgcolor: 'var(--fa-color-surface-warm, #FEF9F5)',
|
||||
borderRadius: 'var(--fa-border-radius-md, 8px)',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
px: 3,
|
||||
py: 4,
|
||||
}}
|
||||
>
|
||||
<InfoOutlinedIcon
|
||||
sx={{ fontSize: 28, color: 'var(--fa-color-brand-500)', mb: 1.5 }}
|
||||
aria-hidden
|
||||
/>
|
||||
<Typography variant="h6" component="p" sx={{ mb: 1 }}>
|
||||
Itemised Pricing Unavailable
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ maxWidth: 360 }}>
|
||||
This provider has shared their overall package price, but has not provided a
|
||||
detailed breakdown of what is included.
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<>
|
||||
{/* Main sections — included in the package price */}
|
||||
{sections.map((section, idx) => (
|
||||
<Box key={section.heading} sx={{ mb: idx < sections.length - 1 ? 3 : 0 }}>
|
||||
<SectionBlock section={section} />
|
||||
</Box>
|
||||
))}
|
||||
|
||||
{/* Total — separates included content from extras */}
|
||||
{total != null && <LineItem name="Total" price={total} variant="total" />}
|
||||
|
||||
{/* Extras — additional cost items after the total */}
|
||||
{extras && extras.items.length > 0 && (
|
||||
<>
|
||||
<Divider sx={{ my: 3 }} />
|
||||
<SectionBlock
|
||||
section={extras}
|
||||
subtext="These items can be added to your package at additional cost."
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user