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>
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
import { useState } from 'react';
|
|
import { Navigate, useNavigate, useParams } from 'react-router-dom';
|
|
import { PackagesStep } from '../../../../components/pages/PackagesStep';
|
|
import { providersById, toPackagesStepProvider } from '../../../shared/fixtures/providers';
|
|
import {
|
|
packagesByProvider,
|
|
makeBasketKey,
|
|
nearbyVerifiedProviders,
|
|
} from '../../../shared/fixtures/packages';
|
|
import { useComparisonBasket } from '../../../shared/state/useComparisonBasket';
|
|
import { demoNav } from '../DemoNav';
|
|
|
|
export function PackagesRoute() {
|
|
const { providerId = '' } = useParams();
|
|
const navigate = useNavigate();
|
|
const provider = providersById[providerId];
|
|
const bundle = packagesByProvider[providerId];
|
|
const basket = useComparisonBasket();
|
|
|
|
const [selectedId, setSelectedId] = useState<string | null>(bundle?.matching[0]?.id ?? null);
|
|
|
|
if (!provider || !bundle) return <Navigate to="/" replace />;
|
|
|
|
// Compare CTA on the PackageDetail panel toggles the selection in the
|
|
// basket — adds when absent, removes when present. The button's visible
|
|
// state (Compare / Added + ✓) reflects `isSelectedInCart` below. The
|
|
// floating CompareBar (mounted in App.tsx) handles navigation once the
|
|
// user has 2+ packages selected.
|
|
const handleCompare = () => {
|
|
if (selectedId) basket.toggle(makeBasketKey(provider.id, selectedId));
|
|
};
|
|
|
|
// When the selected package is already in the basket, PackageDetail swaps
|
|
// the Compare button into its "In comparison" selected state.
|
|
const isSelectedInCart = selectedId ? basket.has(makeBasketKey(provider.id, selectedId)) : false;
|
|
|
|
// Tier-3 / tier-2 providers show verified-provider MiniCards instead of
|
|
// "more from this provider". Exclude the current provider from the
|
|
// "similar" list in case we ever add a verified id that collides.
|
|
const secondaryList =
|
|
provider.tier === 'verified'
|
|
? { kind: 'same-provider-more' as const, packages: bundle.other }
|
|
: {
|
|
kind: 'nearby-verified' as const,
|
|
providers: nearbyVerifiedProviders.filter((p) => p.id !== provider.id),
|
|
};
|
|
|
|
const secondaryHasItems =
|
|
secondaryList.kind === 'same-provider-more'
|
|
? secondaryList.packages.length > 0
|
|
: secondaryList.providers.length > 0;
|
|
|
|
return (
|
|
<PackagesStep
|
|
provider={toPackagesStepProvider(provider)}
|
|
providerTier={provider.tier}
|
|
packages={bundle.matching}
|
|
secondaryList={secondaryHasItems ? secondaryList : undefined}
|
|
selectedPackageId={selectedId}
|
|
onSelectPackage={setSelectedId}
|
|
onArrange={() =>
|
|
alert(
|
|
provider.tier === 'verified'
|
|
? 'Make Arrangement — would route to next wizard step.'
|
|
: 'Make an enquiry — would open enquiry form.',
|
|
)
|
|
}
|
|
onCompare={handleCompare}
|
|
isSelectedPackageInCart={isSelectedInCart}
|
|
onNearbyProviderClick={(id) => navigate(`/providers/${id}/packages`)}
|
|
onProviderClick={() => alert('Provider profile — not built in this demo slice.')}
|
|
onBack={() => navigate('/')}
|
|
navigation={demoNav}
|
|
/>
|
|
);
|
|
}
|