Skip to content

Componente Navbar - Documentación Técnica

Componente: ts/core/components/layout/Navbar.tsxTipo: Layout Component (Core) Estado: Implementado


Descripción General

Navbar es la barra de navegación superior del layout AdminLTE. Se renderiza dentro de Layout y consume ConfigContext de forma opcional para leer permisos del usuario.

Características principales:

  • Lectura de ConfigContext con useContext directo (compatible con React Compiler)
  • Renderizado condicional de SchemaSelectors según permiso CONFIG_CAMBIO-SUCURSAL
  • Soporte de prop fallback para entornos sin ConfigProvider (modo heredado)
  • Renderizado de nombre de usuario y período de ejercicio opcionales

Arquitectura Dual: Navbar Legacy vs. React Navbar

El sistema mantiene dos barras de navegación coexistentes:

AspectoLegacy (PHP SSR)React Navbar
Archivophp/components/ (views PHP)ts/core/components/layout/Navbar.tsx
RenderizadoServidor (PHP)Cliente (React)
ContextoVariables PHP globalesConfigContext
EstadoSolo mantenimientoActivo / en uso
UsoMódulos legacy sin migrarApps React Full Module

La React Navbar solo aparece en apps que usan el componente Layout (ver sección de consumidores).


Patrón useContext(ConfigContext) — Optional Provider Consumption

Decisión de diseño

Navbar usa useContext(ConfigContext) directamente en lugar de useConfig().

AspectouseConfig()useContext(ConfigContext)
Comportamiento sin ProviderLanza ErrorRetorna undefined
Hooks en try/catchRequería el anti-patrónNo aplica
React CompilerViolación (hooks-in-try)Compatible
Uso correctoComponentes que requieren configComponentes con config opcional

useConfig() sigue siendo la opción correcta para componentes donde ConfigProvider es obligatorio (formularios, vistas de módulos).

useContext(ConfigContext) es la opción correcta cuando el componente puede funcionar sin ConfigProvider (modo fallback por props).

Fuentes de datos en Navbar

Nombre de usuario:  config?.usuario.usuario  ?? props.userName
Permiso sucursal:   config?.usuario.permisos.includes('CONFIG_CAMBIO-SUCURSAL') ?? false

Si ConfigProvider está ausente, config es undefined y se usan los valores fallback (props.userName, sin selectores de esquema).


SchemaSelectors — Renderizado Condicional

SchemaSelectors se renderiza dentro de Navbar como <li> implícito via React.Fragment.

Condición de visibilidad:

  • El usuario tiene el permiso CONFIG_CAMBIO-SUCURSAL en AppConfiguration.usuario.permisos
  • Y hay más de una sucursal o más de una caja disponible (lógica interna de SchemaSelectors)

Ubicación del componente: ts/config/components/SchemaSelectors.tsx

Corrección HTML: Fragment en lugar de div

SchemaSelectors usa React.Fragment como wrapper raíz (no <div>).

Motivo: Navbar renderiza sus hijos dentro de <ul className="navbar-nav">. Un <div> como hijo directo de <ul> produce HTML inválido. React.Fragment permite que SucursalSelect y CajaSelect se rendericen como <li> directos de la <ul>.


Jerarquía de Componentes

Layout
  └── Navbar
        ├── MaintenanceBanner
        └── SchemaSelectors [condicional: CONFIG_CAMBIO-SUCURSAL]
              ├── SucursalSelect [condicional: múltiples sucursales o cajas]
              └── CajaSelect [condicional: sucursal seleccionada + múltiples cajas]

Estructura de Archivos

ts/
├── core/
│   ├── components/layout/
│   │   └── Navbar.tsx              # Componente principal
│   ├── context/
│   │   └── ConfigContext.tsx       # ConfigContext + ConfigProvider + useConfig
│   └── types/
│       └── layout.types.ts         # NavbarProps
└── config/
    └── components/
        ├── SchemaSelectors.tsx     # Contenedor de selectores (usa React.Fragment)
        ├── SucursalSelect.tsx      # Selector de sucursal
        └── CajaSelect.tsx          # Selector de caja (depende de sucursal)

Props

NavbarProps (todas opcionales):

PropTipoDescripción
userNamestringNombre de usuario fallback cuando ConfigProvider está ausente
showExercisePeriodbooleanMostrar el período de ejercicio. Default: false
exercisePeriodstringTexto del período de ejercicio

Layout construye NavbarProps desde sus propios props y los pasa a Navbar.


Gestión de Estado

No hay estado local en Navbar. El estado de los selectores de esquema es encapsulado en SchemaSelectors.

SchemaSelectors maneja internamente:

  • currentSucursal: sucursal activa seleccionada por el usuario
  • shouldShowSelectors: booleano derivado de la cantidad de sucursales/cajas
  • sucursalData: array con datos de sucursales y conteo de cajas
  • loading: estado de carga inicial

Integración con API (SchemaSelectors)

SchemaSelectors consume dos endpoints vía api.get:

  • GET /config/sucursales — Lista de sucursales disponibles
  • GET /config/sucursales/{sucursal}/cajas — Cajas de una sucursal

Ambas respuestas se cachean en localStorage via sucursalStorage utils. No usan TanStack Query (inicialización de estado estructural, no datos reactivos).


Aplicaciones Consumidoras

Cualquier app que use Layout obtiene Navbar (y SchemaSelectors) automáticamente.

Apps actualmente en producción:

AppArchivoIncluye ConfigProvider
MembershipsAppts/mod-membresias/MembershipsApp.tsxSí — SchemaSelectors activo
CRMAppts/crm/CRMApp.tsxSí — SchemaSelectors activo

Patrón esperado para nuevas apps:

StrictMode
  └── ConfigProvider          ← habilita SchemaSelectors en Navbar
        └── HashRouter
              └── Layout      ← incluye Navbar con SchemaSelectors condicional
                    └── AppRouter

Apps que omitan ConfigProvider seguirán funcionando (Navbar acepta ausencia de contexto), pero no mostrarán SchemaSelectors.


Accesibilidad

  • La <nav> usa clases AdminLTE con rol semántico correcto
  • <a data-widget="pushmenu"> mantiene role="button" para accesibilidad
  • SchemaSelectors se renderiza como React.Fragment garantizando HTML válido dentro de <ul>

Notas Adicionales

  • useConfig() NO debe usarse en Navbar — lanza error si ConfigProvider está ausente
  • El permiso CONFIG_CAMBIO-SUCURSAL es el único gate para mostrar selectores de esquema; la visibilidad interna (múltiples sucursales/cajas) la controla SchemaSelectors por su cuenta
  • MaintenanceBanner también se renderiza en Navbar con lógica de visibilidad propia, independiente de ConfigContext