Skip to content

Admin — Navegación, formularios y listas (UI)

Snapshot de la interfaz del panel admin (camaroneras_admin). Se actualiza cuando un módulo cambia la UI (parte del cierre de cada tarea con UI).

RutaTipoGuard / acceso
/loginpública (GuestRoute)si hay sesión → /dashboard; sin link de registro (alta solo por invitación)
/onboardingregistrorequiere onboardingToken (si no → /login); nombra la organización en la alta delegada
/forgot-password, /reset-passwordpúblicas (GuestRoute)recuperación
/accept-invitation?token=públicasin token → /login
/dashboardprotegidaProtectedRoute (sesión)
/piscinasprotegidaProtectedRoute + piscinas:ver (sin permiso → /dashboard)

Gestión de usuarios/roles: no vive en este repo. La gestión cross-tenant de usuarios/roles de una organización se hace desde camaroneras_platform (/organizations/:id/members, /organizations/:id/roles, superadmin) — ver plataforma/superadmin-flow.md.

  • Layout (AppLayout): sidebar en desktop, topbar + drawer (Sheet) en mobile. El menú es una lista plana de ítems, filtrada según los permisos del usuario (hook usePermission). Avatar con iniciales + logout.
    • Sidebar colapsable (solo desktop): toggle que alterna entre menú completo (w-64) y rail de solo íconos (w-16, con tooltips). El drawer mobile no se colapsa.
    • Preferencias de UI persistentes (localStorage, vía hook useLocalStorage en shared/hooks/): colapso del sidebar (clave sidebar-collapsed). Si localStorage no está disponible, cae a memoria (la UI no se rompe, solo no persiste entre recargas).
  • SessionRestore envuelve el router: al recargar, hace silent refresh con la cookie antes de pintar (evita parpadeo a /login).
  • Gate de cliente web: en login, si clients no incluye web → no entra ("usa la app móvil").

Componentes de formulario (convención)

En src/shared/components/, reutilizables, con label + error + aria:

  • FormField — input (text/email/number/date) con label y error.
  • PasswordField — password con botón mostrar/ocultar.
  • FormSelect — select (Base UI) que recibe options: {value,label}[].
  • FormCombobox — select con búsqueda (Base UI Combobox), mismo contrato que FormSelect.

El <Select> crudo solo se usa en ediciones inline de tabla (sin label), no en formularios.

Formularios y sus campos

Auth

  • Login: email, contraseña (PasswordField). Sin link de registro (alta solo por invitación); link ¿olvidaste contraseña?
  • Onboarding: nombre de la camaronera, tu nombre (administrador).
  • Forgot password: email. Reset password: código OTP, nueva contraseña, confirmar.
  • Accept invitation: contraseña, confirmar (token viene en la URL).

Piscinas

  • Nueva/editar piscina (dialog): código (FormField), hectáreas (FormField number), tipo (FormSelect: engorde/precriadero), tope lb/ha (FormField number, opcional), sector (FormCombobox, con búsqueda).
  • Sectores (dialog): nombre (FormField) + lista con eliminar.
  • Equipos (dialog, por piscina): tipo de equipo (FormSelect), cantidad (FormField), desde (FormField date).

Listas y detalles

Piscinas (tabla)

Columnas: Piscina (código), Sector, Hectáreas, Tipo (badge), Tope lb/ha, Acciones (Equipos · Editar · Eliminar, según permiso).

  • Detalle de equipos (dialog): equipos vigentes (tipo + cantidad), formulario de asignación, e historial de asignaciones con fecha.

Protecciones transversales

  • Rutas protegidas por sesión (ProtectedRoute) y por permiso (module/action).
  • Acciones (botones) ocultas/deshabilitadas según usePermission.
  • La UI es espejo de UX; la autorización real es el backend (403 aunque la UI falle).