// Maison Yeya — Appointments multi-step modal function AppointmentModal({ open, onClose, savedItems, onRemoveSaved }) { const [step, setStep] = useState(0); const [data, setData] = useState({ occasion: "", fullName: "", email: "", phone: "", eventDate: "", preferredDate: "", preferredTime: "Morning", notes: "", ack: false }); const [done, setDone] = useState(false); useEffect(() => { if (!open) return; document.body.style.overflow = "hidden"; const onKey = (e) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => { document.body.style.overflow = ""; window.removeEventListener("keydown", onKey); }; }, [open, onClose]); // Reset state when re-opened after completion useEffect(() => { if (open && done) { setTimeout(() => { setDone(false); setStep(0); }, 200); } }, [open]); if (!open) return null; const set = (k, v) => setData(d => ({ ...d, [k]: v })); const steps = [ { id: "occasion", label: "Occasion", valid: () => !!data.occasion }, { id: "details", label: "Details", valid: () => data.fullName.trim() && data.email.trim() && data.phone.trim() }, { id: "schedule", label: "Schedule", valid: () => !!data.preferredDate }, { id: "review", label: "Review", valid: () => data.ack } ]; const next = () => { if (!steps[step].valid()) return; if (step === steps.length - 1) { setDone(true); return; } setStep(s => s + 1); }; const back = () => setStep(s => Math.max(0, s - 1)); return (
{/* Left: image rail */} {/* Right: form */}
{done ? ( ) : ( <> {step === 0 && } {step === 1 && } {step === 2 && } {step === 3 && }
{steps[step].valid() ? "Looks good." : "Complete the fields above to continue."}
{step > 0 && }
)}
); } // ─── Step 1: Occasion ─── function StepOccasion({ data, set, savedItems }) { const opts = [ { id: "bridal", label: "Bridal Couture", note: "Wedding gown, second look, full bridal couture privée." }, { id: "couture", label: "Couture · Evening", note: "Eveningwear, red-carpet, premiere or gala." }, { id: "made-to-meas", label: "Made-to-Measure", note: "A bespoke commission outside scheduled collections." }, { id: "press", label: "Press / Styling", note: "Editorial, red-carpet, or stylist enquiry." } ]; return (
01 · Occasion

What brings you to the Maison?

{opts.map(o => ( ))}
{savedItems.length > 0 && (
{savedItems.length} saved look{savedItems.length > 1 ? "s" : ""} will accompany your enquiry.
)}
); } // ─── Step 2: Details ─── function StepDetails({ data, set }) { return (
02 · Your Details

Tell us who is enquiring.

set("fullName", e.target.value)} placeholder="Mrs. ..."/>
set("email", e.target.value)} placeholder="you@example.com"/>
set("phone", e.target.value)} placeholder="+971 ..."/>
set("eventDate", e.target.value)}/>
); } // ─── Step 3: Schedule ─── function StepSchedule({ data, set }) { // Generate next 21 days, skip Fridays (Dubai closure) const days = useMemo(() => { const out = []; const today = new Date(); today.setHours(0, 0, 0, 0); for (let i = 1; i < 30 && out.length < 14; i++) { const d = new Date(today); d.setDate(today.getDate() + i); if (d.getDay() === 5) continue; // Friday closed out.push(d); } return out; }, []); const timeSlots = ["Morning · 10:00 – 12:00", "Midday · 12:00 – 14:00", "Afternoon · 14:00 – 16:00", "Evening · 16:00 – 18:00"]; return (
03 · Schedule

Choose a preferred date.

Showroom hours: 10:00 – 18:00. Closed Fridays and UAE public holidays.

{days.map(d => { const iso = d.toISOString().slice(0, 10); const sel = data.preferredDate === iso; return ( ); })}
Preferred Time
{timeSlots.map(t => ( ))}
); } // ─── Step 4: Review ─── function StepReview({ data, set, savedItems, onRemoveSaved }) { const occasionLabels = { bridal: "Bridal Couture", couture: "Couture · Evening", "made-to-meas": "Made-to-Measure", press: "Press / Styling" }; const dateLabel = data.preferredDate ? new Date(data.preferredDate).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }) : "—"; return (
04 · Review

Confirm and send.

{data.eventDate && }