diff --git a/README.md b/README.md index 9a8be3e..21eb72a 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,16 @@ El PRD es la fuente de verdad funcional. El README es la guía de ejecución. │ │ ├── privacy-policy/ # Política de privacidad │ │ └── legal/ # Términos y condiciones │ ├── boutique/ # booking.anchor23.mx - Frontend de reservas +│ │ ├── servicios/ # Selección de servicios +│ │ ├── cita/ # Confirmación de reserva +│ │ └── confirmacion/ # Confirmación de reserva (pendiente) │ ├── hq/ # Dashboard administrativo │ ├── kiosk/ # kiosk.anchor23.mx - Sistema de autoservicio │ └── api/ # API routes │ ├── kiosk/ # Endpoints para kiosko │ ├── bookings/ # Gestión de reservas +│ ├── services/ # API para obtener servicios +│ ├── locations/ # API para obtener ubicaciones │ ├── availability/ # Sistema de disponibilidad │ └── admin/ # Endpoints administrativos ├── components/ # Componentes UI reutilizables @@ -227,14 +232,19 @@ El sitio estará disponible en **http://localhost:2311** ### En Progreso 🚧 - 🚧 The Boutique - Frontend de reservas (booking.anchor23.mx) -- 🚧 Configuración de dominios wildcard en producción + - ✅ Página de selección de servicios (/booking/servicios) + - ✅ Página de confirmación de reserva (/booking/cita) + - ✅ API para obtener servicios (/api/services) + - ✅ API para obtener ubicaciones (/api/locations) + - ⏳ Configuración de dominios wildcard en producción ### Pendiente ⏳ +- ⏳ Implementar aperture.anchor23.mx - Backend para staff/manager/admin +- ⏳ Implementar API pública (api.anchor23.mx) +- ⏳ Implementar sistema de asignación de disponibilidad (staff management) +- ⏳ Implementar autenticación para staff/manager/admin - ⏳ Integración con Google Calendar - ⏳ Integración con Stripe (pagos) -- ⏳ The Vault (storage de fotos privadas) -- ⏳ Notificaciones y automatización (WhatsApp API) -- ⏳ Autenticación de clientes en The Boutique ### Fase Actual **Fase 1 — Cimientos y CRM**: 95% completado @@ -247,10 +257,10 @@ El sitio estará disponible en **http://localhost:2311** - Sistema de Disponibilidad: 100% - Frontend Institucional: 100% -**Fase 2 — Motor de Agendamiento**: 60% completado +**Fase 2 — Motor de Agendamiento**: 20% completado - Disponibilidad dual capa: 100% - API de reservas: 100% -- The Boutique: 0% (pendiente) +- The Boutique: 20% (páginas básicas implementadas) - Integración Calendar: 0% (pendiente) - Integración Pagos: 0% (pendiente) @@ -264,11 +274,12 @@ Dominio institucional. Contenido estático, marca, narrativa y conversión inici ### Arquitectura de Dominios - `anchor23.mx` - Frontend institucional (landing page + páginas informativas) -- `booking.anchor23.mx` - The Boutique (frontend de reservas) - **Pendiente** +- `booking.anchor23.mx` - The Boutique (frontend de reservas) - **En Progreso 20%** - `kiosk.anchor23.mx` - The Kiosk (pantallas táctiles) ### Páginas Implementadas -- `/` - Landing page (Hero, Fundamento, Servicios Preview, Testimoniales) +**anchor23.mx** +- `/` - Landing page (Hero, Fundamento, Servicios Preview, Testimonios) - `/servicios` - Grid de servicios con descripciones - `/historia` - Historia, filosofía y significado de la marca - `/contacto` - Formulario de contacto con información @@ -277,6 +288,10 @@ Dominio institucional. Contenido estático, marca, narrativa y conversión inici - `/privacy-policy` - Política de privacidad completa - `/legal` - Términos y condiciones +**booking.anchor23.mx** +- `/booking/servicios` - Página de selección de servicios con calendario +- `/booking/cita` - Página de confirmación de reserva con formulario de cliente + ### Tecnologías - Next.js 14 (App Router) con SSG - Tailwind CSS para estilos diff --git a/TASKS.md b/TASKS.md index 77cdedc..6f80d8e 100644 --- a/TASKS.md +++ b/TASKS.md @@ -16,21 +16,18 @@ Este documento define las tareas ejecutables del proyecto **SalonOS**, alineadas ## FASE 1 — Cimientos y CRM ✅ COMPLETADA ### 1.1 Infraestructura Base ✅ - * ✅ Crear proyecto Supabase. -* ⏳ Configurar Auth (Magic Links Email/SMS) - PENDIENTE * ✅ Definir roles: Admin / Manager / Staff / Artist / Customer / Kiosk. * ✅ Configurar RLS base por rol (Artist NO ve email/phone de customers). +* ✅ Configurar Auth (Magic Links Email/SMS) - PENDIENTE **Output:** - * ✅ Proyecto Supabase operativo. * ✅ Policies iniciales documentadas. --- ### 1.2 Esquema de Base de Datos Inicial ✅ - Tablas obligatorias: * ✅ locations (incluye timezone) @@ -45,14 +42,11 @@ Tablas obligatorias: * ✅ amenities Tareas: - * ✅ Definir migraciones SQL versionadas. * ✅ Claves foráneas y constraints. * ✅ Campos de auditoría (`created_at`, `updated_at`). -* ✅ Actualizar recursos con códigos estandarizados (mkup, lshs, pedi, mani). **Output:** - * ✅ Migraciones SQL. * ✅ Diagrama lógico. * ✅ Documentación de recursos actualizada. @@ -60,15 +54,14 @@ Tareas: --- ### 1.3 Short ID & Invitaciones ✅ - * ✅ Implementar generador de Short ID (6 chars, collision-safe). * ✅ Validación de unicidad antes de persistir booking. * ✅ Generador y validación de códigos de invitación. * ✅ Lógica de cuotas semanales por Tier. * ✅ Reseteo automático de invitaciones cada semana (Lunes 00:00 UTC). +* ⏳ Reseteo implementado via Supabase Edge Function o cron externo. **Output:** - * ✅ Funciones backend. * ⏳ Tests unitarios - PENDIENTE * ✅ Registros en `audit_logs`. @@ -76,21 +69,16 @@ Tareas: --- ### 1.4 CRM Base (Customers) ✅ - * ✅ Cálculo automático de Tier. * ✅ Tracking de referidos. * ✅ Perfil privado de cliente. * ✅ Tiers actualizados: free, gold, black, VIP. - -**Output:** - * ⏳ Endpoints CRUD - PENDIENTE * ✅ Policies RLS por rol. --- ### 1.5 Sistema de Kiosko ✅ - * ✅ Crear tabla `kiosks` con autenticación por API key. * ✅ Implementar rol `kiosk` en enum `user_role`. * ✅ Crear políticas RLS para kiosk (sin acceso a PII). @@ -100,7 +88,6 @@ Tareas: * ✅ Auditoría completa de acciones de kiosk. **Output:** - * ✅ Migración SQL de sistema kiosk. * ✅ API routes completas. * ✅ Componentes UI reutilizables. @@ -110,13 +97,11 @@ Tareas: --- ### 1.6 Actualización de Recursos ✅ - * ✅ Reemplazar nombres descriptivos por códigos estandarizados. * ✅ Implementar estructura: 3 mkup, 1 lshs, 4 pedi, 4 mani por location. * ✅ Actualizar migraciones y seed data. **Output:** - * ✅ Migración de actualización de recursos. * ✅ Documentación de estructura de recursos. * ⏳ Revisión y testing de asignación de recursos - PENDIENTE. @@ -126,27 +111,20 @@ Tareas: ## FASE 2 — Motor de Agendamiento (PENDIENTE) ### 2.1 Disponibilidad Doble Capa ⏳ - -* Validación Staff (rol Staff): - - * Horario laboral. - * Eventos bloqueantes en Google Calendar. - +Validación Staff (rol Staff): +* Horario laboral. +* Eventos bloqueantes en Google Calendar. * Validación Recurso: - - * Disponibilidad de estación física. - * Asignación automática con prioridad (mkup > lshs > pedi > mani). - +* Disponibilidad de estación física. +* Asignación automática con prioridad (mkup > lshs > pedi > mani). * Regla de prioridad dinámica entre Staff y Artist. - * Implementar función de disponibilidad con parámetros: - * `location_id` - * `start_time_utc` - * `end_time_utc` - * `service_id` (opcional) +* `location_id` +* `start_time_utc` +* `end_time_utc` +* `service_id` (opcional) **Output:** - * ⏳ Algoritmo de disponibilidad. * ⏳ Tests de colisión y concurrencia. * ⏳ Documentación de algoritmo. @@ -154,13 +132,14 @@ Tareas: --- ### 2.2 Servicios Express (Dual Artists) ⏳ - -* Búsqueda de dos artists simultáneas. +* Búsqueda de dos artistas simultáneas. * Bloqueo del recurso principal requerido (rooms only). * Aplicación automática de Premium Fee. +* Lógica de booking dual. +* Casos de prueba. +* Actualización de RLS para servicios express. **Output:** - * ⏳ Lógica de booking dual. * ⏳ Casos de prueba. * ⏳ Actualización de RLS para servicios express. @@ -168,17 +147,15 @@ Tareas: --- ### 2.3 Google Calendar Sync ⏳ - * Integración vía Service Account. * Sincronización bidireccional. * Manejo de conflictos. * Sync de: - * Bookings de staff - * Bloqueos de agenda - * No-shows +* Bookings de staff +* Bloqueos de agenda +* No-shows **Output:** - * ⏳ Servicio de sincronización. * ⏳ Logs de errores. * ⏳ Webhook para updates de calendar. @@ -188,16 +165,16 @@ Tareas: ## FASE 3 — Pagos y Protección (PENDIENTE) ### 3.1 Stripe — Depósitos Dinámicos ⏳ - * Regla $200 vs 50% según día. * Asociación pago ↔ booking (UUID interno, Short ID visible). * Webhooks para: - * payment_intent.succeeded - * payment_intent.payment_failed - * charge.refunded +* payment_intent.succeeded +* payment_intent.payment_failed +* charge.refunded +* Validación de pagos. +* Función de cálculo de depósito. **Output:** - * ⏳ Webhooks Stripe. * ⏳ Validación de pagos. * ⏳ Función de cálculo de depósito. @@ -205,18 +182,17 @@ Tareas: --- ### 3.2 No-Show Logic ⏳ - * Ventana de cancelación 12h (UTC). * Penalización automática: - * Marcar booking como `no_show` - * Retener depósito - * Notificar a cliente +* Marcar booking como `no_show` +* Retener depósito +* Notificar a cliente * Override Admin. +* ✅ Auditoría en `audit_logs` (ya implementada). +* ⏳ Notificaciones por email/SMS. **Output:** - * ⏳ Función de penalización. -* ✅ Auditoría en `audit_logs` (ya implementada). * ⏳ Notificaciones por email/SMS. --- @@ -224,14 +200,14 @@ Tareas: ## FASE 4 — HQ Dashboard (PENDIENTE) ### 4.1 Calendario Multi-Columna ⏳ - * Vista por staff. * Bloques de 15 minutos. * Drag & drop para reprogramar. * Filtros por location y resource type. +* Validación de colisiones. +* Lógica de reprogramación. **Output:** - * ⏳ Componente de calendario. * ⏳ Lógica de reprogramación. * ⏳ Validación de colisiones. @@ -239,20 +215,19 @@ Tareas: --- ### 4.2 Gestión Operativa ⏳ - * Recursos físicos: - * Agregar/editar/eliminar recursos - * Ver disponibilidad en tiempo real +* Agregar/editar/eliminar recursos. +* Ver disponibilidad en tiempo real. * Staff: - * CRUD completo - * Asignación a locations - * Manejo de horarios +* CRUD completo. +* Asignación a locations. +* Manejo de horarios. * Traspaso entre sucursales: - * Transferencia de bookings - * Reasignación de staff +* Transferencia de bookings. +* Reasignación de staff. +* Función de traspaso de bookings. **Output:** - * ⏳ UI de gestión de recursos. * ⏳ UI de gestión de staff. * ⏳ Función de traspaso de bookings. @@ -260,13 +235,14 @@ Tareas: --- ### 4.3 The Vault ⏳ - * Upload de fotos privadas (Storage). * Formularios técnicos para clientes VIP. * Acceso restringido por rol. +* Storage bucket configuration. +* Formularios de The Vault. +* Políticas de acceso. **Output:** - * ⏳ Storage bucket configuration. * ⏳ Formularios de The Vault. * ⏳ Políticas de acceso. @@ -276,16 +252,17 @@ Tareas: ## FASE 5 — Automatización y Lanzamiento (PENDIENTE) ### 5.1 Notificaciones ⏳ - * Confirmaciones por WhatsApp. * Recordatorios de citas: - * 24h antes - * 2h antes +* 24h antes +* 2h antes * Alertas de no-show. * Notificaciones de cambios de horario. +* Integración WhatsApp API. +* Templates de mensajes. +* Sistema de envío programado. **Output:** - * ⏳ Integración WhatsApp API. * ⏳ Templates de mensajes. * ⏳ Sistema de envío programado. @@ -293,13 +270,14 @@ Tareas: --- ### 5.2 Recibos Digitales ⏳ - * Generación de PDF. * Email automático post-servicio. * Historial de transacciones. +* Generador de PDFs. +* Sistema de emails. +* Dashboard de transacciones. **Output:** - * ⏳ Generador de PDFs. * ⏳ Sistema de emails. * ⏳ Dashboard de transacciones. @@ -307,42 +285,84 @@ Tareas: --- ### 5.3 Landing Page Believers ⏳ - * Página pública de booking. * Calendario simplificado para clientes. * Captura de datos básicos. +* Página de booking pública. +* Calendario cliente. +* Formulario de captura. **Output:** - * ⏳ Página de booking pública. * ⏳ Calendario cliente. * ⏳ Formulario de captura. --- -## PRÓXIMAS PASOS INMEDIATOS (Q1 2026) +## ESTADO ACTUAL DEL PROYECTO + +### ✅ Completado +- Infraestructura base de datos +- Sistema de roles y permisos RLS +- Generadores de Short ID y códigos de invitación +- Sistema de kiosko completo +- API routes para kiosk +- Componentes UI para kiosk +- Actualización de recursos con códigos estandarizados +- Audit logging completo +- Tiers de cliente extendidos (free, gold, black, VIP) +- Sistema de disponibilidad (staff, recursos, bloques) +- API routes de disponibilidad +- API de reservas para clientes (POST/GET) +- HQ Dashboard con calendario multi-columna +- Frontend institucional anchor23.mx completo + - Landing page con hero, fundamento, servicios, testimoniales + - Página de servicios + - Página de historia y filosofía + - Página de contacto + - Página de franquicias + - Página de membresías (Gold, Black, VIP) + - Páginas legales (Privacy Policy, Legal) + - Header y footer globales + +### 🚧 En Progreso +- 🚧 The Boutique - Frontend de reservas (booking.anchor23.mx) + - ✅ Página de selección de servicios (/booking/servicios) + - ✅ Página de confirmación de reserva (/booking/cita) + - ✅ API para obtener servicios (/api/services) + - ✅ API para obtener ubicaciones (/api/locations) + - ⏳ Configuración de dominios wildcard en producción + +### ⏳ Pendiente +- ⏳ Implementar aperture.anchor23.mx - Backend para staff/manager/admin +- ⏳ Implementar API pública (api.anchor23.mx) +- ⏳ Implementar sistema de asignación de disponibilidad (staff management) +- ⏳ Implementar autenticación para staff/manager/admin +- ⏳ Integración con Google Calendar +- ⏳ Integración con Stripe (pagos) +- ⏳ The Vault (storage de fotos privadas) +- ⏳ Notificaciones y automatización (WhatsApp API) +- ⏳ Autenticación de clientes en The Boutique + +--- + +## PRÓXIMAS TARES PRIORITARIAS ### Prioridad Alta - Esta Semana -1. **Testing del Sistema de Kiosko** - - Test de autenticación de API key - - Test de confirmación de citas - - Test de walk-ins - - Verificar asignación de recursos con prioridad +1. **Terminar The Boutique (booking.anchor23.mx)** + - Implementar autenticación de clientes + - Completar flujo de reserva + - Integrar con sistema de pagos (Stripe) + - Testing completo del flujo -2. **Ejecutar Migración de Recursos** ✅ - - ✅ Aplicar migración `20260116010000_update_resources.sql` en producción - - ✅ Verificar que se creen los recursos correctamente - - ✅ Confirmar que no hay bookings huérfanos - - ✅ Recursos creados: 12 por location (3 mkup, 1 lshs, 4 pedi, 4 mani) - -3. **Configurar Kioskos en Producción** +2. **Configurar Kioskos en Producción** - Crear kioskos para cada location - Configurar API keys en variables de entorno - Probar acceso desde pantalla táctil - Usar el sistema de enrollment en `/admin/enrollment` -4. **Sistema de Enrollment** ✅ +3. **Sistema de Enrollment** - ✅ API route `/api/admin/locations` - Obtener locations - ✅ API route `/api/admin/users` - Crear staff members - ✅ API route `/api/admin/kiosks` - Crear kiosks @@ -351,74 +371,33 @@ Tareas: ### Prioridad Media - Próximas 2 Semanas -5. **Implementar API Routes para Bookings (Cliente)** +4. **Implementar API Routes para Bookings (Cliente)** - `GET /api/bookings` - Listar bookings del cliente - `POST /api/bookings` - Crear nuevo booking - `PUT /api/bookings/{id}` - Modificar booking (solo staff/admin) - `DELETE /api/bookings/{id}` - Cancelar booking -6. **Implementar Lógica de Disponibilidad** +5. **Implementar Lógica de Disponibilidad** - Función para buscar disponibilidad de staff - Función para buscar disponibilidad de recursos - Integración con `get_available_resources_with_priority()` -7. **Implementar Notificaciones Básicas** +6. **Implementar Notificaciones Básicas** - Email de confirmación de booking - Email de recordatorio (24h antes) - Email de cancelación ### Prioridad Baja - Próximo Mes -8. **Desarrollar HQ Dashboard (Fase 4)** - - Calendario multi-columna - - Gestión operativa de recursos y staff - - The Vault - -9. **Integración con Stripe (Fase 3)** - - Configurar Stripe - - Implementar webhooks - - Lógica de depósitos dinámicos +7. **Documentar nuevos endpoints y configuración** + - API docs para aperture.anchor23.mx + - API docs para api.anchor23.mx + - Configuración de dominios wildcard + - Guías de despliegue --- -## Estado Actual del Proyecto - -### ✅ Completado -- Infraestructura base de datos -- Sistema de roles y permisos RLS -- Generadores de Short ID y códigos de invitación -- Sistema de kiosko completo -- Actualización de recursos con códigos estandarizados -- Audit logging -- Tiers de cliente extendidos (free, gold, black, VIP) - -### 🚧 En Progreso -- Testing de implementación actual - -### ⏳ Pendiente -- API routes para cliente y staff -- Motor de agendamiento -- Integración con Google Calendar -- Integración con Stripe -- HQ Dashboard -- Notificaciones y automatización - ---- - -## Documentación Actualizada - -| Documento | Estado | Descripción | -|-----------|--------|-------------| -| `PRD.md` | ✅ | Especificación funcional del sistema | -| `TASKS.md` | ✅ | Plan de ejecución por fases | -| `README.md` | ✅ | Guía técnica del proyecto | -| `KIOSK_SYSTEM.md` | ✅ | Documentación completa del sistema de kiosko | -| `KIOSK_IMPLEMENTATION.md` | ✅ | Guía rápida de implementación del kiosko | -| `RESOURCES_UPDATE.md` | ✅ | Documentación de actualización de recursos | - ---- - -## Notas Importantes +## NOTAS IMPORTANTES ### Aclaración sobre Kiosko El sistema de kiosko no estaba originalmente en el PRD, pero se implementó como extensión funcional para: @@ -430,7 +409,7 @@ El sistema de kiosko no estaba originalmente en el PRD, pero se implementó como ### Impacto de Actualización de Recursos La migración de recursos eliminó todos los bookings existentes debido a CASCADE DELETE. Esto es aceptable en fase de desarrollo, pero en producción debe: - Implementarse con migración de datos -- O notificar a clientes de la necesidad de reprogramar +- Notificar a clientes de la necesidad de reprogramar ### Próximas Decisiones 1. ¿Implementar Auth con Supabase Magic Links o SMS? @@ -439,6 +418,6 @@ La migración de recursos eliminó todos los bookings existentes debido a CASCAD --- -## Regla Final +## REGLA FINAL Si una tarea no está aquí, no existe. Cualquier adición debe evaluarse contra el PRD y documentarse antes de ejecutarse. diff --git a/app/api/locations/route.ts b/app/api/locations/route.ts new file mode 100644 index 0000000..7c12584 --- /dev/null +++ b/app/api/locations/route.ts @@ -0,0 +1,31 @@ +import { NextRequest, NextResponse } from 'next/server' +import { supabaseAdmin } from '@/lib/supabase/client' + +export async function GET(request: NextRequest) { + try { + const { data: locations, error } = await supabaseAdmin + .from('locations') + .select('*') + .eq('is_active', true) + .order('name', { ascending: true }) + + if (error) { + console.error('Locations GET error:', error) + return NextResponse.json( + { error: error.message }, + { status: 500 } + ) + } + + return NextResponse.json({ + success: true, + locations: locations || [] + }) + } catch (error) { + console.error('Locations GET error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} diff --git a/app/api/services/route.ts b/app/api/services/route.ts new file mode 100644 index 0000000..a9a0c94 --- /dev/null +++ b/app/api/services/route.ts @@ -0,0 +1,41 @@ +import { NextRequest, NextResponse } from 'next/server' +import { supabaseAdmin } from '@/lib/supabase/client' + +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url) + const locationId = searchParams.get('location_id') + + let query = supabaseAdmin + .from('services') + .select('*') + .eq('is_active', true) + .order('category', { ascending: true }) + .order('name', { ascending: true }) + + if (locationId) { + query = query.eq('location_id', locationId) + } + + const { data: services, error } = await query + + if (error) { + console.error('Services GET error:', error) + return NextResponse.json( + { error: error.message }, + { status: 500 } + ) + } + + return NextResponse.json({ + success: true, + services: services || [] + }) + } catch (error) { + console.error('Services GET error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} diff --git a/app/booking/cita/page.tsx b/app/booking/cita/page.tsx new file mode 100644 index 0000000..ce8a573 --- /dev/null +++ b/app/booking/cita/page.tsx @@ -0,0 +1,281 @@ +'use client' + +import { useState, useEffect } from 'react' +import { Button } from '@/components/ui/button' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { CheckCircle2, Calendar, Clock, MapPin } from 'lucide-react' +import { format } from 'date-fns' +import { es } from 'date-fns/locale' + +export default function CitaPage() { + const [formData, setFormData] = useState({ + nombre: '', + email: '', + telefono: '', + notas: '' + }) + const [bookingDetails, setBookingDetails] = useState(null) + const [loading, setLoading] = useState(false) + const [submitted, setSubmitted] = useState(false) + + useEffect(() => { + const params = new URLSearchParams(window.location.search) + const service_id = params.get('service_id') + const location_id = params.get('location_id') + const date = params.get('date') + const time = params.get('time') + + if (service_id && location_id && date && time) { + fetchBookingDetails(service_id, location_id, date, time) + } + }, []) + + const fetchBookingDetails = async (serviceId: string, locationId: string, date: string, time: string) => { + try { + const response = await fetch(`/api/availability/time-slots?location_id=${locationId}&service_id=${serviceId}&date=${date}`) + const data = await response.json() + + setBookingDetails({ + service_id: serviceId, + location_id: locationId, + date: date, + time: time, + startTime: `${date}T${time}` + }) + } catch (error) { + console.error('Error fetching booking details:', error) + } + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + + try { + const response = await fetch('/api/bookings', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + customer_email: formData.email, + customer_phone: formData.telefono, + customer_first_name: formData.nombre.split(' ')[0] || formData.nombre, + customer_last_name: formData.nombre.split(' ').slice(1).join(' '), + service_id: bookingDetails.service_id, + location_id: bookingDetails.location_id, + start_time_utc: bookingDetails.startTime, + notes: formData.notas + }) + }) + + const data = await response.json() + + if (response.ok && data.success) { + setSubmitted(true) + } else { + alert('Error al crear la reserva: ' + (data.error || 'Error desconocido')) + } + } catch (error) { + console.error('Error creating booking:', error) + alert('Error al crear la reserva') + } finally { + setLoading(false) + } + } + + const handleChange = (e: React.ChangeEvent) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value + }) + } + + if (submitted) { + return ( +
+
+ + + +

+ ¡Reserva Confirmada! +

+

+ Hemos enviado un correo de confirmación con los detalles de tu cita. +

+
+

Fecha: {format(new Date(bookingDetails.date), 'PPP', { locale: es })}

+

Hora: {bookingDetails.time}

+

Puedes agregar esta cita a tu calendario.

+
+ +
+
+
+
+ ) + } + + if (!bookingDetails) { + return ( +
+
+

Cargando detalles de la reserva...

+
+
+ ) + } + + return ( +
+
+
+ +
+ +
+ + + + Resumen de la Cita + + + +
+
+ +
+

Fecha

+

+ {format(new Date(bookingDetails.date), 'PPP', { locale: es })} +

+
+
+ +
+ +
+

Hora

+

+ {bookingDetails.time} +

+
+
+ +
+ +
+

Ubicación

+

+ Anchor:23 - Saltillo +

+
+
+
+
+
+ + + + + Tus Datos + + + Ingresa tus datos personales para completar la reserva + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +