RELE · 04-user-flows.md · 6 de 22

En esta página 1. Mapa de flujos 0%

04 — Flujos de usuario — RELE

1. Mapa de flujos

IDFlujoActorÉxito
F0Descubrimiento homeVisitanteEntiende valor y va a login
F1LoginRESIDENT / ADVISORJWT + redirect /lecturas
F2Consultar lecturas + statsAmbosLista y strip stats
F3Crear lecturaRESIDENTReading SUBMITTED con código
F4Revisar y cambiar estadoADVISORREVIEWED o FLAGGED + nota
F5Empty stateRESIDENT (0 items)CTA a nueva lectura
F6Error de redAmbosMensaje + reintento
F7LogoutAmbosLimpia token

2. F0 — Home → Login

[/] → CTA "Soy residente" | "Soy asesor" | "Abrir panel"
    → [/login]
PasoUINotas
1Hero + media + 3 pasosCopy: sin Excel / WhatsApp
2Click CTAAmbos CTAs a /login (mismo form; [DECISIÓN])
3Login prefill residentecasa@rele.energy por defecto en demo

3. F1 — Login JWT

[/login] → email + password → POST /api/auth/login
  OK → localStorage (rele_token, rele_user) → [/lecturas]
  KO → mensaje "Credenciales inválidas"
CampoValidación clienteServer
emailrequired, type email@IsEmail()
passwordrequired, min práctico@MinLength(6) + bcrypt

Errores

CasoRespuestaUI
Password incorrecta401coral “Credenciales inválidas”
API caídanetwork errormismo mensaje genérico o red

4. F2 — Lista + stats

[/lecturas] (token required)
  → GET /api/readings/stats/summary
  → GET /api/readings
  → render cards + badges
RolDatos
RESIDENTSolo residentId = me; include home + advisor
ADVISORTodas; include home + resident

Soft auth UI: si no hay token → navigateByUrl('/login').

Variantes

EstadoCondiciónUI
Loadingpetición en cursolista vacía / sin empty (loading flag)
Empty200 + []“Sin lecturas todavía” + CTA si RESIDENT
ErrorHTTP errorpanel coral + Reintentar
Successitems ≥ 1lista ordenada createdAt desc

5. F3 — Crear lectura (RESIDENT)

[/lecturas] → "Nueva lectura" → [/lecturas/nueva]
  → period, kwh, costEur?, notes?
  → POST /api/readings
  → OK → [/lecturas] (o detalle según impl.)
  → ADVISOR que intenta POST → 403
CampoReqEjemplo
period2026-08
kwhSí, ≥ 0245
costEurNo56.1
notesNoLectura contador 14 ago

Server [COMPROBADO en código]:

  1. Solo role === RESIDENT.
  2. Resuelve Home del residente (primera o crea default).
  3. status = SUBMITTED, code = RE-MMDD-XXX.

6. F4 — Detalle + status (ADVISOR)

[/lecturas] → click card → [/lecturas/:id]
  → GET /api/readings/:id
  → (si ADVISOR) textarea nota + botones REVIEWED | FLAGGED
  → PATCH /api/readings/:id/status { status, advisorNote? }
  → UI actualiza item
Transición típicaDesdeHacia
Validar OKSUBMITTEDREVIEWED
Anomalía / tarifaSUBMITTED o REVIEWEDFLAGGED
Re-validarFLAGGEDREVIEWED

Permisos

ActorPuede ver detallePuede PATCH
RESIDENT dueñoNo
RESIDENT ajeno403No
ADVISOR

7. F5 — Empty

CondiciónMensajeCTA
RESIDENT 0 lecturas“Sin lecturas todavía…”Registrar lectura
ADVISOR 0 lecturasMismo empty sin CTA create

8. F6 — Error de red (lista)

GET fallan → error string → panel "No se pudieron cargar las lecturas"
  → [Reintentar] → load()

9. F7 — Logout

click Salir → ApiService.logout() → limpia localStorage → login/home

10. Diagrama de estados Reading

        create (RESIDENT)


          SUBMITTED ◄──────────────┐
           /      \                │
          /        \               │
         ▼          ▼              │
     REVIEWED    FLAGGED ──────────┘
         \          /   (PATCH ADVISOR)
          \        /
           ▼      ▼
        (ambos pueden re-etiquetarse vía PATCH libre en v1)

Nota [DECISIÓN]: la API acepta cualquier ReadingStatus en PATCH (enum); no hay máquina de estados rígida server-side más allá de rol ADVISOR. DRAFT existe en enum para evolución, no se emite en create v1.


11. Criterios de aceptación por flujo

FlujoAC
F1Login demo 200; mal password mensaje visible
F2Stats total/open/kwhTotal coherentes con seed
F3POST crea SUBMITTED con code RE-
F4PATCH REVIEWED asigna advisorId
F5Empty sin crash
F6Reintentar re-lanza GETs