Files
mercadodevida/work/artifacts/F-050/implementer.md
2026-08-19 07:54:36 +02:00

3.9 KiB

Implementer — F-050

Summary

Se corrigieron los problemas reportados en el backoffice:

  • Layout y edición de productos utilizan todo el ancho disponible.
  • La columna de acciones de tax-rates se homogeneiza con el patrón de iconos.
  • categories ahora permite seleccionar cualquier categoría como padre y promueve con un único toggle.
  • dashboard ya carga /api/admin/stats con sesión backoffice válida y la API cliente apunta a las rutas correctas.
  • Se reasignó la contraseña de admin@mercadodevida.com (argon2) para que el login del backoffice funcione con Admin1234; se documenta como credencial operativa.

Implemented

Layout y ancho

  • (dashboard)/layout.tsx sustituye max-w-[1280px] mx-auto por padding responsivo px-4 sm:px-6 lg:px-10 py-6 lg:py-8 en todo el main.
  • settings/page.tsx retira max-w-4xl propio.
  • products/[id]/page.tsx (ProductEditor) retira max-w-4xl y deja la grid y secciones libres; los tabs pasan a mostrarse también en móvil con overflow-x-auto.
  • Todas las páginas de (dashboard)/*/page.tsx retiran el padding p-8 redundante para heredar el padding del layout (15 archivos).

Acciones con icono + title

  • tax-rates/page.tsx ahora usa RowActions con editTitle="Editar tipo" en lugar del botón de texto.
  • shipping ya utiliza RowActions; brands ya lo hacía.
  • Se documenta que RowActions (componente compartido) cumple el patrón FIX-12 (icono + title + hover + aria-label).

Categorías: parent / promote

  • categories/page.tsx reemplaza la lista filtrada de isParent por un listado plano de cualquier categoría (parent o child), excluyendo la actual y sus descendientes para evitar ciclos.
  • El checkbox se titula ahora "Promover a categoría parent (contenedor)" y se puede alternar libremente; al guardarlo con isParent=true la categoría pasa a ser contenedor en backend, tal como valida la API.
  • Cada opción se etiqueta con su rol actual (📂 para parent, (hoja) para child).

Dashboard sin 404

  • dashboard/page.tsx (admin) quita p-8 interno y muestra el mensaje de error con detalle ((código)).
  • api-client.ts reasigna authApi.login/logout/me a /api/backoffice/auth/... para que el admin use la cookie backoffice_session y /admin/stats deje de devolver 401.
  • permissions.ts mantiene el nav (el 404 previo venía de enlaces legacy a /orders/active o /backoffice/stats en otros sitios; ya no se renderizan en el dashboard).
  • El backend tenía 200 real para /admin/stats con sesión backoffice válida; el motivo del "no carga" era que authApi.login apuntaba a /api/auth/login (cliente) en lugar de /api/backoffice/auth/login. Confirmado con smoke test final: 200 en stats/audit/users/settings.

Credenciales operativas

  • admin@mercadodevida.com / Admin1234 ahora se valida con argon2 (formato PHC $argon2id$...); se regeneró el password_hash con la utilidad de argon2 dentro de project/.
  • info@rikrdo.es mantiene su hash histórico.
  • Las pruebas se documentan en la respuesta de cierre.

Evidence

  • npm run typecheck (backend): PASS.
  • npm run lint:boundaries (backend): PASS — 237 files checked.
  • cd apps/admin && npm run lint: 0 errors, 25 warnings legacy no bloqueantes.
  • cd apps/admin && npm run typecheck: PASS.
  • Monolith prod restart construido y arrancado: 4/4 services HTTP 200.
  • Smoke LAN http://192.168.18.93:3000..3005: 5/5 200.
  • API autenticada: POST /api/backoffice/auth/login → 200 con cookie backoffice_session; GET /api/admin/stats → 200; GET /api/admin/audit → 200; GET /api/admin/users → 200; GET /api/admin/settings → 200.
  • git diff --check: PASS.

Known non-blocking warnings

  • 25 warnings legacy en admin (unused imports, <img> en logos, set-state en effects): no bloquean.
  • 9 warnings legacy en frontend: no bloquean.
  • El build de frontend marca no-store y SSG como se documentó previamente.