Skip to main content

Pantallas y ruteo

Ruteo tipado

Toda pantalla es un standalone component lazy-loaded desde una ruta declarada con typesafe-routes. Cada nivel tiene dos objetos: uno typed (para construir paths sin strings) y uno de Angular.

// pages/<feature>/<feature>.routes.ts
export const depositTypedRoutes = createRoutes({
stats: { path: ['stats'] },
authorizations: { path: ['authorizations'] },
detail: { path: ['detail', int('id')] },
});

export const depositRoutes: Routes = [
{
path: template(depositTypedRoutes.stats),
loadComponent: () =>
import('./deposit-stats/deposit-stats.component').then(m => m.DepositStatsComponent),
},
];
  • template(typedRoute) → el path: de Angular.
  • renderPath(typedRoute, params) → la URL para routerLink / router.navigate.
  • Params: int('id'), str('name').

Nunca armes la URL a mano donde existe la ruta tipada.

La composición es app.routes.tspages/private.routes.ts + pages/public.routes.ts<feature>.routes.ts. appTypedRoutes funde los tres, así renderPath(appTypedRoutes.x.y, {}) funciona desde cualquier lado.

typesafe-routes también se usa para URLs de API (src/app/api/api.routes.ts), con la convención método + nombre (GET_pdf, POST_receive). Hoy solo están migrados los endpoints de delivery-note; el resto arma strings en los servicios.

Los tres shells

ShellCuándoGuard
LayoutComponentApp autenticada (header + menú)redirectUnauthorizedToLogin()
PublicLayoutComponentLogin, recuperar contraseñaredirectLoggedInToHome()
LayoutWithoutHeaderComponentLanding de descarga de BullStock (/download/mobile/bullstock)autenticado

La ruta privada '' redirige a deposit/authorizations: esa es la home real de la app.

Mapa de pantallas

RutaCarpetaQué es
deposit/*pages/deposit/La feature más grande. Autorizaciones, estadísticas, ingreso de mercadería, transferencias, recepciones, movimientos de stock, facturación, carga de remito de despacho. Servicios propios: deposit.service.ts y stock.service.ts
patients/*pages/patients/Padrón (registry) y atenciones
delivery-notespages/delivery-notes/Listado de remitos; desde acá se abren aceptar y recibir de los tres tipos
dispatch-notespages/delivery-dispatchs/Hojas de ruta (envíos)
dispatch-delivery-notes/*pages/dispatch-delivery-notes/Flujo de despacho con escáner
receive-delivery-notes/*pages/receive-delivery-notes/Flujo de recepción con escáner, por pasos
staff/*pages/vehicles/Flota: asignaciones, inspecciones VTV/RTO/seguro, eventos. Ojo: la ruta es staff, la carpeta es vehicles
configuration/*pages/configuration/ABM de Elementos y Productos (+ hijos e imágenes). Gateado por rol ADMIN estricto
call-centerpages/call-center/Atención telefónica
messagespages/messages/WhatsApp
reportspages/reports/Descarga de reportes Excel
surveyspages/surveys/Encuestas
notificationspages/notifications/Centro de notificaciones, con vista tipo mail y preview del PDF del remito
mappages/map/Visualización geográfica
user/historypages/user/"Mi actividad"
Dos pantallas que no son lo que parecen
  • pages/table/ es una página demo con datos hardcodeados ({ name: 'John Doe', … }). Está ruteada en /table pero no figura en el menú. No la uses de molde: no representa cómo se hace una tabla real acá.
  • pages/register/ existe como componente pero su ruta no está registrada: es inalcanzable.

Menú

services/menu.service.ts devuelve el árbol de MenuItem[] de PrimeNG para header y sidebar.

  • Hay bastante menú comentado; el vigente arranca en "Estadísticas".
  • El grupo Configuración se agrega condicionalmente con userAccessService.isAdmin(), que compara role.name === 'ADMIN' — el mismo criterio estricto que usa el backend. Si desalineás uno de los dos, el menú muestra una sección que la API rechaza.
  • El grupo Mercadería todavía usa iconos FontAwesome (fa fa-…); el resto usa PrimeIcons.

Guards

GuardQué hace
auth.guard.tsredirectUnauthorizedToLogin() / redirectLoggedInToHome() sobre el estado de Clerk
permission.guard.tsrequirePermission(code) y requireRole(name). Al fallar: toast "Acceso denegado" + navegación a deposit/authorizations
CanDeactivate localesPor feature, para formularios con cambios sin guardar (attention-form-can-deactivate.guard.ts, dispatch-scanner-can-deactivate.guard.ts)

Ver Permisos y roles.

Estado de la tabla entre navegaciones

El estado de una p-table (orden, página, filtros) se persiste en sessionStorage con claves de enums/table-state-key.enum.ts; la pestaña activa va a localStorage con enums/local-storage.enum.ts.

Si agregás una tabla que tenga que "volver como estaba", sumá tu clave a esos enums en vez de inventar un string suelto.