diff --git a/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.stories.tsx b/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.stories.tsx new file mode 100644 index 0000000..8ee3154 --- /dev/null +++ b/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.stories.tsx @@ -0,0 +1,150 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { UnverifiedProviderStep } from './UnverifiedProviderStep'; +import type { RecommendedProvider, ProviderDetail } from './UnverifiedProviderStep'; +import { Navigation } from '../../organisms/Navigation'; +import Box from '@mui/material/Box'; + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +const FALogo = () => ( + + + + +); + +const nav = ( + } + items={[ + { label: 'FAQ', href: '/faq' }, + { label: 'Contact Us', href: '/contact' }, + { label: 'Log in', href: '/login' }, + ]} + /> +); + +const knownDetails: ProviderDetail[] = [ + { label: 'Estimated pricing', value: 'From approximately $750' }, + { label: 'Services', value: 'Cremation, Service & Cremation, Burial' }, + { label: 'Service area', value: 'Wollongong & surrounding suburbs' }, +]; + +const minimalDetails: ProviderDetail[] = [ + { label: 'Estimated pricing', value: 'From approximately $750' }, +]; + +const recommendedProviders: RecommendedProvider[] = [ + { + id: 'parsons', + name: 'H.Parsons Funeral Directors', + location: 'Wentworth, NSW', + imageUrl: 'https://placehold.co/600x200/E8E0D6/8B6F47?text=H.Parsons', + logoUrl: 'https://placehold.co/64x64/FEF9F5/BA834E?text=HP', + rating: 4.6, + reviewCount: 7, + startingPrice: 900, + }, + { + id: 'rankins', + name: 'Rankins Funeral Services', + location: 'Wollongong, NSW', + imageUrl: 'https://placehold.co/600x200/D7E1E2/4C5B6B?text=Rankins', + logoUrl: 'https://placehold.co/64x64/F2F5F6/4C5B6B?text=R', + rating: 4.8, + reviewCount: 23, + startingPrice: 1200, + }, +]; + +// ─── Meta ──────────────────────────────────────────────────────────────────── + +const meta: Meta = { + title: 'Pages/UnverifiedProviderStep', + component: UnverifiedProviderStep, + tags: ['autodocs'], + parameters: { + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +// ─── With known details + recommendations ─────────────────────────────────── + +/** Full data — pricing, services, and verified alternatives */ +export const Default: Story = { + args: { + providerName: 'Wollongong City Funerals', + providerLocation: 'Wollongong, NSW', + providerRating: 4.2, + providerReviewCount: 15, + details: knownDetails, + recommendations: recommendedProviders, + recommendationContext: 'near Wollongong', + onEnquire: () => alert('Enquiry submitted'), + onSelectRecommendation: (id) => alert(`Navigate to provider: ${id}`), + onBack: () => alert('Back to providers'), + navigation: nav, + }, +}; + +// ─── Minimal data ─────────────────────────────────────────────────────────── + +/** Only rough pricing available — no services, no reviews */ +export const MinimalData: Story = { + args: { + providerName: 'Botanical Funerals', + providerLocation: 'Newtown, NSW', + details: minimalDetails, + recommendations: recommendedProviders, + recommendationContext: 'near Newtown', + onEnquire: () => alert('Enquiry submitted'), + onSelectRecommendation: (id) => alert(`Navigate to provider: ${id}`), + onBack: () => alert('Back to providers'), + navigation: nav, + }, +}; + +// ─── No data at all ───────────────────────────────────────────────────────── + +/** No scraped data — just the name and location */ +export const NoData: Story = { + args: { + providerName: 'Smith & Sons Funerals', + providerLocation: 'Penrith, NSW', + recommendations: recommendedProviders, + recommendationContext: 'near Penrith', + onEnquire: () => alert('Enquiry submitted'), + onSelectRecommendation: (id) => alert(`Navigate to provider: ${id}`), + onBack: () => alert('Back to providers'), + navigation: nav, + }, +}; + +// ─── No recommendations ───────────────────────────────────────────────────── + +/** No verified alternatives available for this area */ +export const NoRecommendations: Story = { + args: { + providerName: 'Wollongong City Funerals', + providerLocation: 'Wollongong, NSW', + providerRating: 4.2, + providerReviewCount: 15, + details: knownDetails, + onEnquire: () => alert('Enquiry submitted'), + onBack: () => alert('Back to providers'), + navigation: nav, + }, +}; diff --git a/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.tsx b/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.tsx new file mode 100644 index 0000000..ba7306a --- /dev/null +++ b/src/components/pages/UnverifiedProviderStep/UnverifiedProviderStep.tsx @@ -0,0 +1,239 @@ +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 { WizardLayout } from '../../templates/WizardLayout'; +import { ProviderCardCompact } from '../../molecules/ProviderCardCompact'; +import { ProviderCard } from '../../molecules/ProviderCard'; +import { Badge } from '../../atoms/Badge'; +import { Button } from '../../atoms/Button'; +import { Card } from '../../atoms/Card'; +import { Typography } from '../../atoms/Typography'; +import { Divider } from '../../atoms/Divider'; + +// ─── Types ─────────────────────────────────────────────────────────────────── + +/** A piece of known information about the unverified provider */ +export interface ProviderDetail { + /** Label (e.g. "Estimated pricing") */ + label: string; + /** Value (e.g. "From approximately $750") */ + value: string; +} + +/** A verified provider recommendation */ +export interface RecommendedProvider { + id: string; + name: string; + location: string; + imageUrl?: string; + logoUrl?: string; + rating?: number; + reviewCount?: number; + startingPrice?: number; +} + +/** Props for the UnverifiedProviderStep page */ +export interface UnverifiedProviderStepProps { + /** Provider display name */ + providerName: string; + /** Provider location */ + providerLocation: string; + /** Average rating (if available from reviews) */ + providerRating?: number; + /** Number of reviews */ + providerReviewCount?: number; + /** Known details — only sections with data are rendered */ + details?: ProviderDetail[]; + /** Callback when "Make an Enquiry" is clicked */ + onEnquire: () => void; + /** Whether the enquiry is being submitted */ + enquiryLoading?: boolean; + /** Verified provider recommendations matching the user's search */ + recommendations?: RecommendedProvider[]; + /** Label for the recommendations section (e.g. "near Wollongong") */ + recommendationContext?: string; + /** Callback when a recommended provider is clicked */ + onSelectRecommendation?: (id: string) => void; + /** Callback for back navigation */ + onBack: () => void; + /** Navigation bar */ + navigation?: React.ReactNode; + /** Progress stepper */ + progressStepper?: React.ReactNode; + /** Running total widget */ + runningTotal?: React.ReactNode; + /** MUI sx prop */ + sx?: SxProps; +} + +// ─── Component ─────────────────────────────────────────────────────────────── + +/** + * Unverified provider detail page for the FA arrangement wizard. + * + * Shown when a user selects an unverified (scraped) provider from + * the ProvidersStep. Displays whatever information we have, offers + * an enquiry CTA, and recommends verified alternatives. + * + * Uses centered-form layout — single column, focused experience. + * No package selection, no arrangement flow. + * + * Pure presentation component — props in, callbacks out. + */ +export const UnverifiedProviderStep: React.FC = ({ + providerName, + providerLocation, + providerRating, + providerReviewCount, + details = [], + onEnquire, + enquiryLoading = false, + recommendations = [], + recommendationContext, + onSelectRecommendation, + onBack, + navigation, + progressStepper, + runningTotal, + sx, +}) => { + return ( + + {/* ── Provider header ── */} + + + + }> + Listing + + + + + {/* ── Available information ── */} + {details.length > 0 && ( + + + What we know + + + {details.map((detail) => ( + + + {detail.label} + + + {detail.value} + + + ))} + + + Based on publicly available information. Pricing and services may vary. + + + )} + + {/* ── Enquiry CTA ── */} + + + Interested in {providerName}? + + + We’ll pass your details along so they can reach out to you directly. No commitment + required. + + + + + {/* ── Verified recommendations ── */} + {recommendations.length > 0 && ( + <> + + + + + Verified providers{recommendationContext ? ` ${recommendationContext}` : ''} + + + Full online arrangement with transparent pricing + + + + {recommendations.map((provider) => ( + onSelectRecommendation(provider.id) : undefined + } + /> + ))} + + + + )} + + ); +}; + +UnverifiedProviderStep.displayName = 'UnverifiedProviderStep'; +export default UnverifiedProviderStep; diff --git a/src/components/pages/UnverifiedProviderStep/index.ts b/src/components/pages/UnverifiedProviderStep/index.ts new file mode 100644 index 0000000..c70b088 --- /dev/null +++ b/src/components/pages/UnverifiedProviderStep/index.ts @@ -0,0 +1,2 @@ +export { default } from './UnverifiedProviderStep'; +export * from './UnverifiedProviderStep';