import React from 'react'; import Box from '@mui/material/Box'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import IconButton from '@mui/material/IconButton'; import TextField from '@mui/material/TextField'; import MenuItem from '@mui/material/MenuItem'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import CloseIcon from '@mui/icons-material/Close'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import GoogleIcon from '@mui/icons-material/Google'; import MicrosoftIcon from '@mui/icons-material/Window'; import type { SxProps, Theme } from '@mui/material/styles'; import type { PackageSection } from '../PackageDetail'; import { ProviderCardCompact } from '../../molecules/ProviderCardCompact'; import { Collapse } from '../../atoms/Collapse'; import { Typography } from '../../atoms/Typography'; import { Button } from '../../atoms/Button'; import { Divider } from '../../atoms/Divider'; // ─── Types ─────────────────────────────────────────────────────────────────── /** Which step of the dialog is active */ export type DialogStep = 'preview' | 'auth'; /** Provider summary */ export interface DialogProvider { name: string; location: string; imageUrl?: string; rating?: number; reviewCount?: number; } /** Package summary for preview */ export interface DialogPackage { name: string; price: number; sections: PackageSection[]; total?: number; } /** A step in the "What's next?" checklist */ export interface NextStepItem { number: number; label: string; } /** Auth sub-step */ export type AuthSubStep = 'email' | 'details' | 'verify'; /** Contact preference */ export type ContactPreference = 'call_anytime' | 'email_preferred' | 'email_only'; /** Auth form values */ export interface AuthValues { subStep: AuthSubStep; email: string; firstName: string; lastName: string; phone: string; contactPreference: ContactPreference; verificationCode: string; } /** Auth field errors */ export interface AuthErrors { email?: string; firstName?: string; lastName?: string; phone?: string; verificationCode?: string; } /** Props for the ArrangementDialog */ export interface ArrangementDialogProps { /** Whether the dialog is open */ open: boolean; /** Callback when the dialog is closed */ onClose: () => void; /** Current dialog step */ step: DialogStep; /** Callback when the step changes */ onStepChange: (step: DialogStep) => void; // ─── Preview data ─── /** Provider summary */ provider: DialogProvider; /** Selected package */ selectedPackage: DialogPackage; /** What's next checklist */ nextSteps?: NextStepItem[]; /** Pre-planning flow */ isPrePlanning?: boolean; /** Callback for "Explore other options" (pre-planning) */ onExplore?: () => void; // ─── Auth data ─── /** Auth form values */ authValues: AuthValues; /** Callback when auth values change */ onAuthChange: (values: AuthValues) => void; /** Auth field errors */ authErrors?: AuthErrors; /** Callback for Google SSO */ onGoogleSSO?: () => void; /** Callback for Microsoft SSO */ onMicrosoftSSO?: () => void; // ─── Actions ─── /** Callback when the final auth CTA is clicked */ onContinue: () => void; /** Loading state for CTAs */ loading?: boolean; /** MUI sx prop */ sx?: SxProps; } // ─── Constants ────────────────────────────────────────────────────────────── const DEFAULT_NEXT_STEPS: NextStepItem[] = [ { number: 1, label: 'Create your account to save your selections' }, { number: 2, label: 'Choose a date and time for the service' }, { number: 3, label: 'Select a venue' }, { number: 4, label: 'Choose a coffin' }, { number: 5, label: 'Review and confirm your arrangement' }, ]; // ─── Helpers ──────────────────────────────────────────────────────────────── function getAuthCTALabel(subStep: AuthSubStep): string { switch (subStep) { case 'email': return 'Continue with email'; case 'details': return 'Continue'; case 'verify': return 'Verify and continue'; } } // ─── Component ─────────────────────────────────────────────────────────────── /** * Two-step arrangement dialog (D-E). * * Consolidates PreviewStep + AuthGateStep into a single modal: * - **Step 1 (preview):** Package summary, provider info, "What's next" checklist * - **Step 2 (auth):** SSO buttons, email entry, details, verification * * The dialog is opened after a user selects a package (from PackagesStep). * The parent controls which step is shown and manages auth form state. * * Pure presentation component — props in, callbacks out. */ export const ArrangementDialog: React.FC = ({ open, onClose, step, onStepChange, provider, selectedPackage, nextSteps = DEFAULT_NEXT_STEPS, isPrePlanning = false, onExplore, authValues, onAuthChange, authErrors, onGoogleSSO, onMicrosoftSSO, onContinue, loading = false, sx, }) => { const isEmailOnly = authValues.contactPreference === 'email_only'; const handleAuthField = (field: keyof AuthValues, value: string) => { onAuthChange({ ...authValues, [field]: value }); }; return ( {/* ─── Header ─── */} {step === 'auth' && ( onStepChange('preview')} aria-label="Back to preview" > )} {step === 'preview' ? 'Your selected package' : 'Save your plan'} {/* ═══════════ Step 1: Preview ═══════════ */} {step === 'preview' && ( {/* Provider */} {/* Package summary */} {selectedPackage.name} ${(selectedPackage.total ?? selectedPackage.price).toLocaleString('en-AU')} {selectedPackage.sections.map((section) => ( {section.heading} {section.items.map((item) => ( {item.name} ))} ))} You'll be able to customise everything in the next steps. {/* What's next */} What happens next {nextSteps.map((s) => ( {s.number} ))} {/* CTAs */} {isPrePlanning && onExplore && ( )} )} {/* ═══════════ Step 2: Auth ═══════════ */} {step === 'auth' && ( { e.preventDefault(); if (!loading) onContinue(); }} > {isPrePlanning ? 'Save your plan to return and update it anytime.' : 'We need a few details so a funeral arranger can help you with the next steps.'} {/* SSO buttons */} or {/* Email */} handleAuthField('email', e.target.value)} error={!!authErrors?.email} helperText={authErrors?.email} placeholder="you@example.com" autoComplete="email" inputMode="email" fullWidth required disabled={authValues.subStep !== 'email'} sx={{ mb: 3 }} /> {/* Details (after email) */} A few details to save your plan handleAuthField('firstName', e.target.value)} error={!!authErrors?.firstName} helperText={authErrors?.firstName} autoComplete="given-name" fullWidth required disabled={authValues.subStep === 'verify'} /> handleAuthField('lastName', e.target.value)} error={!!authErrors?.lastName} helperText={authErrors?.lastName} autoComplete="family-name" fullWidth required disabled={authValues.subStep === 'verify'} /> handleAuthField('phone', e.target.value)} error={!!authErrors?.phone} helperText={authErrors?.phone} placeholder="e.g. 0412 345 678" autoComplete="tel" inputMode="tel" fullWidth required={!isEmailOnly} disabled={authValues.subStep === 'verify'} /> handleAuthField('contactPreference', e.target.value)} fullWidth disabled={authValues.subStep === 'verify'} > Call me anytime Email is preferred Only contact by email {/* Verification */} We've sent a 6-digit code to {authValues.email}. Please enter it below. handleAuthField('verificationCode', e.target.value)} error={!!authErrors?.verificationCode} helperText={ authErrors?.verificationCode || 'Check your email for the 6-digit code' } placeholder="Enter 6-digit code" autoComplete="one-time-code" inputMode="numeric" fullWidth required /> {/* Terms */} By continuing, you agree to the{' '} terms and conditions . {/* CTA */} )} ); }; ArrangementDialog.displayName = 'ArrangementDialog'; export default ArrangementDialog;