const VEHICLES = ['Small / hatchback', 'Saloon / estate', 'SUV / 4x4', 'Van / large', 'Other']; const fieldStyle = { width: '100%', background: '#0c0c0c', border: '1px solid #2a2a2a', color: '#fff', padding: '14px 16px', fontFamily: 'var(--font-body)', fontSize: 15, borderRadius: 0, outline: 'none', transition: 'border-color .2s ease', }; const labelStyle = { display: 'block', fontFamily: 'var(--font-display)', fontSize: 11, letterSpacing: 1.4, textTransform: 'uppercase', color: 'var(--ash)', marginBottom: 9 }; function Field({ label, children, span }) { return
{children}
; } function FInput(props) { const [f, setF] = React.useState(false); return setF(true)} onBlur={() => setF(false)} style={{ ...fieldStyle, borderColor: f ? 'var(--lambo-gold)' : '#2a2a2a' }} />; } function BookingForm() { const [data, setData] = React.useState({ name: '', email: '', phone: '', service: 'Silver — Full Valet', vehicle: VEHICLES[1], make: '', date: '', postcode: '', notes: '' }); const [selectedAddons, setSelectedAddons] = React.useState(['none']); const [errors, setErrors] = React.useState({}); const [sent, setSent] = React.useState(false); const set = (k) => (e) => setData(d => ({ ...d, [k]: e.target.value })); const BOOKING_ADDONS = [ { id: 'none', label: 'No Add-Ons Required', price: '' }, ...ADDONS.map((a, i) => ({ id: 'addon-' + i, label: a.name, price: a.price })), { id: 'addon-fabric-shampoo', label: 'Fabric seat shampoo & extraction', price: 'POA' }, { id: 'addon-pet-hair', label: 'Pet hair removal', price: '£20 – £80' }, { id: 'addon-heavy-stain', label: 'Heavy stain removal', price: 'POA' }, { id: 'addon-child-seat-deep', label: 'Child seat deep clean', price: '£30' }, ]; const toggleAddon = (id) => { if (id === 'none') { setSelectedAddons(['none']); } else { setSelectedAddons(prev => { const without = prev.filter(x => x !== 'none'); if (without.includes(id)) { const next = without.filter(x => x !== id); return next.length === 0 ? ['none'] : next; } return [...without, id]; }); } }; const validate = () => { const er = {}; if (!data.name.trim()) er.name = 'Please enter your name'; if (!/^[^@]+@[^@]+\.[^@]+$/.test(data.email)) er.email = 'Enter a valid email'; if (data.phone.replace(/\D/g, '').length < 7) er.phone = 'Enter a valid phone number'; if (!data.postcode.trim()) er.postcode = 'We need your area / postcode'; if (selectedAddons.length === 0) er.addons = 'Please select at least one option'; setErrors(er); return Object.keys(er).length === 0; }; const [sending, setSending] = React.useState(false); const [error, setError] = React.useState(''); /* Show the success screen when FormSubmit returns the customer here. */ React.useEffect(() => { try { if (new URLSearchParams(window.location.search).get('sent') === '1') setSent(true); } catch (err) { /* ignore */ } }, []); /* Native browser submission — see the note on the contact form. */ const submit = (e) => { if (!validate()) { e.preventDefault(); return; } if (!FORM_KEY) { e.preventDefault(); setError('The form is not configured yet — please contact us on WhatsApp or by phone.'); return; } setSending(true); // no preventDefault — the browser posts the form from here }; const waBook = () => { const msg = `Hi MVH, I'd like to book a detail.%0AName: ${data.name}%0AService: ${data.service}%0AVehicle: ${data.vehicle} ${data.make}%0APreferred date: ${data.date}%0AArea: ${data.postcode}`; return `https://wa.me/${MVH.wa}?text=${msg}`; }; if (sent) { return (

Request received

Thank you, {data.name.split(' ')[0] || 'there'}. Your booking request has been sent directly to us. We'll confirm availability and your exact price by phone or WhatsApp shortly.

); } return (
{ const a = BOOKING_ADDONS.find(x => x.id === id); return a ? a.label : id; }).join(', ')} readOnly />
{errors.name && } {errors.phone && } {errors.email && }
{errors.postcode && } {/* Add-On Services */}

Please select any additional services you would like to add to your booking. Multiple add-ons can be selected. If no additional services are required, select 'No Add-Ons Required'.

Multiple selections allowed
{BOOKING_ADDONS.map((addon) => { const isSelected = selectedAddons.includes(addon.id); const isNone = addon.id === 'none'; return ( ); })}
{errors.addons && }
{error &&
{error}
}

No payment taken now — we'll confirm availability and your exact price first.

); } function Err({ msg }) { return
{msg}
; } function Caret() { return ; } function Aside() { const steps = [ ['Tell us what you need', 'Pick a package and date, or ask us to recommend one.'], ['We confirm & quote', "We'll reply by phone or WhatsApp with availability and your exact price."], ['We come to you', 'We arrive fully equipped and transform your vehicle on your driveway.'], ]; return (
What Happens Next
{steps.map((s, i) => (
{i + 1}
{i !== steps.length - 1 &&
}
{s[0]}

{s[1]}

))}
4.9· {REVIEW_STATS.count} reviews
Prefer to call?
{MVH.phoneDisplay}
); } function App() { return (
); } ReactDOM.createRoot(document.getElementById('root')).render();