// Multi-step Consultation booking modal
const INTERESTS = [
{ id: 'engagement', label: 'Engagement Ring' },
{ id: 'bespoke', label: 'Custom Design' },
{ id: 'wedding', label: 'Wedding & Eternity' },
{ id: 'diamond', label: 'A Loose Diamond' },
{ id: 'gift', label: 'A Gift' },
{ id: 'repair', label: 'Service / Repair' },
];
const BOUTIQUE_OPTS = [
{ id: 'deira', label: 'Deira Gold Souq \u00b7 Flagship' },
{ id: 'gdp', label: 'Gold & Diamond Park \u00b7 Factory Outlet' },
{ id: 'eva-gdp', label: 'Eva \u2014 Gold & Diamond Park' },
{ id: 'eva-madinat', label: 'Eva Gems \u2014 Madinat Jumeirah' },
{ id: 'video', label: 'Video Consult (WhatsApp)' },
];
const TIMES = ['10:30', '12:00', '14:00', '16:00', '17:30', '19:00'];
function todayPlus(days) {
const d = new Date();
d.setDate(d.getDate() + days);
return d;
}
function fmtDate(d) {
return d.toLocaleDateString('en-GB', { weekday: 'short', day: '2-digit', month: 'short' });
}
function fmtISO(d) {
return d.toISOString().slice(0, 10);
}
const DateChips = ({ value, onChange }) => {
const days = Array.from({ length: 7 }, (_, i) => todayPlus(i + 1));
return (
{days.map(d => {
const iso = fmtISO(d);
const on = value === iso;
return (
onChange(iso)} className={`mm-radio ${on ? 'on' : ''}`}
style={{ flex: 'none', minWidth: 0, padding: '10px 14px' }}>
{fmtDate(d)}
);
})}
);
};
const BookingModal = ({ open, onClose, prefill }) => {
const [step, setStep] = React.useState(0);
const [data, setData] = React.useState({
interest: prefill?.interest || 'engagement',
boutique: prefill?.boutique || 'deira',
date: fmtISO(todayPlus(2)),
time: '14:00',
name: '', email: '', phone: '', notes: '',
});
const [errors, setErrors] = React.useState({});
const [submitted, setSubmitted] = React.useState(false);
React.useEffect(() => {
if (open) { setStep(0); setSubmitted(false); setErrors({}); }
}, [open]);
const update = (k, v) => setData(d => ({ ...d, [k]: v }));
const validateContact = () => {
const e = {};
if (!data.name.trim()) e.name = 'Please tell us your name.';
if (!/^.+@.+\..+$/.test(data.email)) e.email = 'A valid email, please.';
if (data.phone && !/^[\d+\s\-()]{6,}$/.test(data.phone)) e.phone = 'That phone number looks off.';
setErrors(e);
return Object.keys(e).length === 0;
};
const next = () => {
if (step < 2) setStep(step + 1);
else if (step === 2) {
if (validateContact()) setSubmitted(true);
}
};
const back = () => { if (step > 0) setStep(step - 1); };
if (!open) return null;
const STEP_LABELS = ['Interest', 'When & Where', 'Your Details'];
return (
{ if (e.target === e.currentTarget) onClose(); }}>
Private Consultation
An unhurried hour at the bench.
Choose a boutique, a date and a time. One of our advisers \u2014 Abhijeet, Joyce, Sam, Joy, Rohan \u2014 will be expecting you, with coffee and the right cases pulled.
No pressure. No sales tactics.
Bring a picture, a sketch, a stone.
Bespoke designs realised in under an hour.
Authentication and warranty included.
{!submitted ? (
{STEP_LABELS.map((l, i) => (
0{i+1} {l}
))}
{step === 0 && (
)}
{step === 1 && (
Step 02 of 03
When & where
Boutique
update('boutique', e.target.value)}>
{BOUTIQUE_OPTS.map(o => {o.label} )}
Date
update('date', v)} />
Time
{TIMES.map(t => (
update('time', t)}
className={`mm-radio ${data.time === t ? 'on' : ''}`}
style={{ flex: 'none', padding: '10px 14px', fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: '0.16em' }}>
{t}
))}
)}
{step === 2 && (
Step 03 of 03
Your details
Full name
update('name', e.target.value)} placeholder="As you'd like to be greeted" />
{errors.name && {errors.name} }
Summary
{INTERESTS.find(i => i.id === data.interest)?.label}
{' \u00b7 '}
{BOUTIQUE_OPTS.find(b => b.id === data.boutique)?.label.split(' \u00b7 ')[0]}
{fmtDate(new Date(data.date))} \u00b7 {data.time}
)}
{step > 0
? Back
: }
{step < 2 ? 'Continue' : 'Confirm Booking'}
) : (
Confirmed
We'll see you, {data.name.split(' ')[0]}.
Your private consultation is booked for {fmtDate(new Date(data.date))} at {data.time} at
the {BOUTIQUE_OPTS.find(b => b.id === data.boutique)?.label.split(' \u00b7 ')[0]} boutique.
We've sent confirmation to {data.email}. An adviser will WhatsApp you the day before.
Done
Open WhatsApp
)}
);
};
Object.assign(window, { BookingModal });