# Frontend de suppliers: diseño e implementación UI/UX
## 1. Objetivo
El frontend de `suppliers` debe ofrecer listado, detalle, creación y edición con el mismo lenguaje visual y los mismos patrones de navegación que `customers`, respetando el contrato funcional más pequeño de Supplier.
Este documento es la fuente normativa para la implementación. La paridad buscada es de arquitectura y experiencia, no de campos ni capacidades de negocio.
## 2. Estado actual
Antes de esta implementación, Supplier solo disponía de entidades frontend, adapters, APIs y hooks de TanStack Query. La sidebar enlazaba a `/suppliers`, pero no existían manifest, rutas, páginas, formularios ni traducciones del módulo.
El API client tenía una incompatibilidad activa: la actualización delegaba en `IDataSource.updateOne()`, que usa PUT, aunque Supplier solo expone PATCH.
## 3. Customer como referencia
Se adoptan de Customer:
- manifest y rutas lazy por módulo;
- páginas de listado con `RdxPageContainer`, `RdxPageHeader`, búsqueda con debounce y `DataTable`;
Se adopta `edit`, que es la convención vigente de Customer. No se crean rutas DELETE, activate o deactivate.
## 7. Listado
El listado usa header, descripción, acción principal, `SimpleSearchInput`, tabla server-side y paginación. Las columnas son:
- identidad: nombre, nombre comercial, TIN y tipo empresa/persona;
- referencia;
- contacto principal;
- status no interactivo;
- acciones Ver y Editar.
Solo `name`, `reference` y `email_primary` ofrecen sorting, porque pertenecen a la whitelist real. La búsqueda usa el query param `q`, debounce de 300 ms y reinicia la página.
## 8. Detail
El detalle presenta un header con nombre, contexto secundario y badge de status. Se agrupa en Identificación, Contacto, Dirección y Preferencias. Los valores ausentes muestran `-` para mantener una cuadrícula estable. Las únicas acciones son Volver y Editar.
## 9. Create
Create reutiliza el editor común Supplier y genera el UUID en el cliente. El payload conserva el DTO plano del backend y omite campos opcionales vacíos. Tras éxito actualiza caché, muestra feedback y navega al detalle.
## 10. Update
Update carga el detalle, adapta la entidad al formulario y construye el PATCH desde `dirtyFields`. Solo se envían campos modificados con valor utilizable. Un campo vacío se omite porque el contrato vigente no admite `null => borrar`; la UI no inventa esa semántica.
La petición se realiza explícitamente con método PATCH, nunca con `IDataSource.updateOne()`.
## 11. Formularios y validación
Un único `SupplierFormSchema` en camelCase valida create y update. Se reutilizan schemas semánticos de Core para TIN, país, código postal, idioma, moneda, teléfono y web. Las secciones son Identificación, Dirección, Contacto y Preferencias.
`isCompany` es boolean y usa el selector visual empresa/persona. `status` no forma parte del formulario.
## 12. API / React Query
Las keys separan listado y detalle. Create establece el detalle e invalida listados. Update establece el detalle, parchea filas presentes e invalida listados. El cambio de empresa reutiliza el reset global de queries y el interceptor común que añade `X-Company-Id`.
## 13. Estados loading/error/empty
- List usa `SkeletonDataTable` en carga inicial.
- Detail y Update usan skeleton de editor.
- Errores bloqueantes usan `PageErrorState` con reintento y regreso.
- Errores de mutación usan `ErrorAlert` y toast.
- La tabla conserva el empty state común; una búsqueda sin resultados mantiene visible el buscador.
## 14. Responsive
Header y acciones apilan en móvil. Formularios pasan de dos columnas a una. Las tarjetas de detalle usan una columna en móvil y dos en escritorio. La tabla conserva scroll horizontal y paginación del componente compartido.
## 15. Accesibilidad
Todos los inputs tienen labels asociados mediante los componentes Rdx. Los botones incluyen nombre accesible, los iconos decorativos usan `aria-hidden`, las filas de acciones son navegables y los errores se asocian mediante React Hook Form. El foco se mueve al primer campo inválido.
## 16. i18n
Todos los textos visibles pertenecen al namespace `Suppliers`. Se mantienen recursos completos en `es` y `en`; no se insertan textos de interfaz específicos en componentes.