/* global React, TREATMENTS, CATEGORIES, CLINIC, IconClose, IconArrow, IconArrowLeft, IconCheck, IconSparkle, IconAligner, IconImplant, IconLeaf, IconTooth, IconCalendar */ const TX_GROUPS = [ { id: "Cosmetic", icon: IconSparkle, label: "Cosmetic", desc: "Veneers, whitening, smile makeover" }, { id: "Orthodontics", icon: IconAligner, label: "Orthodontics", desc: "Invisalign, braces, retainers" }, { id: "Implants", icon: IconImplant, label: "Implants & Restoration", desc: "Implants, crowns, dentures" }, { id: "General", icon: IconLeaf, label: "General & Preventive", desc: "Check-up, cleaning, root canal" } ]; // generate a synthetic next-7-days set, excluding Friday (likely closed) function nextDays(n = 7) { const out = []; const today = new Date(2026, 4, 22); // anchored to keep prototype deterministic let cursor = new Date(today); while (out.length < n) { cursor.setDate(cursor.getDate() + 1); if (cursor.getDay() === 5) continue; // skip Friday out.push(new Date(cursor)); } return out; } const DAYS = nextDays(5); const WEEKDAY = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; const MONTH = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; const TIME_SLOTS = ["10:00","10:30","11:00","11:30","12:00","12:30","14:30","15:00","15:30","16:00","16:30","17:00","17:30","18:00"]; // pretend some are taken const TAKEN = new Set(["11:00","12:30","15:30","18:00"]); function BookingModal({ open, onClose, prefillTreatment }) { const [step, setStep] = React.useState(0); const [form, setForm] = React.useState({ category: "Cosmetic", treatment: null, day: 1, time: "15:00", name: "", phone: "", email: "", message: "", consent: false }); // Sync the category when a treatment is prefilled React.useEffect(() => { if (open && prefillTreatment) { const tx = TREATMENTS.find(t => t.id === prefillTreatment); if (tx) setForm(f => ({ ...f, category: tx.cat, treatment: tx.id })); } }, [open, prefillTreatment]); React.useEffect(() => { if (!open) { // tiny delay so the close animation finishes before resetting const t = setTimeout(() => { setStep(0); }, 240); return () => clearTimeout(t); } document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = ""; }; }, [open]); const set = (patch) => setForm(f => ({ ...f, ...patch })); const steps = [ { id: 0, t: "What brings you in?", sub: "Pick a category — we'll match it to the right dentist." }, { id: 1, t: "Choose a date & time", sub: "Provisional slots; the clinic will confirm by phone." }, { id: 2, t: "Your details", sub: "We only need a phone number to confirm — the rest is optional." }, { id: 3, t: "Confirm your booking", sub: "Last look. We’ll text and call to confirm." } ]; const filteredTx = TREATMENTS.filter(t => t.cat === form.category); const canAdvance = (() => { if (step === 0) return !!form.category; if (step === 1) return form.day !== null && form.time; if (step === 2) return form.name.trim().length > 1 && /^[+\d\s()-]{7,}$/.test(form.phone) && form.consent; return true; })(); const submit = () => setStep(4); return (
e.stopPropagation()} role="dialog" aria-modal="true">
Step {Math.min(step, 3) + 1} of 4
{step <= 3 && (

{steps[step].t}

{steps[step].sub}

)} {/* STEP 0 — category & treatment */} {step === 0 && (
{TX_GROUPS.map(g => { const Icon = g.icon; return ( ); })}
)} {/* STEP 1 — calendar */} {step === 1 && (
{DAYS.map((d, i) => ( ))}
Available times — {WEEKDAY[DAYS[form.day].getDay()]} {DAYS[form.day].getDate()} {MONTH[DAYS[form.day].getMonth()]}
{TIME_SLOTS.map(t => { const taken = TAKEN.has(t); return ( ); })}
Heads up: these are placeholder slots until the clinic confirms its working calendar — the team will phone you within 1 working day to lock the time.
)} {/* STEP 2 — details */} {step === 2 && (
set({ name: e.target.value })} placeholder="e.g. Sarah Ahmadi" />
set({ phone: e.target.value })} placeholder="+971 50 000 0000" />
set({ email: e.target.value })} placeholder="you@example.com" />