/* global React, FLEET */ const { useState, useMemo } = React; /* ============================================================ BOOKING — multi-step quote with live recommendation ============================================================ */ function BookingFlow() { const [step, setStep] = useState(0); const [data, setData] = useState({ from: 'PRG', fromName: 'Prague', to: 'LCY', toName: 'London City', distance: 1050, date: '2026-05-12', time: '09:00', pax: 4, aircraft: null, catering: 'standard', extras: [], }); const update = (k, v) => setData(d => ({ ...d, [k]: v })); // recommend aircraft based on pax + distance const recommended = useMemo(() => { const candidates = window.FLEET.filter(a => { const rangeKm = parseInt(a.range.replace(/[,\s]/g, '')); return a.seats >= data.pax && rangeKm >= data.distance * 1.15; }); return candidates.sort((a, b) => a.seats - b.seats).slice(0, 3); }, [data.pax, data.distance]); // estimated price (rough — for prototype only) const priceEst = useMemo(() => { const a = data.aircraft || recommended[0]; if (!a) return 0; const ratePerKm = { 'learjet-75': 9, 'gulfstream-g200': 11, 'gulfstream-g280': 13, 'challenger-605': 15, 'global-6000': 22 }; const base = (ratePerKm[a.id] || 12) * data.distance * 2; const cateringExtra = { standard: 0, premium: 1200, signature: 3500 }[data.catering] || 0; return Math.round((base + cateringExtra) / 100) * 100; }, [data.aircraft, data.catering, data.distance, recommended]); const steps = ['Route', 'Passengers', 'Aircraft', 'Details', 'Quote']; const next = () => setStep(s => Math.min(s + 1, steps.length - 1)); const prev = () => setStep(s => Math.max(s - 1, 0)); return (
04 — Instant quote

Plan your
flight in five steps.

Tell us where, when and how many — we'll suggest the right aircraft and a live price band. A real dispatcher confirms within four working hours.

{/* LEFT — form */}
{/* Step bar */}
{steps.map((s, i) => (
0{i + 1} {s}
))}
{/* Step content */}
{step === 0 && (

Where to?

update('from', v.toUpperCase())} mono/> update('to', v.toUpperCase())} mono/> update('date', v)}/> update('time', v)}/>
{[ ['PRG → LCY', 1050, 'PRG', 'Prague', 'LCY', 'London City'], ['PRG → DXB', 4350, 'PRG', 'Prague', 'DXB', 'Dubai'], ['PRG → CDG', 880, 'PRG', 'Prague', 'CDG', 'Paris CDG'], ['PRG → LJU', 480, 'PRG', 'Prague', 'LJU', 'Ljubljana'], ].map(p => ( ))}
)} {step === 1 && (

How many?

Passengers
{[2, 4, 6, 8, 10, 12].map(n => ( ))}
With {data.pax} passengers and a leg of {data.distance} km, we have {recommended.length} aircraft that fit.
)} {step === 2 && (

Pick your aircraft

{recommended.length === 0 && (
No aircraft in the fleet match these requirements. Adjust passenger count or contact dispatch.
)} {recommended.map((a, i) => { const sel = (data.aircraft?.id || recommended[0]?.id) === a.id; return ( ); })}
)} {step === 3 && (

Onboard preferences

Catering
{[ { id: 'standard', t: 'Standard', d: 'Sandwiches, fresh fruit, soft drinks', p: 'Included' }, { id: 'premium', t: 'Premium', d: 'Three-course menu by Prague chef, full bar', p: '+ €1,200' }, { id: 'signature', t: 'Signature', d: 'Bespoke menu — sourced and prepped to your spec', p: '+ €3,500' }, ].map(c => { const sel = data.catering === c.id; return ( ); })}
Extras
{['VIP Lounge', 'Ground transfer', 'Pet onboard', 'Cargo hold'].map(x => { const sel = data.extras.includes(x); return ( ); })}
)} {step === 4 && (

Your estimate

Indicative. A dispatcher confirms binding price within 4 working hours.

Estimated price band
€{(priceEst * 0.92).toLocaleString('en-US', { maximumFractionDigits: 0 })} €{(priceEst * 1.08).toLocaleString('en-US', { maximumFractionDigits: 0 })}
Round trip · all taxes & fees · positioning included
)}
{/* Nav buttons */}
{step < steps.length - 1 && ( )}
{/* RIGHT — live summary */}
Your quote · LIVE
{/* Route visual */}
FROM
{data.from}
{data.fromName}
{data.distance} KM
TO
{data.to}
{data.toName}
Estimated · indicative only
€{priceEst.toLocaleString('en-US', { maximumFractionDigits: 0 })}
± 8% · all-in · round trip
); } function Field({ label, value, onChange, type = 'text', mono }) { return ( ); } function SummaryRow({ l, v }) { return (
{l} {v}
); } Object.assign(window, { BookingFlow });