Saltar a contenido

ADR-022 — Gestor responsive (sidebar colapsable) + PWA instalable

  • Status: accepted (operador 2026-08-22; enmienda parcial a ADR-015 sobre el uso del gestor)
  • Context: ADR-015 definió el gestor como herramienta interna de escritorio (stack WorkDone). En la práctica hay una tarea genuinamente móvil — registrar la entrega del premio en la sucursal (verificar DNI del ganador, sucursal, responsable) — que hoy es incómoda: el sidebar mide 240px fijos y nunca se colapsa, comiendo dos tercios de un teléfono de 375px. El operador pidió que el gestor "se vea bien en el celular" sin abrir un segundo proyecto (app nativa).
  • Alternatives:
  • App móvil nativa del gestor completo: otro código, otro stack (rompe ADR-015), fricción de app store, mantenimiento — sobre-ingeniería para tareas mayormente de escritorio.
  • Responsive del gestor actual + PWA instalable (elegida): reusa todo el stack existente, un solo código, y cubre al personal de sucursal que administra desde el teléfono.
  • Decision:
  • Responsive: el sidebar se colapsa a un drawer (hamburguesa) por debajo de md (768px); el contenido pasa a ancho completo; las tablas siguen con scroll horizontal dentro de su contenedor (no scroll del body). Solo Tailwind + los componentes existentes, sin librería nueva (ADR-015).
  • PWA: manifest.webmanifest (nombre "Sistema Premios", scope/start_url /gestor/, display standalone, theme = rojo de branding, íconos) + un service worker mínimo que cachea el shell de la app para instalabilidad — NUNCA cachea respuestas de /api (el gestor es una herramienta viva; datos siempre frescos). Servido por el jar bajo /gestor/. Compatible con el CSP estricto (SW y manifest son same-origin self).
  • Consequences: El gestor entero queda usable en teléfono/tablet para la entrega en mostrador, sin segundo codebase. La PWA da ícono en el teléfono. El branding del cliente (color/logo, ADR-branding) alimenta el theme del manifest. No se toca la landing.

Implementation Plan

  • gestor/src/components/layout/AppShell.tsx: sidebar → hidden md:flex + drawer overlay con botón hamburguesa en un header móvil; cierra al navegar; foco/aria correctos.
  • gestor/public/manifest.webmanifest + íconos (192/512, maskable); <link rel="manifest"> y meta theme-color en index.html; registro del SW en main.tsx (solo en prod build).
  • gestor/public/sw.js (o vite-plugin-pwa si no agrega peso/stack — evaluar; preferir SW a mano si el plugin trae mucho): precache del shell, NetworkOnly para /api y /bases.
  • Backend: servir /gestor/manifest.webmanifest y /gestor/sw.js con content-type correcto y Service-Worker-Allowed: /gestor/; el SW debe poder tener scope /gestor/.

Verification

  • [ ] AC-36 — Sidebar colapsa a drawer < 768px; todos los ítems de navegación alcanzables por el menú hamburguesa; se cierra al elegir uno.
  • [ ] AC-37 — Sin scroll horizontal del body en el gestor a 375px (las tablas scrollean dentro de su contenedor).
  • [ ] AC-38 — PWA instalable: manifest válido (nombre, íconos 192/512, start_url /gestor/, display standalone) y service worker registrado con scope /gestor/.
  • [ ] AC-39 — El service worker NUNCA sirve respuestas cacheadas de /api/** (siempre red).