/* ─── Quote Modal: configurable wizard ────────────────────────── Configuration comes from window.HOOPOE_QUOTE (defined in index.html). - services: list of options shown in step 1 - showServiceStep: hide step 1 entirely (becomes a 2-step wizard) - timelines / budgets: chips in the scope step ───────────────────────────────────────────────────────────────── */ function _getQuoteConfig() { const c = window.HOOPOE_QUOTE || {}; return { services: c.services || [], showServiceStep: c.showServiceStep !== false, timelines: c.timelines || ['< 1 week', '1–2 weeks', '2–4 weeks', '1–3 months', 'Flexible'], budgets: c.budgets || ['Under AED 5K', 'AED 5–25K', 'AED 25–100K', 'AED 100K+', 'Not sure'], }; } function QuoteModal({ open, onClose, initialService }) { const cfg = _getQuoteConfig(); const QUOTE_SERVICES = cfg.services; const TIMELINE_OPTIONS = cfg.timelines; const BUDGET_OPTIONS = cfg.budgets; // Build the active step list based on config const stepDefs = [ cfg.showServiceStep ? 'services' : null, 'scope', 'contact', ].filter(Boolean); const totalSteps = stepDefs.length; const [stepIdx, setStepIdx] = React.useState(0); const stepKey = stepDefs[stepIdx]; const [data, setData] = React.useState({ services: [], timeline: '', budget: '', name: '', email: '', phone: '', company: '', notes: '', }); React.useEffect(() => { if (open) { setStepIdx(0); setData(d => ({ ...d, services: initialService ? [initialService] : [] })); } }, [open, initialService]); React.useEffect(() => { if (!open) return; const onKey = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); document.body.style.overflow = 'hidden'; return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; }; }, [open, onClose]); if (!open) return null; const toggleService = (id) => { setData(d => ({ ...d, services: d.services.includes(id) ? d.services.filter(s => s !== id) : [...d.services, id] })); }; const submitted = stepIdx >= totalSteps; const progress = submitted ? 100 : ((stepIdx + 1) / totalSteps) * 100; const canAdvance = (stepKey === 'services' && data.services.length > 0) || (stepKey === 'scope' && data.timeline && data.budget) || (stepKey === 'contact' && data.name && data.email); const next = () => stepIdx < totalSteps - 1 ? setStepIdx(stepIdx + 1) : submit(); const prev = () => stepIdx > 0 ? setStepIdx(stepIdx - 1) : onClose(); const submit = () => setStepIdx(totalSteps); const serviceLabel = (id) => (QUOTE_SERVICES.find(x => x.id === id) || {}).label || id; return (
e.target === e.currentTarget && onClose()}>
{!submitted ? <>Step {stepIdx + 1} / {totalSteps} · Request a Quote : <>Submitted}
{stepKey === 'services' && ( <>

What can we build for you?

Select one or more services. You can refine the details next.

{QUOTE_SERVICES.map(s => ( ))}
)} {stepKey === 'scope' && ( <>

Project scope

Helps us route your enquiry to the right team and reply with accurate lead times.

{TIMELINE_OPTIONS.map(t => ( ))}
{BUDGET_OPTIONS.map(t => ( ))}