- 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>
42 lines
2.3 KiB
Markdown
42 lines
2.3 KiB
Markdown
# web
|
|
|
|
Frontend Angular (standalone, zoneless, señales) del ERP base. Interfaz densa y ligera estilo SAP Business One.
|
|
|
|
```bash
|
|
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).
|