import { createFileRoute } from "@tanstack/react-router"; import { useEffect, useMemo, useState } from "react"; import { useDraft } from "@/lib/cotizador-draft"; import { ArrowLeft, ArrowRight, Check } from "lucide-react"; import { AppShell } from "@/components/AppShell"; import { Paso1Extras } from "@/components/reserva/Paso1Extras"; import { Paso2Datos } from "@/components/reserva/Paso2Datos"; import { Paso3Pago } from "@/components/reserva/Paso3Pago"; import { Paso4Certificados } from "@/components/reserva/Paso4Certificados"; import { formatoMoneda } from "@/lib/catalogo"; import { notificar } from "@/lib/notificaciones"; import { calcularReserva, estadoInicialReserva, extrasSeleccionados, pasajeroVacio, totalPasajeros, validarPaso2, type Certificado, type PasajeroDatos, type ReservaEstado, } from "@/lib/reserva-flujo"; const PASOS = ["Pasajeros y extras", "Datos del vuelo", "Pago", "Certificados"]; export const Route = createFileRoute("/reserva")({ head: () => ({ meta: [ { title: "Reservación en 4 pasos | Sky Balloons México" }, { name: "description", content: "Flujo de reservación multietapas: elige pasajeros y extras, captura datos del vuelo, paga y personaliza los certificados de vuelo.", }, { property: "og:title", content: "Reservación en 4 pasos | Sky Balloons México" }, { property: "og:description", content: "Wizard de compra para socios comerciales: extras, datos de pasajeros, pago y certificados.", }, { property: "og:type", content: "website" }, { name: "twitter:card", content: "summary_large_image" }, ], }), component: ReservaWizard, }); function ReservaWizard() { const { draft, listo } = useDraft(); const [paso, setPaso] = useState(1); const [estado, setEstado] = useState(estadoInicialReserva); const [finalizado, setFinalizado] = useState(false); const [error, setError] = useState(null); const set = (parcial: Partial) => setEstado((p) => ({ ...p, ...parcial })); // Previsualiza los datos capturados en el cotizador (localStorage). useEffect(() => { if (!listo) return; setEstado((p) => ({ ...p, adultos: draft.adultos, ninos: draft.ninos, fecha: draft.fecha || p.fecha, fechaPorConfirmar: draft.fechaPorConfirmar, })); }, [listo]); // Sincroniza la lista de pasajeros con los contadores del paso 1. const cantidad = totalPasajeros(estado); useEffect(() => { setEstado((p) => { if (p.pasajeros.length === cantidad) return p; const pasajeros = Array.from({ length: cantidad }, (_, i) => p.pasajeros[i] ?? pasajeroVacio()); const certificados = Array.from({ length: cantidad }, (_, i) => p.certificados[i] ?? { nombre: "", frase: "" }); return { ...p, pasajeros, certificados }; }); }, [cantidad]); const desglose = useMemo(() => calcularReserva(estado), [estado]); const extras = extrasSeleccionados(estado.extras); const setExtra = (id: string, cant: number) => setEstado((p) => ({ ...p, extras: { ...p.extras, [id]: cant } })); const setPasajero = (i: number, parcial: Partial) => setEstado((p) => ({ ...p, pasajeros: p.pasajeros.map((x, idx) => (idx === i ? { ...x, ...parcial } : x)), })); const setCertificado = (i: number, parcial: Partial) => setEstado((p) => ({ ...p, certificados: p.certificados.map((x, idx) => (idx === i ? { ...x, ...parcial } : x)), })); const avanzar = () => { setError(null); if (paso === 1 && cantidad < 1) return setError("Agrega al menos un pasajero."); if (paso === 2) { const err = validarPaso2(estado); if (err) return setError(err); } if (paso === 3 && !estado.pagoConfirmado) return setError("Confirma el pago para continuar."); setPaso((p) => Math.min(4, p + 1)); }; const confirmarPago = () => { set({ pagoConfirmado: true }); notificar("Pago registrado", `Total ${formatoMoneda(desglose.total)} · método ${estado.metodoPago}`); setPaso(4); }; const finalizar = () => { setFinalizado(true); notificar("¡Reservación finalizada!", `Pases emitidos para ${cantidad} pasajero(s).`); notificar("Comisión del 10% acreditada", `Se acreditaron ${formatoMoneda(desglose.comision)} a tu cuenta.`); }; return ( {/* Indicador de pasos */}
    {PASOS.map((label, i) => { const n = i + 1; const activo = paso === n; const completo = paso > n; return (
  1. {n < PASOS.length && }
  2. ); })}
{paso === 1 && ( set({ adultos: v })} setNinos={(v) => set({ ninos: v })} extras={estado.extras} setExtra={setExtra} /> )} {paso === 2 && } {paso === 3 && ( set({ metodoPago: m })} pagoConfirmado={estado.pagoConfirmado} confirmarPago={confirmarPago} /> )} {paso === 4 && (estado.pagoConfirmado ? ( ) : (

Este paso se habilita al confirmar el pago.

))}
{error && (

{error}

)} {/* Barra de navegación del wizard */}

{cantidad} pax · {extras.length} extras

{formatoMoneda(desglose.total)}

); }