/* --- Panos Melekkis · multi-step booking modal --- */ const D3 = window.PM_DATA; const INTERESTS = [ { id: "bespoke", ti: "Bespoke", sub: "Custom design" }, { id: "bridal", ti: "Engagement & Bridal", sub: "Rings, bands, sets" }, { id: "collection", ti: "A collection piece", sub: "From the shop" }, { id: "redesign", ti: "Redesign", sub: "Heirloom stones" }, ]; const LOCATIONS = [ { id: "dubai", ti: "Dubai d3", sub: "By appointment" }, { id: "cyprus", ti: "Limassol HQ", sub: "Boutique hours" }, { id: "video", ti: "Video call", sub: "International" }, ]; function BookingModal({ open, onClose }) { const [step, setStep] = React.useState(0); const [data, setData] = React.useState({ interest: null, location: null, name: "", email: "", phone: "", date: null, // ISO date time: null, notes: "", }); const TIMES = ["10:00", "11:30", "14:00", "15:30", "17:00"]; // make a 14-day date grid starting today const dateGrid = React.useMemo(() => { const today = new Date(); today.setHours(0, 0, 0, 0); return Array.from({ length: 14 }, (_, i) => { const d = new Date(today); d.setDate(today.getDate() + i); return d; }); }, []); React.useEffect(() => { if (open) { document.body.classList.add("is-locked"); } else { document.body.classList.remove("is-locked"); // reset after exit animation const t = setTimeout(() => { setStep(0); }, 380); return () => clearTimeout(t); } return () => document.body.classList.remove("is-locked"); }, [open]); React.useEffect(() => { if (!open) return; const onKey = (e) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [open, onClose]); const set = (k, v) => setData((d) => ({ ...d, [k]: v })); const steps = [ { key: "interest", lab: "Interest" }, { key: "location", lab: "Where" }, { key: "datetime", lab: "When" }, { key: "contact", lab: "Contact" }, { key: "review", lab: "Confirm" }, ]; const canNext = (() => { if (step === 0) return !!data.interest; if (step === 1) return !!data.location; if (step === 2) return !!data.date && !!data.time; if (step === 3) return !!data.name && (!!data.email || !!data.phone); if (step === 4) return true; return false; })(); const isFinal = step === steps.length; // post-confirm state const next = () => { if (step === steps.length - 1) setStep(step + 1); // go to "submitted" else setStep(step + 1); }; const back = () => setStep(Math.max(0, step - 1)); const summary = (k) => { if (k === "interest") return data.interest ? INTERESTS.find(i => i.id === data.interest).ti : "—"; if (k === "location") return data.location ? LOCATIONS.find(i => i.id === data.location).ti : "—"; if (k === "datetime") { if (!data.date) return "—"; const d = new Date(data.date); return d.toLocaleDateString(undefined, { weekday: "short", day: "numeric", month: "long" }) + (data.time ? ` · ${data.time}` : ""); } if (k === "contact") return [data.name, data.email, data.phone].filter(Boolean).join(" · "); if (k === "notes") return data.notes || "—"; return "—"; }; const fmtDay = (d) => d.toLocaleDateString(undefined, { weekday: "short" }).slice(0, 2).toUpperCase(); const fmtNum = (d) => d.getDate(); const fmtMonth = (d) => d.toLocaleDateString(undefined, { month: "short" }); const waMessage = () => { const lines = [ `Hello — I'd like to book a consultation.`, `Interest: ${summary("interest")}.`, `Location: ${summary("location")}.`, `When: ${summary("datetime")}.`, `Name: ${data.name || ""}.`, data.notes ? `Notes: ${data.notes}` : null, ].filter(Boolean).join("\n"); return encodeURIComponent(lines); }; return (
A consultation is approximately 60 minutes. Tell us which conversation to prepare for.
Both ateliers are private. The Dubai d3 studio is appointment-only; the Limassol boutique sees walk-ins during opening hours but consultations are reserved.
Pick any day in the next two weeks. We confirm the exact slot by WhatsApp within the same business day.
We need one of email or phone. We use WhatsApp for confirmations — most clients prefer it.
A WhatsApp confirmation goes to +357 96060772 the moment you submit. You'll hear back from Panos personally within the same business day.
A confirmation message has been sent. Panos will write back within the same business day to confirm your {summary("datetime")} {summary("location")} consultation — and to ask any preparation questions about your piece.