// ============================================ // Booking flows // 1. QuickBookModal — book one catalog item (no full itinerary needed) // 2. TweakItineraryModal — open an existing itinerary, add/remove catalog items, send request // 3. FavouritesQuickAdd — favourites panel surfaced above the planning form // ============================================ const { useState: useStateB, useEffect: useEffectB, useMemo: useMemoB, useRef: useRefB } = React; const Ib = window.MS_I; const WHATSAPP = "212698164331"; // ── Helpers ──────────────────────────────────────────────────── function todayPlusBk(days) { const d = new Date(); d.setDate(d.getDate() + days); return d.toISOString().slice(0, 10); } function readUserPrefill() { try { const user = window.MS_Auth_User || JSON.parse(localStorage.getItem('ms_user') || 'null'); const profile = JSON.parse(localStorage.getItem('ms_profile_data') || '{}'); return { name: profile.name || user?.name || '', email: profile.email || user?.email || '', phone: profile.phone || '', }; } catch { return { name: '', email: '', phone: '' }; } } function whatsappUrl(text) { return `https://wa.me/${WHATSAPP}?text=${encodeURIComponent(text)}`; } // ────────────────────────────────────────────────────────────── // 1. QUICK-BOOK MODAL — book one catalog item, no full itinerary // ────────────────────────────────────────────────────────────── function QuickBookModal({ item, tab, onClose }) { const { useMS } = window.MS_CTX; const ctx = useMS(); const lang = ctx.lang || 'no'; const tx = (en, no, fr) => lang === 'no' ? no : lang === 'fr' ? fr : en; const prefill = readUserPrefill(); const [date, setDate] = useStateB(todayPlusBk(14)); const [people, setPeople] = useStateB(2); const [name, setName] = useStateB(prefill.name); const [email, setEmail] = useStateB(prefill.email); const [phone, setPhone] = useStateB(prefill.phone); const [notes, setNotes] = useStateB(''); const [needTransport, setNeedTransport] = useStateB(false); const [pickupAddr, setPickupAddr] = useStateB(''); const [sent, setSent] = useStateB(false); useEffectB(() => { const onKey = (e) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', onKey); document.body.style.overflow = 'hidden'; return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; }; }, []); const dateLabel = new Date(date).toLocaleDateString(lang === 'no' ? 'no-NO' : lang === 'fr' ? 'fr-FR' : 'en-GB', { day: 'numeric', month: 'short', year: 'numeric' }); const transportLine = () => needTransport ? tx(`\n• Transport needed: yes${pickupAddr ? ` (pickup: ${pickupAddr})` : ''}`, `\n• Trenger transport: ja${pickupAddr ? ` (henting: ${pickupAddr})` : ''}`, `\n• Transport nécessaire : oui${pickupAddr ? ` (prise en charge : ${pickupAddr})` : ''}`) : ''; const buildMessage = () => { return tx( `Hi Marrakech Story, I'd like to book just this:\n\n• ${item.name}\n• Date: ${dateLabel}\n• People: ${people}\n• Name: ${name}\n• Email: ${email}\n• Phone: ${phone}${transportLine()}${notes ? `\n• Notes: ${notes}` : ''}`, `Hei Marrakech Story, jeg vil bestille kun dette:\n\n• ${item.name}\n• Dato: ${dateLabel}\n• Antall: ${people}\n• Navn: ${name}\n• E-post: ${email}\n• Telefon: ${phone}${transportLine()}${notes ? `\n• Notater: ${notes}` : ''}`, `Bonjour Marrakech Story, je souhaite réserver uniquement ceci :\n\n• ${item.name}\n• Date : ${dateLabel}\n• Personnes : ${people}\n• Nom : ${name}\n• Email : ${email}\n• Téléphone : ${phone}${transportLine()}${notes ? `\n• Notes : ${notes}` : ''}` ); }; const persistQuickBook = (via) => { try { const reqs = JSON.parse(localStorage.getItem('ms_requests') || '[]'); reqs.push({ type: 'single', item: item.name, tab, date, people, name, email, phone, notes, needTransport, pickupAddr, at: Date.now() }); localStorage.setItem('ms_requests', JSON.stringify(reqs)); } catch {} if (window.MS_submitForm) { window.MS_submitForm('quickbook', { item: item.name, tab, date, people, name, email, phone, notes, needTransport, pickupAddr, startDate: date, endDate: date, duration: 1 }, { via }); } }; const sendWhatsapp = () => { if (!name.trim() || !email.trim()) return; persistQuickBook('whatsapp'); window.open(whatsappUrl(buildMessage()), '_blank', 'noopener'); setSent(true); }; const sendEmail = () => { if (!name.trim() || !email.trim()) return; const subject = `Booking — ${item.name}`; const body = buildMessage(); window.location.href = `mailto:marrakechstory@outlook.com?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`; persistQuickBook('email'); setSent(true); }; return (
e.stopPropagation()}>
{tx('QUICK BOOK', 'RASK BOOKING', 'RÉSERVATION RAPIDE')}
{item.name}
{sent ? (

{tx('Request sent', 'Forespørsel sendt', 'Demande envoyée')}

{tx( "We've received your booking request. The team will confirm by email or WhatsApp within 24 hours.", "Vi har mottatt forespørselen din. Teamet bekrefter på e-post eller WhatsApp innen 24 timer.", "Nous avons reçu votre demande. L'équipe vous confirmera par e-mail ou WhatsApp sous 24 h." )}

) : ( <>

{tx( "Just want this one thing? Skip the full planner — give us a date, who's coming, and how to reach you.", "Bare denne ene? Hopp over hele planleggeren — gi oss en dato, hvem som blir med og kontaktinfo.", "Juste cela ? Sautez le planificateur — donnez-nous une date, qui vient, et comment vous joindre." )}

{needTransport && ( setPickupAddr(e.target.value)} placeholder={tx('Pickup address (hotel / riad name)', 'Henteadresse (hotell / riad)', 'Adresse de prise en charge')} /> )}