04 — Flujos de usuario · COMAL
Convenciones
- TZ: Europe/Madrid
- Slot: 1 hora; reserva mínima configurable (default 2 h)
- Idempotencia:
Idempotency-Keyen pago y creación de reserva
F1 — Descubrimiento → Landing → Explorar
| Entrada | SEO, ads, link compartido, / |
| Pasos | Ver hero → CTA Explorar → Listado con geo default ciudad |
| Resultado | Usuario en explorar (auth opcional para ver precios completos: decisión — precios visibles sin auth) |
| Analytics | landing_view, cta_explore_click |
F2 — Registro / Login
Registro
- Email + contraseña (min 10 chars) o Google OAuth
- Nombre y teléfono
- Rol inicial: Cocinero (default) u Operador (ruta separada)
- Aceptación términos + privacidad
- Verificación email (magic link)
- Onboarding: ciudad, equipos frecuentes, aviso legal producción
Errores: email en uso, contraseña débil, OAuth cancelado
Recuperación: mensaje + link a login
Login
Email/password o Google · “Recordarme” · link olvidé contraseña
Recuperación contraseña
Email → link 30 min → nueva contraseña → sesión invalidada en otros dispositivos
Analytics: sign_up, login, password_reset_request
F3 — Explorar y filtrar
- Listado ordenado por distancia o relevancia
- Abrir filtros → aplicar chips equipo / precio / horario
- Vacío → empty state
- Tap en card → ficha
Estados: loading skeleton, error red, empty, resultados
Analytics: search_filter_apply, listing_impression, listing_click
F4 — Reserva end-to-end (crítico)
Ficha → Reservar → Fecha → Slots → Resumen → Pago → Confirmación
| Paso | UI | Reglas |
|---|---|---|
| Fecha | Calendario 14–60 días vista | No pasado; lead time min 2 h |
| Slots | Grid horas | Solo disponibles; selección contigua |
| Resumen | Cocina, estación, horas, € | Desglose IVA, descuento membresía |
| Pago | Stripe Payment Element | 3DS si aplica |
| OK | ID reserva, ICS, QR preview | Email + push opcional |
Decisiones en branch:
- Slot se ocupa entre resumen y pago → error “ya no disponible” + reembolso si cargo
- Pago falla → reintentar; no crear reserva
- Usuario cierra → carrito no persistente (slots no hold largos); hold 10 min opcional v1.1
Analytics: booking_start, slot_select, checkout_start, payment_success|fail, booking_confirmed
F5 — Check-in
- Desde Mis reservas o tab Acceso
- Ventana: desde 15 min antes hasta fin de franja
- Muestra QR + PIN de 6 dígitos
- Operador escanea o introduce PIN en /ops/checkin
- Estado → “En curso”
Offline: PIN visible si reserva cacheada; validación operador puede ser manual
Error: fuera de ventana; reserva cancelada; PIN revocado
F6 — Cancelación
- Detalle reserva → Cancelar
- Mostrar política y importe reembolsable
- Confirmar
- Reembolso Stripe (parcial/total) async
- Slot liberado
Analytics: booking_cancel, refund_initiated
F7 — Membresía
Planes:
- Sin plan: pay-as-you-go
- Base (29€/mes): 10 % dto, soporte prioritario
- Pro (59€/mes): 15 % dto, hold prioritario, 1 cancelación flexible/mes
Flujo: ver planes → Stripe Subscription → badge en UI
F8 — Operador: bloqueo y dashboard
- Login rol operador
- Dashboard: estaciones del día, llegadas, ocupación %
- Bloquear franja: motivo + rango
- Slots dejan de venderse
Estados de UI transversales
| Estado | Comportamiento |
|---|---|
| Empty listado | Ilustración industrial + “Ampliar zona o quitar filtros” |
| Loading | Skeletons, no spinners de página completa en móvil |
| Error red | Banner + Reintentar |
| Validación | Inline bajo campo, aria-invalid |
| 403 | “No tienes acceso” + volver |
| Sesión expirada | Modal → re-login, preservar deep link |
| Sin resultados | Empty específico |
| Pago parcial | No aplica (all-or-nothing) |
| Destructivo | Modal confirmación cancelar/borrar cuenta |
| Undo | Toast 5 s solo en favoritos (no en pagos) |
Eventos analíticos (lista maestra)
Ver 12-analytics.md.