diff --git a/src/components/organisms/PackageDetail/PackageDetail.stories.tsx b/src/components/organisms/PackageDetail/PackageDetail.stories.tsx index 6cd1391..cbae1aa 100644 --- a/src/components/organisms/PackageDetail/PackageDetail.stories.tsx +++ b/src/components/organisms/PackageDetail/PackageDetail.stories.tsx @@ -159,6 +159,21 @@ export const CompareLoading: Story = { }, }; +/** "In comparison" selected state — package is already in the basket. + * The Compare button is swapped for a soft-brand-tinted inert pill + * with a check icon; removal happens via the CompareBar, not here. */ +export const InCart: Story = { + args: { + name: 'Traditional Family Cremation Service', + price: 6966, + sections: [{ heading: 'Essentials', items: essentials.slice(0, 4) }], + total: 6966, + onArrange: () => alert('Make Arrangement'), + onCompare: () => {}, + inCart: true, + }, +}; + // --- Without Extras ---------------------------------------------------------- /** Simpler package with essentials and optionals only — no extras */ diff --git a/src/components/organisms/PackageDetail/PackageDetail.tsx b/src/components/organisms/PackageDetail/PackageDetail.tsx index 3211399..834af93 100644 --- a/src/components/organisms/PackageDetail/PackageDetail.tsx +++ b/src/components/organisms/PackageDetail/PackageDetail.tsx @@ -1,6 +1,7 @@ import React from 'react'; import Box from '@mui/material/Box'; import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; +import CheckRoundedIcon from '@mui/icons-material/CheckRounded'; import type { SxProps, Theme } from '@mui/material/styles'; import { Typography } from '../../atoms/Typography'; import { Button } from '../../atoms/Button'; @@ -53,6 +54,11 @@ export interface PackageDetailProps { arrangeDisabled?: boolean; /** Whether the compare button is in loading state */ compareLoading?: boolean; + /** Whether this package is already in the comparison basket. When true, + * the Compare button swaps to an "In comparison" selected-state (soft + * brand tint + check icon) and is inert — removal happens via the + * CompareBar, not this button. */ + inCart?: boolean; /** Custom label for the arrange CTA button (default: "Make Arrangement") */ arrangeLabel?: string; /** Disclaimer shown below the price (e.g. for unverified/estimated pricing) */ @@ -124,6 +130,7 @@ export const PackageDetail = React.forwardRef {arrangeLabel} - {onCompare && ( - - )} + {onCompare && + (inCart ? ( + // Selected-state: soft brand tint + check icon. Inert + // (disabled + aria-disabled) — removal happens via the + // CompareBar, not this button. sx override keeps the + // brand tint instead of the default greyed-disabled look. + + ) : ( + + ))} diff --git a/src/components/pages/PackagesStep/PackagesStep.tsx b/src/components/pages/PackagesStep/PackagesStep.tsx index 5153220..538d87b 100644 --- a/src/components/pages/PackagesStep/PackagesStep.tsx +++ b/src/components/pages/PackagesStep/PackagesStep.tsx @@ -94,6 +94,10 @@ export interface PackagesStepProps { onArrange: () => void; /** Callback when the "Compare" button on the PackageDetail panel is clicked */ onCompare?: () => void; + /** Whether the currently-selected package is already in the comparison + * basket. When true, PackageDetail swaps its Compare button into the + * "In comparison" selected-state (inert; removal via CompareBar). */ + isSelectedPackageInCart?: boolean; /** Callback when a nearby-verified package card is clicked (route change to that provider) */ onNearbyPackageClick?: (id: string) => void; /** @@ -192,6 +196,7 @@ export const PackagesStep: React.FC = ({ onSelectPackage, onArrange, onCompare, + isSelectedPackageInCart = false, onNearbyPackageClick, onSeeAllPackages, onProviderClick, @@ -275,6 +280,7 @@ export const PackagesStep: React.FC = ({ terms={selectedPackage.terms} onArrange={onArrange} onCompare={onCompare} + inCart={isSelectedPackageInCart} arrangeDisabled={loading} arrangeLabel={copy.arrangeLabel} priceDisclaimer={copy.priceDisclaimer} diff --git a/src/demo/apps/arrangement/routes/Packages.tsx b/src/demo/apps/arrangement/routes/Packages.tsx index 45c431e..69d45c3 100644 --- a/src/demo/apps/arrangement/routes/Packages.tsx +++ b/src/demo/apps/arrangement/routes/Packages.tsx @@ -23,11 +23,15 @@ export function PackagesRoute() { // Compare CTA on the PackageDetail panel just adds the selection to the // basket. The floating CompareBar (mounted in App.tsx) handles navigation - // once the user has 2+ packages selected. + // and removal once the user has 2+ packages selected. const handleCompare = () => { if (selectedId) basket.add(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 "nearby verified" cards instead of // "more from this provider". const secondaryList = @@ -51,6 +55,7 @@ export function PackagesRoute() { ) } onCompare={handleCompare} + isSelectedPackageInCart={isSelectedInCart} onNearbyPackageClick={(key) => { const [otherProviderId] = key.split(':'); if (otherProviderId) navigate(`/providers/${otherProviderId}/packages`);