The ComparisonPage's `recommendedPackage` prop was never wired in the
demo — users only saw their basket contents. Now always surface a
default recommended package (parsons:deluxe) as an extra column, deduped
against the basket so it never appears twice.
Basket mechanics are unchanged: the 3-package cap counts user selections
only, and the recommended is layered on top as an editorial suggestion.
The empty state only renders when there is genuinely nothing to show —
since the recommended is static, it's effectively defensive for a future
state where resolution could fail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
The unverified-tier "similar packages" section previously rendered a list
of NearbyPackageCards — one per package. Swap to MiniCard, showing the
provider itself: image, verified badge, location, rating, "From $X".
2-col on sm+, 1-col on xs, capped at 4. Heading dropped "nearby" to
"Similar packages from verified providers".
Data shape renamed NearbyVerifiedPackage → NearbyVerifiedProvider;
`verified` is implicit (the section is verified-only by definition).
Callback renamed onNearbyPackageClick → onNearbyProviderClick, routing
directly on provider id. Demo fixture now derives the list from the
main providers fixture (filtered to verified + imageUrl).
NearbyPackageCard is now orphaned — kept in place pending registry
cleanup in a follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces a full Google-Maps-backed provider map for the arrangement
wizard's ProvidersStep. Clicking a pin morphs it into a MapPopup at
the same coord; pins within 70px of each other collapse into a cluster
(ceiling at zoom 13) that opens a ClusterPopup list on click. Row
clicks pan + zoom the map to the provider and open their MapPopup.
Map-background click routes through an exit transition that fades the
popup out before reappearing the pin, via a matching fade-in keyframe
on the atom markers.
Key additions:
- @vis.gl/react-google-maps + @googlemaps/markerclusterer deps
- ClusterMarker atom (count badge; verified / unverified palettes)
- ClusterPopup molecule (image-free rows; verified icon aligned to
name; right-aligned "From $X" column; verified-first sort)
- ProviderMap organism (APIProvider + Map + imperative AdvancedMarker
layer via createRoot for clusterer compatibility)
Component changes:
- MapPin: promoted verified palette (brand-700); name now required;
name-only and price-only variants dropped; active prop removed in
favour of organism-level state; SVG nub with fill+stroke replaces
the CSS border-triangle trick so the outline is continuous
- MapPopup: `exiting` prop drives close animation; click events stop
propagation so the map's onClick can't clear state mid-interaction
- ProviderData type gains optional `coords`; demo fixtures populated
with real NSW/QLD lat/lng for all 7 providers
- ProvidersStep demo route wires ProviderMap into the mapPanel slot
Memory:
- docs/memory/component-registry updated (ClusterMarker, ClusterPopup,
ProviderMap added; MapPin + MapPopup refined; MapCard retired)
- docs/memory/session-log captures arc across 2026-04-21/22 and flags
next-session work: ProvidersStep polish, mobile layout for list-map
WizardLayout, and demo deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes images 404'ing under /arrangement/ — Vite's publicDir copies assets
to the build root, but the base prefix is only applied to bundled assets
(JS/CSS), not to runtime URL strings. assetUrl() helper resolves paths
against import.meta.env.BASE_URL so '/images/foo.png' becomes
'/arrangement/images/foo.png' in production while staying '/images/foo.png'
in dev.
- src/demo/shared/assets.ts — assetUrl() helper
- providers.ts + DemoNav.tsx — wrap all public asset paths
- nginx/parsons-demos.conf — swag site-conf for parsons.tensordesign.com.au
(asset cache regex above SPA fallback regex per nginx first-match rule)
- docs/reference/client-demo-deploy.md — server runbook (DNS, swag
SUBDOMAINS, mount, htpasswd, deploy loop)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a self-contained demo build target for the Providers → Packages →
Comparison flow, deployable as a static SPA at /arrangement/.
- vite.demo.config.ts: per-slice build via --mode, base path flips for
dev vs prod, output to dist-demo/<slice>/
- src/demo/: shared fixtures (7 providers across verified/tier3/tier2
with real venue photography from brandassets) + Zustand basket store
with ?compare= URL persistence
- Verified-provider packages now share the nine canonical Essentials
line items per FA convention; only Optionals/Extras vary
- App-level CompareBar surfaces "Already added" / "Maximum 3" feedback
via transient store error
- ProviderCard logo objectFit cover→contain so wide logos don't crop
- npm scripts demo:dev / demo:build, deps zustand + react-router-dom