// Booking modal const { useState, useMemo, useEffect } = React; function dateKey(d) { return d.toISOString().slice(0, 10); } function seededTakenFor(date) { const day = date.getDay(); if (day === 0) return null; const k = date.getDate() + date.getMonth() * 31; const slots = ["09:00", "10:30", "12:00", "14:00", "15:30", "17:00"]; const taken = []; if (k % 7 === 0) taken.push("10:30", "15:30"); else if (k % 7 === 1) taken.push("09:00", "14:00", "17:00"); else if (k % 7 === 2) taken.push("12:00"); else if (k % 7 === 3) taken.push("10:30", "17:00"); else if (k % 7 === 4) taken.push("09:00", "12:00", "15:30"); else if (k % 7 === 5) taken.push("14:00"); else taken.push("12:00", "15:30"); return slots.map(s => ({ time: s, taken: taken.includes(s) })); } function buildMonth(year, month) { const first = new Date(year, month, 1); const startWeekday = (first.getDay() + 6) % 7; const daysInMonth = new Date(year, month + 1, 0).getDate(); const cells = []; for (let i = 0; i < startWeekday; i++) cells.push(null); for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(year, month, d)); while (cells.length % 7 !== 0) cells.push(null); return cells; } const MONTH_NAMES = ["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]; const DAY_NAMES = ["L","M","X","J","V","S","D"]; function BookingModal({ open, onClose, prefillService }) { const today = useMemo(() => { const t = new Date(); t.setHours(0,0,0,0); return t; }, []); const [view, setView] = useState({ y: today.getFullYear(), m: today.getMonth() }); const [selectedDate, setSelectedDate] = useState(null); const [selectedSlot, setSelectedSlot] = useState(null); const [serviceId, setServiceId] = useState(prefillService || (window.ALL_SERVICES[0]?.name)); const [step, setStep] = useState(1); const [contact, setContact] = useState({ name: "", phone: "", notes: "" }); const [done, setDone] = useState(false); useEffect(() => { if (open) { setSelectedDate(null); setSelectedSlot(null); setStep(1); setDone(false); if (prefillService) setServiceId(prefillService); } }, [open, prefillService]); if (!open) return null; const cells = buildMonth(view.y, view.m); const slots = selectedDate ? seededTakenFor(selectedDate) : null; const service = window.ALL_SERVICES.find(s => s.name === serviceId) || window.ALL_SERVICES[0]; const goPrev = () => { const m = view.m - 1; const y = view.y + (m < 0 ? -1 : 0); setView({ y, m: (m + 12) % 12 }); }; const goNext = () => { const m = view.m + 1; const y = view.y + (m > 11 ? 1 : 0); setView({ y, m: m % 12 }); }; const isPast = (d) => d && d < today; const isClosed = (d) => d && d.getDay() === 0; return (
e.stopPropagation()}>
{done ? (
¡Lista, {contact.name.split(" ")[0] || "preciosa"}!

Te enviamos los datos por WhatsApp. Recibirás un mensaje de confirmación humano:

"Preparamos tu kit personal y tu té; te esperamos a las {selectedSlot || "..."}".

) : step === 1 ? (

Elige tu ritual

Cada experiencia incluye recibimiento con té y un momento de respiración guiada.

{window.ALL_SERVICES.map(s => ( ))}
) : step === 2 ? (

¿Cuándo te esperamos?

Cerramos los domingos. Cada bloque incluye 15 min de buffer.

{MONTH_NAMES[view.m]} {view.y}
{DAY_NAMES.map(d =>
{d}
)} {cells.map((d, i) => { if (!d) return
; const past = isPast(d), closed = isClosed(d); const sel = selectedDate && dateKey(d) === dateKey(selectedDate); return ( ); })}
{selectedDate && (
Horarios disponibles · {selectedDate.toLocaleDateString("es-CO", { weekday: "long", day: "numeric", month: "long" })}
{slots.map(s => ( ))}
)}
) : (

Tus datos

Te confirmamos por WhatsApp 24 h antes de tu cita.