diff --git a/docs/frontend/editor-layout-audit.md b/docs/frontend/editor-layout-audit.md new file mode 100644 index 00000000..458255e8 --- /dev/null +++ b/docs/frontend/editor-layout-audit.md @@ -0,0 +1,274 @@ +# Auditoría De Layouts De Editores + +Fecha de auditoría: 18 de agosto de 2026. + +## Objetivo + +Inventariar los editores reales del frontend del ERP y clasificarlos respecto a la norma visual vigente de edición focalizada. + +Esta auditoría: + +- inventaría rutas, páginas y dialogs de edición activos; +- clasifica cada caso por tipo; +- evalúa el layout actual frente a la norma; +- detecta desviaciones y excepciones justificadas; +- propone una secuencia pequeña de migración. + +Esta auditoría no migra masivamente las pantallas. + +## Norma visual de referencia + +SSOT vigente: + +- `packages/rdx-ui/docs/page-layouts.md` +- `packages/rdx-ui/docs/contributing-ui.md` + +Resumen operativo: + +- los editores de página completa deben usar por defecto shell `app-fullscreen`; +- la navegación mínima sale por `PageFormHeader` o un header de dominio equivalente; +- el contenido del editor se centra mediante `RdxEditorPageLayout`; +- `complexity="simple"` aplica a formularios focalizados centrados; +- `complexity="complex"` aplica a documentos o editores con `main + aside`, bloques especializados y footer sticky; +- los dialogs e inline editors no deben migrarse automáticamente a fullscreen. + +## Método de investigación + +Búsquedas y fuentes revisadas: + +- rutas y layouts en `apps/web/src/routes/app-routes.tsx` y `modules/*/src/web/*routes.tsx` +- contratos de layout en `modules/core/src/web/lib/modules/module-client.interface.ts` +- primitivas Rdx en: + - `packages/rdx-ui/src/components/editor-page/rdx-editor-page-layout.tsx` + - `packages/rdx-ui/src/components/editor-page/rdx-editor-sticky-footer.tsx` + - `modules/core/src/web/components/form/form-actions/page-form-header.tsx` + - `apps/web/src/layout/app-fullscreen-layout.tsx` + - `apps/web/src/layout/app-sidebar-layout.tsx` +- módulos revisados: + - `identity` + - `customers` + - `customer-invoices` + - `companies` + - `catalogs` + - `document-series` + - `supplier` +- búsquedas textuales sobre: + - `layout: "app-fullscreen"` + - `layout: "app-sidebar"` + - `RdxEditorPageLayout` + - `PageFormHeader` + - `RdxEditorStickyFooter` + - `create` + - `update` + - `edit` + - `Dialog` + +## Inventario + +| Module | Feature | Route | Type | Current layout | Rdx editor layout | Compliance | Risk | Priority | Recommended action | Evidence | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| `identity` | Account self-service | `/account` | `PAGE_SIMPLE` | `app-fullscreen` | `simple` | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantener como referencia de editor simple focalizado. | `modules/identity/src/web/account-routes.tsx`, `modules/identity/src/web/account/ui/pages/account-page.tsx` | +| `identity` | Change password dialog | Sin ruta propia. Dialog dentro de `/account` | `DIALOG` | Host `app-fullscreen` | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantener como dialog de edición contenida. | `modules/identity/src/web/account/ui/pages/account-page.tsx` | +| `customers` | Create customer | `/customers/create` | `PAGE_SIMPLE` | `app-fullscreen` | `simple` | `COMPLIANT` | `LOW` | `-` | Ninguna. Referencia vigente de editor simple. | `modules/customers/src/web/customer-routes.tsx`, `modules/customers/src/web/create/ui/pages/customer-create-page.tsx` | +| `customers` | Update customer | `/customers/:id/edit` | `PAGE_SIMPLE` | `app-fullscreen` | `simple` | `COMPLIANT` | `LOW` | `-` | Ninguna. Referencia vigente de editor simple. | `modules/customers/src/web/customer-routes.tsx`, `modules/customers/src/web/update/ui/pages/customer-update-page.tsx` | +| `customers` | Quick create customer | Sin ruta propia. Dialog reutilizado desde proformas | `DIALOG` | Host `app-fullscreen` | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantenerlo como creación rápida embebida. | `modules/customers/src/common/features/quick-create-customer/ui/dialogs/quick-create-customer-dialog.tsx` | +| `companies` | Company details settings | `/settings/company/details` | `PAGE_SIMPLE` | `app-sidebar` | No usa `RdxEditorPageLayout` | `EXCEPTION_JUSTIFIED` | `MEDIUM` | `P3` | Mantener en settings por ahora. Revaluar solo si se define una variante focalizada específica para formularios de settings. | `modules/companies/src/web/company-routes.tsx`, `modules/companies/src/web/settings/company-details/ui/pages/company-details-settings-page.tsx` | +| `customer-invoices` | Verifactu settings | `/settings/billing/verifactu` | `PAGE_SIMPLE` | `app-sidebar` | No usa `RdxEditorPageLayout` | `EXCEPTION_JUSTIFIED` | `MEDIUM` | `P3` | Mantener en settings por ahora. Revaluar junto con una política específica de formularios largos dentro de settings. | `modules/customer-invoices/src/web/customer-invoice-routes.tsx`, `modules/customer-invoices/src/web/settings/verifactu/ui/pages/company-verifactu-settings-page.tsx` | +| `customer-invoices` | Create proforma | `/proformas/create` | `PAGE_SIMPLE` | `app-fullscreen` | `simple` | `COMPLIANT` | `MEDIUM` | `-` | Ninguna. Mantener como bootstrap inicial de proforma hacia el editor documental completo. | `modules/customer-invoices/src/web/customer-invoice-routes.tsx`, `modules/customer-invoices/src/web/proformas/create/ui/pages/proforma-create-page.tsx`, `modules/customer-invoices/src/web/proformas/create/ui/blocks/proforma-create-form.tsx` | +| `customer-invoices` | Update proforma | `/proformas/:id/edit` | `PAGE_COMPLEX` | `app-fullscreen` | `complex` | `COMPLIANT` | `HIGH` | `-` | Ninguna. Mantener como referencia vigente de editor complejo. | `modules/customer-invoices/src/web/customer-invoice-routes.tsx`, `modules/customer-invoices/src/web/proformas/update/ui/pages/proforma-update-page.tsx`, `modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-editor-form.tsx` | +| `customer-invoices` | Change proforma status | Sin ruta propia. Dialog usado desde listado y detalle | `DIALOG` | Host mixto (`app-sidebar` o `app-fullscreen`) | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Es una edición contenida por dialog, no candidata a fullscreen. | `modules/customer-invoices/src/web/proformas/change-status/ui/change-status-dialog.tsx`, `modules/customer-invoices/src/web/proformas/list/ui/pages/list-proformas-page.tsx`, `modules/customer-invoices/src/web/proformas/detail/ui/pages/proforma-detail-page.tsx` | +| `catalogs` | Payment methods create/update | Host: `/settings/general/payment-methods` | `DIALOG` | Host `app-sidebar` | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantener como edición contenida en dialog dentro de settings. | `modules/catalogs/src/web/catalogs-routes.tsx`, `modules/catalogs/src/web/settings/payment-methods/ui/pages/payment-methods-settings-page.tsx`, `modules/catalogs/src/web/settings/payment-methods/ui/components/payment-method-form-dialog.tsx` | +| `catalogs` | Payment terms create/update | Host: `/settings/general/payment-terms` | `DIALOG` | Host `app-sidebar` | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantener como dialog aunque su contenido interno sea más rico. | `modules/catalogs/src/web/catalogs-routes.tsx`, `modules/catalogs/src/web/settings/payment-terms/ui/pages/payment-terms-settings-page.tsx`, `modules/catalogs/src/web/settings/payment-terms/ui/components/payment-term-form-dialog.tsx` | +| `catalogs` | Tax regimes create/update | Host: `/settings/general/tax-regimes` | `DIALOG` | Host `app-sidebar` | No aplica | `COMPLIANT` | `LOW` | `-` | Ninguna. Mantener como dialog de edición contenida. | `modules/catalogs/src/web/catalogs-routes.tsx`, `modules/catalogs/src/web/settings/tax-regimes/ui/pages/tax-regimes-settings-page.tsx`, `modules/catalogs/src/web/settings/tax-regimes/ui/components/tax-regime-form-dialog.tsx` | +| `customer-invoices` | Issued invoices create/edit references | Referencias a `/issued-invoices/create` y `/customer-invoices/:id/edit`, sin ruta activa | `UNCLEAR` | Sin ruta activa | No aplica | `UNKNOWN` | `MEDIUM` | `P2` | Aclarar si esas rutas deben existir o limpiar referencias muertas antes de cualquier trabajo visual. | `modules/customer-invoices/src/web/issued-invoices/list/ui/pages/list-issued-invoices-page.tsx`, `modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/issued-invoices-grid.tsx`, `modules/customer-invoices/src/web/customer-invoice-routes.tsx` | +| `document-series` | Frontend editor activo | No detectado | `LEGACY_OR_UNUSED` | Sin route frontend | No aplica | `UNKNOWN` | `LOW` | `P3` | Confirmar si el módulo tendrá UI activa antes de cualquier migración de layout. | Sin `src/web/*routes.tsx` ni páginas frontend activas en `modules/document-series` | +| `supplier` | Frontend editor activo | No detectado | `LEGACY_OR_UNUSED` | Sin route frontend | No aplica | `UNKNOWN` | `LOW` | `P3` | Resolver primero si el módulo se reactiva o se limpia; no priorizar migración visual. | Sin `src/web/*routes.tsx`; solo `modules/supplier/src/web/shared/*` | + +## Editores conformes + +Conformes respecto a la norma vigente: + +- `customers/create` +- `customers/update` +- `/account` +- `proformas/:id/edit` + +Motivos comunes observados: + +- ruta bajo `app-fullscreen`; +- navegación mínima por `PageFormHeader` o header de dominio equivalente; +- uso explícito de `RdxEditorPageLayout`; +- geometría coherente con `simple` o `complex` según caso; +- acciones de salida/guardado visibles y no delegadas al sidebar. + +## Desviaciones + +### 1. `proformas/create` + +HECHO OBSERVADO + +- la ruta usa `app-fullscreen`; +- la página usa header de edición y `RdxEditorPageLayout complexity="simple"`; +- el flujo de alta actual solo captura cabecera inicial y deriva después al editor documental completo; +- no existe todavía editor de líneas, `aside`, totales sticky ni footer persistente equivalentes a `proformas/:id/edit`. + +IMPACTO + +- el create queda alineado con el patrón focalizado simple sin fingir que ya es el editor documental completo; +- la diferencia visual restante frente a `update` responde a una diferencia funcional real y no a drift accidental de layout. + +DECISIÓN + +- `PAGE_SIMPLE`; +- `COMPLIANT`. + +### 2. Referencias a create/edit de issued invoices sin ruta activa + +HECHO OBSERVADO + +- hay referencias a `/issued-invoices/create` y a `/customer-invoices/:id/edit`; +- `customer-invoice-routes.tsx` no declara esas rutas activas. + +IMPACTO + +- el inventario de editores queda ambiguo en esa área; +- puede existir deuda de navegación muerta o una funcionalidad incompleta; +- no conviene planificar migración visual ahí hasta aclarar si hay editor real. + +RECOMENDACIÓN + +- confirmar si esas rutas deben implementarse; +- si no, limpiar referencias muertas antes de meterlas en cualquier backlog de layouts. + +## Excepciones justificadas + +### Company details settings + +HECHO OBSERVADO + +- es un formulario de página completa; +- vive bajo `/settings/company/details`; +- depende del shell de settings con `app-sidebar`. + +INFERENCIA + +- la navegación lateral de settings forma parte funcional de la tarea y hoy actúa como mecanismo primario de cambio de subsección. + +DECISIÓN DE AUDITORÍA + +- `EXCEPTION_JUSTIFIED` por ahora; +- no priorizar fullscreen salvo que el sistema de settings evolucione con una variante focalizada explícita. + +### Verifactu settings + +HECHO OBSERVADO + +- es un formulario de configuración largo; +- vive bajo `/settings/billing/verifactu`; +- comparte patrón de settings con shell lateral. + +INFERENCIA + +- igual que en `company/details`, la tarea sigue integrada en navegación de settings y no en un editor aislado. + +DECISIÓN DE AUDITORÍA + +- `EXCEPTION_JUSTIFIED` por ahora; +- revisar sólo si se aborda una política transversal de formularios largos dentro de settings. + +## Dialogs e inline editors + +Dialogs correctamente clasificados y no candidatos automáticos a fullscreen: + +- `QuickCreateCustomerDialog` +- `PaymentMethodFormDialog` +- `PaymentTermFormDialog` +- `TaxRegimeFormDialog` +- dialog de cambio de contraseña de `/account` +- `ChangeProformaStatusDialog` + +No se detectaron rutas independientes que deban reclasificarse desde `DIALOG` o `INLINE` a `PAGE_*`. + +No se detectaron inline editors de entidad de primer nivel con route propia. Sí existen bloques especializados internos, como el editor de líneas de proformas, pero forman parte de un `PAGE_COMPLEX` y no deben inventariarse como pantalla independiente. + +## Incoherencias create/update + +Agregados revisados: + +- `customers` + - `create` y `update` comparten patrón y están alineados. +- `proformas` + - `create` usa `RdxEditorPageLayout complexity="simple"` porque hoy es un bootstrap inicial; + - `update` usa `RdxEditorPageLayout complexity="complex"` porque ya es el editor documental completo con `main`, bloques especializados y footer sticky. + +Conclusión: + +- la diferencia create/update restante es funcional legítima: `create` todavía no edita el documento completo y `update` sí. + +## Riesgos de migración + +Riesgos bajos: + +- `customers/create` +- `customers/update` +- `/account` + +Riesgos medios: + +- `proformas/create` por convivencia con quick-create/select customer dialogs y porque el flujo actual parece de bootstrap inicial, no de edición documental completa; +- `company/details` y `verifactu` si se intentara moverlos fuera del shell settings. + +Riesgos altos: + +- `proformas/:id/edit`, aunque hoy ya cumple. Cualquier cambio allí impacta: + - scroll complejo + - footer sticky + - totales embebidos + - `aside` + - dialogs anidados + +## Plan incremental + +### Fase A + +- completada: migración de `proformas/create` + +Motivo: + +- era el único `PAGE_*` activo no plenamente alineado con el patrón Rdx; +- ya usaba `app-fullscreen`, así que el salto era incremental; +- permite distinguir mejor entre bootstrap inicial y editor documental completo del agregado Proforma. + +### Fase B + +- revisar si `company/details` y `verifactu` deben seguir como excepción de settings o si merece una variante focalizada específica para formularios largos dentro de settings + +Motivo: + +- ahora mismo la excepción parece razonable; +- no conviene forzar fullscreen sin una decisión explícita sobre el sistema de settings. + +### Fase C + +- aclarar `issued-invoices` create/edit + +Motivo: + +- primero hay que determinar si existe editor real o solo referencias muertas. + +### Fase D + +- hacer una auditoría UX más fina de dialogs ricos, empezando por `payment-terms` + +Motivo: + +- no es un incumplimiento de fullscreen; +- sí es el dialog más complejo de los auditados y puede requerir reglas específicas de consistencia interna. + +## No cambios + +Durante esta auditoría: + +- no se modificaron rutas ni layouts runtime de `customers`, `companies`, `customer-invoices`, `catalogs`, `identity`, `document-series` o `supplier`; +- no se tocaron hooks, controllers, formularios, React Query ni backend de los editores auditados; +- el único cambio de código del turno es este documento operativo de auditoría. diff --git a/modules/customer-invoices/src/web/proformas/create/ui/blocks/proforma-create-form.tsx b/modules/customer-invoices/src/web/proformas/create/ui/blocks/proforma-create-form.tsx index 5604b8fa..1c839047 100644 --- a/modules/customer-invoices/src/web/proformas/create/ui/blocks/proforma-create-form.tsx +++ b/modules/customer-invoices/src/web/proformas/create/ui/blocks/proforma-create-form.tsx @@ -1,6 +1,5 @@ import type { CustomerSelectionOption } from "@erp/customers"; import { preventEnterKeySubmitForm } from "@repo/rdx-ui/helpers"; -import { cn } from "@repo/shadcn-ui/lib/utils"; import { ProformaCreateAutoAppliedInfo } from "./proforma-create-auto-applied-info"; import { ProformaCreateEmptyLinesCard } from "./proforma-create-empty-lines-card"; @@ -20,7 +19,6 @@ interface ProformaCreateFormProps { proformaSeriesOptions: { value: string; label: string }[]; targetInvoiceSeriesOptions: { value: string; label: string }[]; paymentTermOptions: { value: string; label: string }[]; - className?: string; } export const ProformaCreateForm = ({ @@ -37,31 +35,28 @@ export const ProformaCreateForm = ({ proformaSeriesOptions, targetInvoiceSeriesOptions, paymentTermOptions, - className, }: ProformaCreateFormProps) => { return ( -
- {t("account.description")} -
-+ {t("account.description")} +
-+ {ctrl.isSavingProfile + ? t("account.feedback.savingProfile") + : t("account.feedback.idle")} +
+ +- {ctrl.isSavingProfile - ? t("account.feedback.savingProfile") - : t("account.feedback.idle")} -
++ {t("account.sections.security.passwordDescription")} +
++ {t("account.sections.session.description")} +
+ +- {t("account.sections.security.passwordDescription")} -
-- {t("account.sections.session.description")} -
- -