Files
basic-erp/apps/web
GeorgeandClaude Sonnet 5.5 4c8c499a72 feat(web): login, sesión, interceptor, guards y layout con menú por permisos
- Login contra POST /api/auth/login; SessionStore en localStorage con el
  timeout deslizante que informa el servidor (sessionTimeoutMinutes).
- Interceptor: Bearer en /api, renueva actividad y, ante 401, cierra la
  sesión y vuelve al login recordando la ruta (solo rutas internas).
- Guards: sesión, invitado y permiso por pantalla (data.path). Corrige que
  inject() no puede usarse tras un await en permissionGuard.
- Layout con barra superior (empresa, usuario, tema, salir) y menú lateral
  filtrado por GET /api/user/menu; plegable y con botón en pantallas angostas.
- Menú único en libs/sap-types (MENU, filterMenu); el backend verifica por
  test que las rutas de permiso de sus recursos existan en él.
- Una ruta por pantalla del menú; las no construidas muestran "no disponible".
- Verificado en Chrome headless contra el backend y SAP reales: redirección
  sin sesión, menú de 20 pantallas, navegación, plegado, tema oscuro y
  persistencia, vista móvil, salir, token inválido y credenciales malas.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 19:18:05 -05:00
..

web

Frontend Angular (standalone, zoneless, señales) del ERP base. Interfaz densa y ligera estilo SAP Business One.

npm run dev:web          # desde la raíz; http://localhost:4200 (proxy /api -> localhost:3000)
npm run build -w apps/web
npm test -w apps/web

Criterios de rendimiento

Es un ERP, no un sitio publicitario: rápido y ligero.

  • Sin librerías de UI (nada de Material/PrimeNG): componentes propios, densos (13 px).
  • Fuentes del sistema, sin webfonts; sin animaciones.
  • Zoneless + OnPush; rutas con loadComponent para cargar solo lo que se usa.
  • Presupuesto del bundle inicial: aviso a 260 kB, error a 400 kB (angular.json). Hoy: ~200 kB (56 kB comprimido).
  • Listas largas con paginación del servidor ($top/$skip) o virtualización.

Temas

El color sale solo de variables CSS (src/styles/themes/*.css). Tema por defecto: claro, con la paleta del mockup de Oferta de ventas.

Agregar un tema:

  1. src/styles/themes/<id>.css con un bloque :root[data-theme='<id>'] (copiar los tokens de light.css).
  2. @import en src/styles.css.
  3. Una entrada en src/app/core/theme/themes.ts.

Tokens: --app --shell --shell-ink --shell-quiet --win --panel --line --line-soft --ink --quiet --field --field-ro --field-b --focus --gold --grid-head --row-sel --row-alt --ok --ok-bg --warn --warn-bg --err --err-bg --btn --btn-b --btn-h --overlay --shadow-pop.

Tipos compartidos

@basic-erp/sap-types (libs/sap-types): usuario, respuestas de la API y el evaluador de permisos de menú, los mismos que usa el backend.

Autenticación y rutas

  • core/auth: SessionStore (sesión en localStorage, compartida entre pestañas, con timeout deslizante según el servidor), AuthService (login/logout/expire), interceptor (Bearer en /api, renueva actividad y atiende los 401) y guards (authGuard, guestGuard, permissionGuard).
  • core/menu: MenuService carga GET /api/user/menu una vez por sesión; el menú visible sale de MENU (@basic-erp/sap-types) filtrado por permisos.
  • app.routes.ts genera una ruta por pantalla del menú; las que aún no existen muestran "no disponible" (ComingSoonPage). Para construir una pantalla, se reemplaza su loadComponent.
  • Un 401 en cualquier llamada cierra la sesión local y lleva al login recordando la ruta (?returnUrl=, solo rutas internas).