feat(F-159): completed feature
This commit is contained in:
24
work/artifacts/F-159/architect.md
Normal file
24
work/artifacts/F-159/architect.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# F-159 — Diseño
|
||||
|
||||
## Arquitectura
|
||||
El estado vive en `DashboardShell`, única composición del layout autenticado:
|
||||
|
||||
- `desktopCollapsed`: preferencia persistida en `localStorage` bajo `mdv.admin.sidebar.collapsed`.
|
||||
- `mobileOpen`: estado efímero del drawer.
|
||||
|
||||
`Sidebar` y `NavItemRow` siguen consumiendo la misma lista `visibleNavItems(role)`. No se crean menús alternativos.
|
||||
|
||||
## Responsive
|
||||
- Sidebar base: drawer `fixed`, 240px y desplazado fuera de viewport cuando está cerrado.
|
||||
- `lg+`: pasa a `sticky`, siempre visible, ancho 240px/80px según preferencia.
|
||||
- Etiquetas usan `lg:hidden` solo durante collapse, por lo que el drawer móvil siempre conserva texto.
|
||||
- Backdrop solo se renderiza con drawer abierto.
|
||||
|
||||
## Accesibilidad
|
||||
- Toggle es `<button>` nativo con `aria-expanded`, `aria-controls` y etiqueta dinámica.
|
||||
- Escape cierra drawer.
|
||||
- Drawer móvil cerrado usa `invisible` para excluir enlaces del foco.
|
||||
- Enlaces tienen `aria-label`; modo icon-only añade `title`.
|
||||
|
||||
## Transiciones
|
||||
`transition-[width,transform] duration-300 ease-in-out`, respetando las utilidades existentes de Tailwind.
|
||||
5
work/artifacts/F-159/documenter.md
Normal file
5
work/artifacts/F-159/documenter.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# F-159 — Uso
|
||||
|
||||
- En desktop, el botón del header colapsa/expande el sidebar. La preferencia se conserva al recargar.
|
||||
- Colapsado muestra iconos; cada icono mantiene tooltip y nombre accesible.
|
||||
- En mobile/tablet, el botón abre un drawer. Se cierra al navegar, pulsar el fondo, el botón de cierre o Escape.
|
||||
20
work/artifacts/F-159/implementer.md
Normal file
20
work/artifacts/F-159/implementer.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# F-159 — Implementer
|
||||
|
||||
## Implementación
|
||||
- `SidebarToggle` reutilizable para desktop y mobile.
|
||||
- Estado desktop `expanded/collapsed` persistido en `localStorage` (`mdv.admin.sidebar.collapsed`).
|
||||
- Desktop colapsado reduce 240px→80px y oculta etiquetas solo en breakpoint `lg`.
|
||||
- Mobile/tablet usa el mismo sidebar como drawer con backdrop y cierre por navegación, botón o Escape.
|
||||
- Drawer cerrado queda `invisible`, evitando foco en enlaces fuera de pantalla.
|
||||
- Transiciones suaves de ancho, transformación e icono.
|
||||
- Accesibilidad: botones nativos, `aria-label`, `aria-expanded`, `aria-controls`, `aria-current`, focus rings y tooltips.
|
||||
- Restaurado acceso visible a cerrar sesión dentro del sidebar.
|
||||
|
||||
## Evidencia
|
||||
- `cd project/apps/admin && npm run build`: PASS (29 rutas).
|
||||
- `cd project && node_modules/.bin/tsc --noEmit`: PASS.
|
||||
- `git diff --check`: PASS.
|
||||
- `./scripts/verify.sh`: PASS.
|
||||
|
||||
## Archivo
|
||||
- `project/apps/admin/src/app/(dashboard)/layout.tsx`
|
||||
14
work/artifacts/F-159/leader-close.json
Normal file
14
work/artifacts/F-159/leader-close.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"feature_id":"F-159",
|
||||
"agent":"leader",
|
||||
"stage":"close",
|
||||
"verdict":"APPROVED",
|
||||
"summary":"SidebarToggle responsive, persistente y accesible completado.",
|
||||
"checks":[
|
||||
{"item":"reviewer","ok":true},
|
||||
{"item":"security","ok":true},
|
||||
{"item":"qa","ok":true},
|
||||
{"item":"build and verify","ok":true}
|
||||
],
|
||||
"issues":[]
|
||||
}
|
||||
15
work/artifacts/F-159/qa.json
Normal file
15
work/artifacts/F-159/qa.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"feature_id": "F-159",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Cumple persistencia, icon-only desktop, drawer mobile, transición y accesibilidad.",
|
||||
"checks": [
|
||||
{"item":"Desktop collapse","ok":true,"evidence":"lg width 60→20 and lg-only label hiding"},
|
||||
{"item":"Mobile/tablet drawer","ok":true,"evidence":"fixed transform drawer plus backdrop"},
|
||||
{"item":"Keyboard","ok":true,"evidence":"Native buttons, focus rings and Escape handler"},
|
||||
{"item":"Persistence","ok":true,"evidence":"Stable localStorage key"},
|
||||
{"item":"Regression","ok":true,"evidence":"Admin build, tsc and verify passed"}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
14
work/artifacts/F-159/reviewer.json
Normal file
14
work/artifacts/F-159/reviewer.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"feature_id": "F-159",
|
||||
"agent": "reviewer",
|
||||
"stage": "review_gate",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Una única jerarquía de navegación cubre collapse desktop y drawer mobile sin duplicación.",
|
||||
"checks": [
|
||||
{"item":"Single navigation source","ok":true,"evidence":"Sidebar maps visibleNavItems once"},
|
||||
{"item":"Persisted desktop state","ok":true,"evidence":"localStorage key read on mount and written on toggle"},
|
||||
{"item":"Mobile drawer","ok":true,"evidence":"fixed drawer, backdrop, route close and Escape close"},
|
||||
{"item":"Admin build","ok":true,"evidence":"Next.js production build passed"}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
13
work/artifacts/F-159/security.json
Normal file
13
work/artifacts/F-159/security.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"feature_id": "F-159",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Solo se persiste una preferencia booleana no sensible; no cambian auth, permisos ni destinos de navegación.",
|
||||
"checks": [
|
||||
{"item":"No sensitive storage","ok":true,"evidence":"localStorage contains only collapsed boolean"},
|
||||
{"item":"RBAC preserved","ok":true,"evidence":"Navigation remains filtered by visibleNavItems(role)"},
|
||||
{"item":"No dependency change","ok":true,"evidence":"Uses React and existing Tailwind only"}
|
||||
],
|
||||
"issues": []
|
||||
}
|
||||
@@ -1,17 +1,23 @@
|
||||
# Feature activa: F-158 — POS use same-origin API proxy on LAN
|
||||
# Feature activa: F-159 — Admin responsive collapsible sidebar
|
||||
|
||||
## Problema
|
||||
El TPV abierto en `http://192.168.18.93:3006` ejecuta peticiones del navegador contra `http://localhost:3000`. En un cliente LAN, `localhost` apunta al propio cliente y produce `ERR_CONNECTION_REFUSED`.
|
||||
## Objetivo
|
||||
Añadir un único `SidebarToggle` reutilizando el layout y `NAV_ITEMS` existentes.
|
||||
|
||||
## Alcance
|
||||
- El cliente POS usa rutas same-origin `/api/...`.
|
||||
- El route handler de Next.js reenvía las peticiones al backend privado (`127.0.0.1:3000`).
|
||||
- El proxy conserva cookies de sesión y `x-terminal-id`.
|
||||
- El login propaga `Set-Cookie` al navegador.
|
||||
- Next dev permite el origen LAN `192.168.18.93`.
|
||||
## Comportamiento
|
||||
- Desktop (`lg+`): expandido a 240px o colapsado a 80px mostrando solo iconos; preferencia guardada en `localStorage`.
|
||||
- Mobile/tablet: sidebar como drawer superpuesto con backdrop; siempre muestra iconos y etiquetas.
|
||||
- El estado del drawer no duplica ni sustituye el estado persistido de desktop.
|
||||
- Transición suave de ancho y desplazamiento.
|
||||
|
||||
## Accesibilidad
|
||||
- Botones con `aria-label`, `aria-expanded` y `aria-controls`.
|
||||
- Drawer cerrado no es visible ni alcanzable por teclado.
|
||||
- Escape cierra el drawer.
|
||||
- Los enlaces conservan etiquetas accesibles y tooltips al colapsar.
|
||||
|
||||
## Aceptación
|
||||
1. El navegador no solicita directamente `localhost:3000`.
|
||||
2. `GET /api/pos/config` llega al backend mediante el proxy.
|
||||
3. Login conserva la cookie de sesión.
|
||||
4. POS build, TypeScript y `verify.sh` pasan.
|
||||
1. Toggle visible y operable por teclado.
|
||||
2. Preferencia desktop persiste tras recarga.
|
||||
3. Sidebar desktop colapsado muestra solo iconos.
|
||||
4. Mobile/tablet usa drawer con backdrop y cierre por Escape.
|
||||
5. Una sola fuente de navegación y build responsive sin regresiones.
|
||||
|
||||
@@ -1,11 +1,68 @@
|
||||
{
|
||||
"feature_id": null,
|
||||
"stage": "idle",
|
||||
"feature_id": "F-159",
|
||||
"stage": "close",
|
||||
"agent": "leader",
|
||||
"action": "Sin ejecución activa",
|
||||
"state": "waiting",
|
||||
"action": "Close SidebarToggle feature",
|
||||
"state": "running",
|
||||
"next_agent": "leader",
|
||||
"waiting_for": "Seleccionar una feature pending y actualizar este estado",
|
||||
"updated_at": "2026-08-22T15:51:06Z",
|
||||
"timeline": []
|
||||
"updated_at": "2026-08-22T16:01:58Z",
|
||||
"timeline": [
|
||||
{
|
||||
"ts": "2026-08-22T15:58:39Z",
|
||||
"agent": "leader",
|
||||
"stage": "intake",
|
||||
"state": "running",
|
||||
"message": "Define responsive persisted SidebarToggle"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T15:59:15Z",
|
||||
"agent": "architect",
|
||||
"stage": "design",
|
||||
"state": "running",
|
||||
"message": "Design shared desktop collapse and mobile drawer state"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T15:59:47Z",
|
||||
"agent": "implementer",
|
||||
"stage": "build",
|
||||
"state": "running",
|
||||
"message": "Implement accessible persisted SidebarToggle"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T16:01:08Z",
|
||||
"agent": "reviewer",
|
||||
"stage": "review_gate",
|
||||
"state": "running",
|
||||
"message": "Review shared responsive sidebar implementation"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T16:01:19Z",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"state": "running",
|
||||
"message": "Audit localStorage and navigation accessibility"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T16:01:30Z",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"state": "running",
|
||||
"message": "Validate desktop/mobile/accessibility acceptance"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T16:01:48Z",
|
||||
"agent": "documenter",
|
||||
"stage": "document",
|
||||
"state": "running",
|
||||
"message": "Document sidebar responsive behavior"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-22T16:01:58Z",
|
||||
"agent": "leader",
|
||||
"stage": "close",
|
||||
"state": "running",
|
||||
"message": "Close SidebarToggle feature"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user