Guest-Facing App · 26 mayo 2026 · branch: main · ✓ Completo

Catálogo, Reservas y Estado del Huésped

La aplicación `@pamaconu/client` ofrece a los huéspedes del hotel una experiencia nativa móvil para explorar el catálogo de actividades, gestionar reservas de experiencias, configurar perfiles de usuario y comunicarse.

Shippeado a producción

Arquitectura Técnica

Client está construido bajo una arquitectura modular y reactiva, desacoplada al 100% de infraestructuras de base de datos directas en el frontend como Firebase Client. Todas las interacciones pasan a través del API REST unificada.

Pilares del Framework

Next.js 15+ App Router
Rutas declarativas y optimización en la carga inicial. Utiliza Server Components para renderizar datos del hotel estáticos y Client Components (`"use client"`) para toda la interactividad de reservas y control de estado.
Desacoplamiento total de Firebase
Se completó la migración eliminando el SDK cliente de Firebase. Las sesiones ahora se manejan mediante JWT nativos del backend almacenados en LocalStorage y administrados mediante el AuthContext.
Zustand & SWR Caching
SWR maneja el refresco y la caché automática del catálogo de experiencias, minimizando llamadas de red duplicadas. Zustand o React Context locales manejan el estado efímero del flujo de checkout.
Tokens de Diseño Standalone
Tailwind CSS lee variables HSL directamente desde tokens.css local. Además, el cliente utiliza sus propias primitivas visuales locales (@/components/ui) desacopladas de core para asegurar consistencia visual y soporte para branding por hotel.

Rutas y Flujos de la Aplicación

El App Router organiza las rutas principales en dos categorías: públicas (búsqueda y checkout sin registro previo) y privadas (historial, perfil del huésped y dashboard).

/

Redirección Raíz

Evalúa el estado y redirige de inmediato a /public/experiences usando un loader adaptativo mobile-first para optimizar el historial.

/public/experiences

Catálogo de Actividades

Panel de exploración para huéspedes. Ofrece buscador predictivo, filtrado por categorías (Gastronomía, Bienestar, Aventura), ordenación por precio o fecha de creación, y favoritos. Admite renderizado embebido con ?embed=true.

/public/reserve/[id]

Checkout de Experiencias

Asistente de reserva en 3 pasos: (1) Selección de opción del catálogo y participantes (limitación dinámica por capacidad). (2) Método de pago (Cargo a habitación room o Pago en mostrador counter) y comentarios. (3) Revisión del resumen y envío.

/public/login

Acceso de Huéspedes

Formulario de autenticación universal. Si un huésped anónimo inicia un checkout, la aplicación guarda el estado de la reserva en sessionStorage, redirige al login y, una vez autenticado, completa automáticamente la reserva pendiente.

/dashboard

Panel de Control Privado

Área de clientes autenticados. Muestra reservas activas, solicitudes de tareas del hotel asignadas, historial completo y enlaces a configuración.

/dashboard/profile

Configuración del Perfil

Permite al huésped actualizar sus datos personales (nombre, apellidos, idioma de comunicación, fecha de nacimiento, avatar) y preferencias.

/requests

Mis Solicitudes

Bandeja de entrada del huésped para solicitudes especiales. Permite ver el listado, abrir el formulario de nueva solicitud y cancelarlas de forma directa.

/requests/[id]

Detalle de Solicitud (Autenticado)

Espacio de seguimiento donde el usuario puede chatear en tiempo real con el equipo del hotel para concretar los detalles de su experiencia.

/requests/public/[token]

Detalle de Solicitud (Público)

Acceso sin credenciales protegido por token de seguridad. Ideal para huéspedes que realizaron peticiones rápidas y quieren chatear con el hotel.

Servicios e Integración con Backend

La capa de servicios en src/services/ actúa como el puente de red. Utiliza la clase ApiClient de @pamaconu/core para configurar las cabeceras JWT y resolver las peticiones REST.

Catálogo de Servicios

Servicio Ruta Endpoint Método Descripción / Mapeos
AuthService /auth/login
/auth/register
POST Inicia sesión y crea cuentas asociando el rol client por defecto. Guarda la sesión JWT en LocalStorage.
ExperiencesService /experiences
/experiences/:id
GET Consulta de experiencias activas de manera pública. Mapea campos localizados de texto (ej. título en español o inglés).
ReservationService /reservations/user/:userId
/reservations/:id
GET Mapea el esquema PostgreSQL del backend a la interfaz del frontend:
  • Mapeo de estados: pending / confirmed / cancelled / completed se transforman a pendiente / confirmada / cancelada / completada.
  • Mapea booking_date y start_time en objetos Date locales.
  • Incluye joins de metadatos (detalles del hotel, rating).
ReservationService /reservations/:id/cancel PATCH Permite la cancelación inmediata de una reserva desde el panel del usuario por el motivo "Cancelado por el huésped".
UserService /users/me GET
PUT
Consulta y actualización de perfil. Centraliza la estructura de preferencias en metadatos anidados en PostgreSQL.

Flujo de Datos (Checkout con Autenticación Diferida)

El siguiente flujo muestra cómo interactúan los componentes cuando un huésped anónimo completa una pre-reserva:

1. Huésped anónimo inicia checkout → Selecciona opción en /public/reserve/[id]
2. Valida formulario localmente → ¿Sesión activa? NO → Guarda datos de reserva en sessionStorage('reserveData')
3. Redirección a /public/login → El usuario inicia sesión o se registra exitosamente
4. El AuthContext guarda el JWT → Redirección automática de vuelta a la experiencia con sesión activa
5. Recupera sessionStorage('reserveData') → Lanza POST a /api/reservas/pre (Proxy de Next.js)
6. El Proxy Next.js crea la reserva en Backend → Envía email de cortesía → Registra notificación de hotel
7. Éxito → Redirección a /public/reserve/[id]/confirmation

Branding y Tematización por Hotel

La aplicación del cliente está diseñada para presentarse de manera personalizada para cada hotel de forma dinámica. Esto se logra a través del sistema de variables de entorno CSS cargadas en el DOM mediante el atributo [data-theme].

Inyección Dinámica

El componente ClientHotelBranding lee el identificador del hotel desde los parámetros de búsqueda o la configuración de la experiencia. Establece el atributo en el DOM raíz:
document.documentElement.dataset.theme = hotel.slug;

Herencia de Tokens

Los componentes visuales de la aplicación (Button, Card, Modal, Chip) utilizan las clases de utilidad de Tailwind que referencian variables CSS HSL globales. Al activar el tema específico, solo cambian las variables del acento primario (--accent y --accent-soft), mientras que las superficies y el contraste general se mantienen legibles.

Internacionalización (i18n)

Para soportar huéspedes internacionales, Client cuenta con una capa nativa de traducción:

Mejoras y Refactorizaciones Recientes

Se han realizado varias optimizaciones clave tanto en la estructura de maquetación general como en la migración de páginas secundarias al sistema de diseño unificado:

Alineación del Dashboard (Desktop)

Se resolvió el apilamiento vertical y desalineación del menú lateral en pantallas grandes aplicando un contenedor lg:flex en el layout raíz de /dashboard. Además, se eliminó el padding offset manual de lg:pl-64 y se reemplazó por un comportamiento de flujo natural con flex-1 min-w-0, garantizando que el contenido se centre y alinee de forma impecable con el menú.

Migración del Módulo de Solicitudes (Requests)

El flujo de solicitudes de experiencias especiales (vistas de listado, detalles, chat y formulario) fue migrado íntegramente a los componentes del sistema de diseño local (@/components/ui), eliminando importaciones visuales heredadas de core. Los campos heredaron los tokens de color correctos (border-border, bg-surface y acentos locales) y se simplificaron las estructuras utilizando propiedades directas de Input.