Packages fixtures: drop 'unknown' treatment + add 10 verified packages

Dash fix: PackageDetail no longer renders em-dash placeholder rows for
Optionals. The 10 fixture entries that used `treatment: 'unknown'` are
removed; the Optional type narrows to IncludedTreatment only; the dead
'unknown' branch in optionalsForStep/optionalsForComparison is gone.
The rule going forward: an Optional/Extra exists on a package when the
package actually offers it. ComparisonTable already handles absence
correctly via buildMergedSections + lookupValue → 'Not Included'.

Package distribution expanded (max 5 per provider, randomised):
  parsons:  3 → 5  (+ traditional-burial, memorial-service)
  rankins:  2 → 3  (+ direct-cremation)
  killick:  2 → 3  (+ traditional-burial)
  mackay:   1 → 4  (+ premium, simple, memorial-service)
  mannings: 1 → 4  (+ premium, simple, direct-cremation)

Each new package follows the canonical-essentials rule: same 9 Essentials
line items, only prices/treatments vary. Optionals + Extras composed per
package. Mackay + Mannings comparison maps rewritten from single-package
to the indexed-array pattern used by parsons/rankins/killick, and their
bundle entries now slice(0,1)/slice(1) so an "Other packages from this
provider" section appears.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 13:52:39 +10:00
parent d2b648750f
commit 9b6d541a6a

View File

@@ -134,26 +134,32 @@ const sumEssentials = (p: EssentialsPrices): number => {
}; };
// ─── Optionals helpers ─────────────────────────────────────────────────────── // ─── Optionals helpers ───────────────────────────────────────────────────────
//
// Rule: Optionals an Extras list an item ONLY when that package actually
// offers it. Missing items are not placeholders — they're just absent. In
// PackageDetail that means the row isn't rendered. In ComparisonTable the
// cross-join (see `buildMergedSections` + `lookupValue`) surfaces the row
// as "Not Included" for any column that doesn't include it.
interface Optional { interface Optional {
name: string; name: string;
treatment: IncludedTreatment | 'unknown'; treatment: IncludedTreatment;
} }
const optionalsForStep = (items: Optional[]): PackageSection => ({ const optionalsForStep = (items: Optional[]): PackageSection => ({
heading: 'Optionals', heading: 'Optionals',
items: items.map<PackageLineItem>((it) => items: items.map<PackageLineItem>((it) => ({
it.treatment === 'unknown' name: it.name,
? { name: it.name, price: 0, priceLabel: '—' } price: 0,
: { name: it.name, price: 0, priceLabel: labelFor(it.treatment) }, priceLabel: labelFor(it.treatment),
), })),
}); });
const optionalsForComparison = (items: Optional[]): ComparisonSection => ({ const optionalsForComparison = (items: Optional[]): ComparisonSection => ({
heading: 'Optionals', heading: 'Optionals',
items: items.map((it) => ({ items: items.map((it) => ({
name: it.name, name: it.name,
value: { type: it.treatment === 'unknown' ? 'unknown' : it.treatment }, value: { type: it.treatment },
})), })),
}); });
@@ -226,6 +232,28 @@ const parsonsDeluxeEssentials: EssentialsPrices = {
service: 5384.9, service: 5384.9,
transport: 'complimentary', transport: 'complimentary',
}; };
const parsonsTraditionalEssentials: EssentialsPrices = {
coffin: 2200,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'complimentary',
govLevy: 45.1,
mortuary: 440,
service: 4534.9,
transport: 'complimentary',
};
const parsonsMemorialEssentials: EssentialsPrices = {
coffin: 900,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'complimentary',
govLevy: 45.1,
mortuary: 440,
service: 3034.9,
transport: 'complimentary',
};
const parsonsForStep: PackageData[] = [ const parsonsForStep: PackageData[] = [
{ {
@@ -290,10 +318,58 @@ const parsonsForStep: PackageData[] = [
{ name: 'Saturday Service Fee', value: 'complimentary' }, { name: 'Saturday Service Fee', value: 'complimentary' },
]), ]),
}, },
{
id: 'traditional-burial',
name: 'Traditional Burial Package',
price: sumEssentials(parsonsTraditionalEssentials),
description:
'A traditional funeral service followed by burial, including a full procession and graveside committal.',
sections: [
essentialsForStep(parsonsTraditionalEssentials),
optionalsForStep([
{ name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'complimentary' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 1100 },
{ name: 'Newspaper Notice', value: 350 },
{ name: 'Saturday Service Fee', value: 880 },
]),
},
{
id: 'memorial-service',
name: 'Memorial Service Package',
price: sumEssentials(parsonsMemorialEssentials),
description:
'A memorial service held after the cremation, giving families time to plan a personalised gathering.',
sections: [
essentialsForStep(parsonsMemorialEssentials),
optionalsForStep([
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'complimentary' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 500 } },
{ name: 'Catering', value: 'poa' },
{ name: 'Newspaper Notice', value: 280 },
]),
},
]; ];
const parsonsForComparison: ComparisonPackage[] = parsonsForStep.map((pkg, idx) => { const parsonsForComparison: ComparisonPackage[] = parsonsForStep.map((pkg, idx) => {
const ess = [parsonsEverydayEssentials, parsonsEssentialEssentials, parsonsDeluxeEssentials][idx]; const ess = [
parsonsEverydayEssentials,
parsonsEssentialEssentials,
parsonsDeluxeEssentials,
parsonsTraditionalEssentials,
parsonsMemorialEssentials,
][idx];
const allOptionals: Optional[][] = [ const allOptionals: Optional[][] = [
[ [
{ name: 'Digital Recording', treatment: 'complimentary' }, { name: 'Digital Recording', treatment: 'complimentary' },
@@ -312,6 +388,17 @@ const parsonsForComparison: ComparisonPackage[] = parsonsForStep.map((pkg, idx)
{ name: 'Flowers', treatment: 'complimentary' }, { name: 'Flowers', treatment: 'complimentary' },
{ name: 'Webstreaming', treatment: 'complimentary' }, { name: 'Webstreaming', treatment: 'complimentary' },
], ],
[
{ name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'complimentary' },
],
[
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'complimentary' },
],
]; ];
const optionals = allOptionals[idx]; const optionals = allOptionals[idx];
const extras: Extra[] = [ const extras: Extra[] = [
@@ -331,6 +418,17 @@ const parsonsForComparison: ComparisonPackage[] = parsonsForStep.map((pkg, idx)
{ name: 'Newspaper Notice', value: 350 }, { name: 'Newspaper Notice', value: 350 },
{ name: 'Saturday Service Fee', value: 'complimentary' as const }, { name: 'Saturday Service Fee', value: 'complimentary' as const },
], ],
[
{ name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 1100 },
{ name: 'Newspaper Notice', value: 350 },
{ name: 'Saturday Service Fee', value: 880 },
],
[
{ name: 'Allowance for Celebrant', value: { allowance: 500 } },
{ name: 'Catering', value: 'poa' as const },
{ name: 'Newspaper Notice', value: 280 },
],
][idx]; ][idx];
return { return {
id: pkg.id, id: pkg.id,
@@ -376,6 +474,17 @@ const rankinsPremiumEssentials: EssentialsPrices = {
service: 4034.9, service: 4034.9,
transport: 'included', transport: 'included',
}; };
const rankinsDirectEssentials: EssentialsPrices = {
coffin: 800,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 434.9,
transport: 'included',
};
const rankinsForStep: PackageData[] = [ const rankinsForStep: PackageData[] = [
{ {
@@ -386,7 +495,6 @@ const rankinsForStep: PackageData[] = [
sections: [ sections: [
essentialsForStep(rankinsStandardEssentials), essentialsForStep(rankinsStandardEssentials),
optionalsForStep([ optionalsForStep([
{ name: 'Digital Recording', treatment: 'unknown' },
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' }, { name: 'Flowers', treatment: 'included' },
@@ -418,13 +526,20 @@ const rankinsForStep: PackageData[] = [
{ name: 'Newspaper Notice', value: 280 }, { name: 'Newspaper Notice', value: 280 },
]), ]),
}, },
{
id: 'direct-cremation',
name: 'Direct Cremation',
price: sumEssentials(rankinsDirectEssentials),
description: 'An unattended cremation with no service — the lowest-cost option.',
sections: [essentialsForStep(rankinsDirectEssentials), optionalsForStep([])],
extras: extrasForStep([]),
},
]; ];
const rankinsForComparison: ComparisonPackage[] = rankinsForStep.map((pkg, idx) => { const rankinsForComparison: ComparisonPackage[] = rankinsForStep.map((pkg, idx) => {
const ess = [rankinsStandardEssentials, rankinsPremiumEssentials][idx]; const ess = [rankinsStandardEssentials, rankinsPremiumEssentials, rankinsDirectEssentials][idx];
const allOptionals: Optional[][] = [ const allOptionals: Optional[][] = [
[ [
{ name: 'Digital Recording', treatment: 'unknown' },
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' }, { name: 'Flowers', treatment: 'included' },
@@ -435,6 +550,7 @@ const rankinsForComparison: ComparisonPackage[] = rankinsForStep.map((pkg, idx)
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' }, { name: 'Flowers', treatment: 'included' },
], ],
[],
]; ];
const optionals = allOptionals[idx]; const optionals = allOptionals[idx];
const extras: Extra[] = [ const extras: Extra[] = [
@@ -448,6 +564,7 @@ const rankinsForComparison: ComparisonPackage[] = rankinsForStep.map((pkg, idx)
{ name: 'Catering', value: 950 }, { name: 'Catering', value: 950 },
{ name: 'Newspaper Notice', value: 280 }, { name: 'Newspaper Notice', value: 280 },
], ],
[],
][idx]; ][idx];
return { return {
id: pkg.id, id: pkg.id,
@@ -495,6 +612,18 @@ const killickSimpleEssentials: EssentialsPrices = {
service: 1534.9, service: 1534.9,
transport: 'complimentary', transport: 'complimentary',
}; };
const killickTraditionalEssentials: EssentialsPrices = {
coffin: 2500,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'complimentary',
govLevy: 45.1,
govLevyLabel: 'Government Levy — Cremation',
mortuary: 440,
service: 4234.9,
transport: 'complimentary',
};
const killickForStep: PackageData[] = [ const killickForStep: PackageData[] = [
{ {
@@ -508,7 +637,6 @@ const killickForStep: PackageData[] = [
{ name: 'Digital Recording', treatment: 'complimentary' }, { name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' }, { name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' }, { name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'unknown' },
]), ]),
], ],
extras: extrasForStep([ extras: extrasForStep([
@@ -524,27 +652,47 @@ const killickForStep: PackageData[] = [
description: 'A direct cremation without a service.', description: 'A direct cremation without a service.',
sections: [ sections: [
essentialsForStep(killickSimpleEssentials), essentialsForStep(killickSimpleEssentials),
optionalsForStep([ optionalsForStep([{ name: 'Online Notice', treatment: 'complimentary' }]),
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'unknown' },
]),
], ],
extras: extrasForStep([{ name: 'Allowance for Celebrant', value: { allowance: 350 } }]), extras: extrasForStep([{ name: 'Allowance for Celebrant', value: { allowance: 350 } }]),
}, },
{
id: 'traditional-burial',
name: 'Traditional Burial Package',
price: sumEssentials(killickTraditionalEssentials),
description:
'A traditional burial service with chapel use, full procession, and graveside committal.',
sections: [
essentialsForStep(killickTraditionalEssentials),
optionalsForStep([
{ name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 550 } },
{ name: 'Catering', value: 'poa' },
{ name: 'Saturday Service Fee', value: 800 },
]),
},
]; ];
const killickForComparison: ComparisonPackage[] = killickForStep.map((pkg, idx) => { const killickForComparison: ComparisonPackage[] = killickForStep.map((pkg, idx) => {
const ess = [killickClassicEssentials, killickSimpleEssentials][idx]; const ess = [killickClassicEssentials, killickSimpleEssentials, killickTraditionalEssentials][
idx
];
const allOptionals: Optional[][] = [ const allOptionals: Optional[][] = [
[ [
{ name: 'Digital Recording', treatment: 'complimentary' }, { name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' }, { name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'complimentary' }, { name: 'Viewing Fee', treatment: 'complimentary' },
{ name: 'Flowers', treatment: 'unknown' },
], ],
[{ name: 'Online Notice', treatment: 'complimentary' }],
[ [
{ name: 'Digital Recording', treatment: 'complimentary' },
{ name: 'Online Notice', treatment: 'complimentary' }, { name: 'Online Notice', treatment: 'complimentary' },
{ name: 'Viewing Fee', treatment: 'unknown' }, { name: 'Viewing Fee', treatment: 'complimentary' },
], ],
]; ];
const optionals = allOptionals[idx]; const optionals = allOptionals[idx];
@@ -555,6 +703,11 @@ const killickForComparison: ComparisonPackage[] = killickForStep.map((pkg, idx)
{ name: 'Saturday Service Fee', value: 800 }, { name: 'Saturday Service Fee', value: 800 },
], ],
[{ name: 'Allowance for Celebrant', value: { allowance: 350 } }], [{ name: 'Allowance for Celebrant', value: { allowance: 350 } }],
[
{ name: 'Allowance for Celebrant', value: { allowance: 550 } },
{ name: 'Catering', value: 'poa' as const },
{ name: 'Saturday Service Fee', value: 800 },
],
][idx]; ][idx];
return { return {
id: pkg.id, id: pkg.id,
@@ -589,6 +742,39 @@ const mackayEverydayEssentials: EssentialsPrices = {
service: 2430.35, service: 2430.35,
transport: 'included', transport: 'included',
}; };
const mackayPremiumEssentials: EssentialsPrices = {
coffin: 2200,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 4034.9,
transport: 'included',
};
const mackaySimpleEssentials: EssentialsPrices = {
coffin: 800,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 434.9,
transport: 'included',
};
const mackayMemorialEssentials: EssentialsPrices = {
coffin: 900,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 2834.9,
transport: 'included',
};
const mackayForStep: PackageData[] = [ const mackayForStep: PackageData[] = [
{ {
@@ -599,7 +785,6 @@ const mackayForStep: PackageData[] = [
sections: [ sections: [
essentialsForStep(mackayEverydayEssentials), essentialsForStep(mackayEverydayEssentials),
optionalsForStep([ optionalsForStep([
{ name: 'Digital Recording', treatment: 'unknown' },
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' }, { name: 'Flowers', treatment: 'included' },
@@ -611,35 +796,119 @@ const mackayForStep: PackageData[] = [
{ name: 'Saturday Service Fee', value: 750 }, { name: 'Saturday Service Fee', value: 750 },
]), ]),
}, },
{
id: 'premium',
name: 'Premium Funeral Service',
price: sumEssentials(mackayPremiumEssentials),
description: 'An enhanced service with premium coffin selection and expanded inclusions.',
sections: [
essentialsForStep(mackayPremiumEssentials),
optionalsForStep([
{ name: 'Digital Recording', treatment: 'included' },
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 1100 },
{ name: 'Newspaper Notice', value: 320 },
]),
},
{
id: 'simple',
name: 'Simple Cremation',
price: sumEssentials(mackaySimpleEssentials),
description: 'A direct cremation without a formal service.',
sections: [
essentialsForStep(mackaySimpleEssentials),
optionalsForStep([{ name: 'Online Notice', treatment: 'included' }]),
],
extras: extrasForStep([{ name: 'Allowance for Celebrant', value: { allowance: 350 } }]),
},
{
id: 'memorial-service',
name: 'Memorial Service Package',
price: sumEssentials(mackayMemorialEssentials),
description:
'A memorial service held separately from the cremation, allowing time for planning and family gatherings.',
sections: [
essentialsForStep(mackayMemorialEssentials),
optionalsForStep([
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 500 } },
{ name: 'Catering', value: 'poa' },
]),
},
]; ];
const mackayForComparison: ComparisonPackage[] = mackayForStep.map((pkg) => ({ const mackayForComparison: ComparisonPackage[] = mackayForStep.map((pkg, idx) => {
id: pkg.id, const ess = [
name: pkg.name, mackayEverydayEssentials,
price: pkg.price, mackayPremiumEssentials,
provider: { mackaySimpleEssentials,
name: 'Mackay Family Funeral Directors', mackayMemorialEssentials,
location: 'Ourimbah, NSW', ][idx];
logoUrl: providersById['mackay'].logoUrl, const allOptionals: Optional[][] = [
rating: 4.6, [
reviewCount: 87,
verified: true,
},
sections: [
essentialsForComparison(mackayEverydayEssentials),
optionalsForComparison([
{ name: 'Digital Recording', treatment: 'unknown' },
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' }, { name: 'Flowers', treatment: 'included' },
]), ],
extrasForComparison([ [
{ name: 'Digital Recording', treatment: 'included' },
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' },
],
[{ name: 'Online Notice', treatment: 'included' }],
[
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
],
];
const optionals = allOptionals[idx];
const extras: Extra[] = [
[
{ name: 'Allowance for Celebrant', value: { allowance: 450 } }, { name: 'Allowance for Celebrant', value: { allowance: 450 } },
{ name: 'Catering', value: 'poa' }, { name: 'Catering', value: 'poa' as const },
{ name: 'Saturday Service Fee', value: 750 }, { name: 'Saturday Service Fee', value: 750 },
]), ],
], [
})); { name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 1100 },
{ name: 'Newspaper Notice', value: 320 },
],
[{ name: 'Allowance for Celebrant', value: { allowance: 350 } }],
[
{ name: 'Allowance for Celebrant', value: { allowance: 500 } },
{ name: 'Catering', value: 'poa' as const },
],
][idx];
return {
id: pkg.id,
name: pkg.name,
price: pkg.price,
provider: {
name: 'Mackay Family Funeral Directors',
location: 'Ourimbah, NSW',
logoUrl: providersById['mackay'].logoUrl,
rating: 4.6,
reviewCount: 87,
verified: true,
},
sections: [
essentialsForComparison(ess),
optionalsForComparison(optionals),
extrasForComparison(extras),
],
};
});
// ─── Mannings (verified, NSW) ──────────────────────────────────────────────── // ─── Mannings (verified, NSW) ────────────────────────────────────────────────
@@ -654,6 +923,39 @@ const manningsStandardEssentials: EssentialsPrices = {
service: 2114.9, service: 2114.9,
transport: 'included', transport: 'included',
}; };
const manningsPremiumEssentials: EssentialsPrices = {
coffin: 2100,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 3734.9,
transport: 'included',
};
const manningsSimpleEssentials: EssentialsPrices = {
coffin: 750,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 284.9,
transport: 'included',
};
const manningsDirectEssentials: EssentialsPrices = {
coffin: 600,
cremationCert: 350,
crematorium: 660,
deathReg: 70,
dressing: 'included',
govLevy: 45.1,
mortuary: 440,
service: 34.9,
transport: 'included',
};
const manningsForStep: PackageData[] = [ const manningsForStep: PackageData[] = [
{ {
@@ -666,7 +968,6 @@ const manningsForStep: PackageData[] = [
optionalsForStep([ optionalsForStep([
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'unknown' },
]), ]),
], ],
extras: extrasForStep([ extras: extrasForStep([
@@ -674,33 +975,101 @@ const manningsForStep: PackageData[] = [
{ name: 'Catering', value: 'poa' }, { name: 'Catering', value: 'poa' },
]), ]),
}, },
{
id: 'premium',
name: 'Premium Funeral Service',
price: sumEssentials(manningsPremiumEssentials),
description: 'A more elaborate service with an upgraded coffin and broader inclusions.',
sections: [
essentialsForStep(manningsPremiumEssentials),
optionalsForStep([
{ name: 'Digital Recording', treatment: 'included' },
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' },
]),
],
extras: extrasForStep([
{ name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 950 },
{ name: 'Newspaper Notice', value: 280 },
]),
},
{
id: 'simple',
name: 'Simple Cremation',
price: sumEssentials(manningsSimpleEssentials),
description: 'A straightforward cremation without a chapel service.',
sections: [
essentialsForStep(manningsSimpleEssentials),
optionalsForStep([{ name: 'Online Notice', treatment: 'included' }]),
],
extras: extrasForStep([{ name: 'Allowance for Celebrant', value: { allowance: 350 } }]),
},
{
id: 'direct-cremation',
name: 'Direct Cremation',
price: sumEssentials(manningsDirectEssentials),
description: 'An unattended cremation with no service — the lowest-cost option.',
sections: [essentialsForStep(manningsDirectEssentials), optionalsForStep([])],
extras: extrasForStep([]),
},
]; ];
const manningsForComparison: ComparisonPackage[] = manningsForStep.map((pkg) => ({ const manningsForComparison: ComparisonPackage[] = manningsForStep.map((pkg, idx) => {
id: pkg.id, const ess = [
name: pkg.name, manningsStandardEssentials,
price: pkg.price, manningsPremiumEssentials,
provider: { manningsSimpleEssentials,
name: 'Mannings Funerals', manningsDirectEssentials,
location: 'Bega, NSW', ][idx];
logoUrl: providersById['mannings'].logoUrl, const allOptionals: Optional[][] = [
rating: 4.7, [
reviewCount: 31,
verified: true,
},
sections: [
essentialsForComparison(manningsStandardEssentials),
optionalsForComparison([
{ name: 'Online Notice', treatment: 'included' }, { name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' }, { name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'unknown' }, ],
]), [
extrasForComparison([ { name: 'Digital Recording', treatment: 'included' },
{ name: 'Online Notice', treatment: 'included' },
{ name: 'Viewing Fee', treatment: 'included' },
{ name: 'Flowers', treatment: 'included' },
],
[{ name: 'Online Notice', treatment: 'included' }],
[],
];
const optionals = allOptionals[idx];
const extras: Extra[] = [
[
{ name: 'Allowance for Celebrant', value: { allowance: 400 } }, { name: 'Allowance for Celebrant', value: { allowance: 400 } },
{ name: 'Catering', value: 'poa' }, { name: 'Catering', value: 'poa' as const },
]), ],
], [
})); { name: 'Allowance for Celebrant', value: { allowance: 600 } },
{ name: 'Catering', value: 950 },
{ name: 'Newspaper Notice', value: 280 },
],
[{ name: 'Allowance for Celebrant', value: { allowance: 350 } }],
[],
][idx];
return {
id: pkg.id,
name: pkg.name,
price: pkg.price,
provider: {
name: 'Mannings Funerals',
location: 'Bega, NSW',
logoUrl: providersById['mannings'].logoUrl,
rating: 4.7,
reviewCount: 31,
verified: true,
},
sections: [
essentialsForComparison(ess),
optionalsForComparison(optionals),
extrasForComparison(extras),
],
};
});
// ─── Wollongong City (tier 3 — itemised but unverified, mostly unknowns) ───── // ─── Wollongong City (tier 3 — itemised but unverified, mostly unknowns) ─────
@@ -832,13 +1201,13 @@ export const packagesByProvider: Record<string, PackageBundle> = {
forComparison: killickForComparison, forComparison: killickForComparison,
}, },
mackay: { mackay: {
matching: mackayForStep, matching: mackayForStep.slice(0, 1),
other: [], other: mackayForStep.slice(1),
forComparison: mackayForComparison, forComparison: mackayForComparison,
}, },
mannings: { mannings: {
matching: manningsForStep, matching: manningsForStep.slice(0, 1),
other: [], other: manningsForStep.slice(1),
forComparison: manningsForComparison, forComparison: manningsForComparison,
}, },
'wollongong-city': { 'wollongong-city': {