146 lines
21 KiB
Markdown
146 lines
21 KiB
Markdown
|
|
# Implementación UI/UX v3: ficha de puesto de trabajo
|
|||
|
|
|
|||
|
|
Fecha: 24 de octubre de 2026. Ruta: `/companies/:companyId/workstations/:id`.
|
|||
|
|
|
|||
|
|
## Resultado y alcance
|
|||
|
|
|
|||
|
|
M08 conserva las diferencias semánticas entre configuración, pendiente, revisión, ciclo de vida, error y ausencia. Software adopta la misma receta Badge que las configuraciones de perfiles. Las mediciones justifican corregir el contraste de la edición principal, los contadores, los estados técnicos no operativos y el resumen compartido de teletrabajo. M09 aproxima el skeleton a la cabecera, las dos bandas y la columna secundaria existentes, sin modificar las consultas ni imponer alturas al contenido real.
|
|||
|
|
|
|||
|
|
La [consolidación M01–M09](cierre-auditoria-uiux-ficha-puesto-trabajo.md) separa implementación, verificaciones pendientes y deuda ajena. Esta entrega no acredita conformidad WCAG integral ni resuelve el problema de concurrencia del backend detectado durante las pruebas.
|
|||
|
|
|
|||
|
|
## Línea base y preparación
|
|||
|
|
|
|||
|
|
La línea base funcional es [v2.2](implementacion-uiux-ficha-puesto-v2.2.md), con M01/M02 de [v1](implementacion-uiux-ficha-puesto-v1.md) y M03/M04/M06 de [v2.1](implementacion-uiux-ficha-puesto-v2.1.md). Se contrastaron la [auditoría original](auditoria-uiux-ficha-puesto-trabajo.md), M08/M09 y E05/E07/E08/E12, DESIGN.md, los patrones de listados compactos y diálogos, estructura web, WD04.3, matriz de skills y procedimiento Playwright. Se consultaron sus capturas y mediciones; las evidencias históricas se conservan y se comprueban mediante hashes.
|
|||
|
|
|
|||
|
|
Antes de modificar producción se ejecutaron `pwd`, `git status --short`, Node v24.20.0 y PNPM 11.25.0. Registro inicial local: `/tmp/metis-uiux-v3-initial-status.txt`. Había modificaciones previas de las entregas anteriores, listados, búsqueda y Recursos; continuaron apareciendo cambios ajenos durante el trabajo, incluidos locales. No se revierten ni se atribuyen a v3. Se conservaron copias locales del alcance para revisar el delta real.
|
|||
|
|
|
|||
|
|
El preparador documentado creó una instalación desechable con `metis_desk_test`; login real con usuario ordinario y sesión privada. Playwright MCP usa Docker/stdio, imagen fijada y Chromium 155.0.8059.12; comprobada conectividad WSL. No se instalaron dependencias, skills ni navegadores. Se usa el origen anunciado por Vite.
|
|||
|
|
|
|||
|
|
## Skills aplicadas
|
|||
|
|
|
|||
|
|
| Skill | Aplicación efectiva |
|
|||
|
|
| --- | --- |
|
|||
|
|
| **shadcn** | Badge `outline`/`secondary`, Button `secondary`, Skeleton y APIs instaladas de Base UI/Vega. Sin regenerar vendor. El CLI instalado `docs badge skeleton` falló por `EAI_AGAIN`; se contrastaron las fuentes locales y sus exports. |
|
|||
|
|
| **frontend-design** | Mantener composición e identidad; aproximar estructura de carga a responsabilidades y ancho real, con alturas solo de placeholders. |
|
|||
|
|
| **ux-error-recovery** | Distinguir carga, cero, incertidumbre y error; conservar datos durante refetch y reintentos independientes. |
|
|||
|
|
| **ux-microcopy** | Conservar textos precisos es/en; pendiente y revisión siguen siendo conceptos distintos, sin nuevas etiquetas de salud. |
|
|||
|
|
| ux-dashboard | Mantener la prioridad de pendientes sin convertirlo en notificación; conservar jerarquía de paneles. |
|
|||
|
|
| ux-empty-states | Verificar que ausencia y error siguen separados en M07. |
|
|||
|
|
| ui-ux-pro-max | Búsqueda local dirigida `text contrast dark mode`, dominio UX: resultados Contrast Readability y Color Contrast; aplicados como apoyo a mediciones efectivas, sin otra paleta. |
|
|||
|
|
| vercel-react-best-practices | No sincronizar estado derivado ni bloquear consultas independientes; CSS para adaptación y movimiento reducido. |
|
|||
|
|
| vercel-composition-patterns | Prop opcional de variante en el control existente; marcador privado, pequeño y presentacional del skeleton, sin nueva capa genérica. |
|
|||
|
|
| ux-design-review | Consolidación de uso, textos, estados, teclado y aplicación del sistema visual. No se ejecutan auditores ausentes. La referencia interna `docs/orchestration-policy.md` de esa skill no está disponible. |
|
|||
|
|
| rdx-solid | Solución local, contratos existentes, prueba de los estados documentales y revisión de consumidores. |
|
|||
|
|
|
|||
|
|
No están instalados los auditores especializados de heurísticas, microcopy, accesibilidad, estética, IA, dark patterns o responsive. No se simulan ni instalan. El sistema existente conserva tipografía, tokens y composición.
|
|||
|
|
|
|||
|
|
## M08: diagnóstico y matriz semántica
|
|||
|
|
|
|||
|
|
[Matriz detallada de representación y contraste](auditorias/ficha-puesto-trabajo/implementacion-v3/comparaciones/estados-y-contraste.md).
|
|||
|
|
|
|||
|
|
| Categoría | Código y significado real | Representación y decisión |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| Configurado | `configured`, documentación de configuración; no demuestra acceso efectivo | Badge `outline` en familias y ahora en Software. |
|
|||
|
|
| Pendiente | `pending`, configuración pendiente | Badge `secondary`, texto «Pendiente de configurar». Conserva Solo pendientes. |
|
|||
|
|
| Retirada pendiente | `removal_pending`, retirada documentada por completar | Badge `secondary` y texto propio; no se fusiona con pendiente de configurar. |
|
|||
|
|
| Revisión requerida | `review` derivado de referencias/cobertura; puede coexistir con configurado | Se conserva el aviso «Requiere revisión» en ámbar: contraste suficiente y significado diferente del estado de configuración. |
|
|||
|
|
| Total de pendientes | Recuento documental de los estados actuales | Número ámbar cuando positivo, con título y acción existentes; cero confirmado neutral. No es notificación de mensajes. |
|
|||
|
|
| Desconocido | No se puede confirmar un total o cobertura | Texto explícito neutral; nunca convertirlo en cero ni en error de negocio. |
|
|||
|
|
| Activo/inactivo | Estado de ciclo de vida documentado | EntityStatus conserva etiqueta y punto decorativo. No significa conectado en tiempo real. |
|
|||
|
|
| Archivado | Perfil histórico que puede mostrarse con el control existente | Etiqueta y ámbito activo/archivado conservados; no equivale a eliminado. |
|
|||
|
|
| Error de consulta | Fallo de una fuente | Alert/error específico, reintento y conservación de datos previos cuando existen. No es un pendiente. |
|
|||
|
|
| Sin registros | Consulta completada sin filas | Mensaje específico de colección vacía; no equivale a fuente pendiente o fallida. |
|
|||
|
|
|
|||
|
|
Se mantienen las distinciones documentales: cobertura/autorización registrada no acredita permisos SMB efectivos; aplicaciones asignadas a perfiles no equivalen a instalaciones; soporte disponible no comprueba conectividad real.
|
|||
|
|
|
|||
|
|
### Cambios justificados
|
|||
|
|
|
|||
|
|
1. **Software:** EntityStatus binario utilizaba `active=false` para estados como pendiente de configurar o retirada pendiente. Se sustituye por la misma receta Badge de las familias, conservando cada etiqueta, filtro y acción. EntityStatus continúa en ciclo de vida, donde sí encaja su contrato.
|
|||
|
|
2. **Edición principal:** contraste inicial 3,70:1 en oscuro y 3,83:1 en hover claro para texto de 14 px. La ficha solicita `editVariant="secondary"` al WorkstationActions existente: 12,33:1 claro y 15,58:1 oscuro en reposo. Es un control relleno de la paleta existente; conserva etiqueta, prominencia, ámbito y foco. Los demás consumidores mantienen `default`.
|
|||
|
|
3. **Contadores:** el texto atenuado sobre fondo muted de Equipamiento/Perfiles mide 4,396877984572111:1 en claro. Se corrige localmente su texto con `foreground`, conservando fondo, cifras, ámbito y disponibilidad. No cambia DetailPanel ni su receta global. La muestra anterior está en [contraste-contadores-antes.json](auditorias/ficha-puesto-trabajo/implementacion-v3/comparaciones/contraste-contadores-antes.json): se tomó con el contador de M06 aún intacto, durante la primera pasada v3, antes de su corrección específica.
|
|||
|
|
4. **Estados técnicos de Equipamiento:** operativo conserva `outline`. Averiado, mantenimiento y retirado pasaban a `destructive` y daban 1,6490871246180994:1 en oscuro. Adoptan `secondary` localmente: 15,58:1 oscuro y 12,33:1 claro, sin cambios en las etiquetas, la asignación o las restricciones. No se añade una severidad que el modelo no proporciona.
|
|||
|
|
5. **Teletrabajo:** «Autorizada» medía 3,2726754151865913:1 en oscuro por su verde fijo. `TeleworkAuthorizationSummary` usa ahora `foreground` para estado y aviso de revisión, conservando vigencia, fechas y notas. La etiqueta alcanza 18,92:1 claro y 17,11:1 oscuro. Se comprueban los tres consumidores: ficha, entorno de perfil y listado de teletrabajo, en ambos temas y con/sin revisión.
|
|||
|
|
6. **Conservaciones:** pendientes y revisión en ámbar ya alcanzan su umbral. No se uniforman todos los indicadores ni se añaden tokens globales o señales de severidad.
|
|||
|
|
|
|||
|
|
### Método de contraste
|
|||
|
|
|
|||
|
|
Se obtienen colores computados en navegador para texto, fondos, opacidad y bordes. Canvas convierte los colores CSS, incluidos OKLCH, a sRGB; se componen fondos transparentes hasta la superficie efectiva y la opacidad de controles. Se calcula luminancia relativa y `(Lclaro + 0,05)/(Loscuro + 0,05)`. Las decisiones usan valores sin redondear; las tablas redondean solo para lectura.
|
|||
|
|
|
|||
|
|
Referencias: [WCAG 2.2, contraste de texto](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) y [contraste no textual](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html). Se aplica 4,5:1 a texto normal y 3:1 a texto grande según tamaño/peso efectivos. Los controles disabled se registran y se distinguen de los umbrales de elementos activos. Los puntos de EntityStatus llevan `aria-hidden` y tienen una etiqueta textual redundante: no se afirma que el verde decorativo por sí solo cumpla 3:1. Tampoco se evalúa un borde decorativo como información esencial.
|
|||
|
|
|
|||
|
|
Se inspeccionan reposo, hover y foco de acciones representativas, estados con revisión/retirada pendiente simulados en la frontera HTTP, ausencia, error y desconocido. No es una auditoría exhaustiva de cada nodo descriptivo, borde, anillo y estado de todos los diálogos de la aplicación; las muestras identifican exactamente el texto/control medido.
|
|||
|
|
|
|||
|
|
## M09: diagnóstico, medición y decisión
|
|||
|
|
|
|||
|
|
La cuadrícula inicial de seis paneles uniformes no anticipaba ni la cabecera móvil ni las dos bandas 900/1000 px y la pila lateral. En la observación inicial a 390/320 px, el primer marcador de panel empezaba en Y=243 frente a Y=391 del panel real: diferencia estática de 148 px. Se observaron también eventos `layout-shift` durante las respuestas de fuentes; no se atribuyen todos al skeleton.
|
|||
|
|
|
|||
|
|
**Decisión:** refinar la estructura del skeleton. Se incorporan marcadores de título, acciones y metadatos; banda Equipamiento/Pendientes desde 900 px de contenedor, pendientes de 256 px alineado al extremo; banda Perfiles/columna apilada desde 1000 px. Se mantienen seis paneles ligeros y alturas orientativas solo durante carga. Ninguna tarjeta real recibe alturas fijas. No se reproducen todos sus datos ni se añaden animaciones de entrada.
|
|||
|
|
|
|||
|
|
La ficha desactiva el pulse de sus Skeleton cuando `prefers-reduced-motion: reduce`. Se comprobó el valor computado `animation-name: none` en los 24 marcadores iniciales. La información real sigue apareciendo al resolverse su fuente; no hay temporizadores para prolongar la carga ni una consulta bloqueante nueva.
|
|||
|
|
|
|||
|
|
[Mediciones y comparación de carga](auditorias/ficha-puesto-trabajo/implementacion-v3/comparaciones/carga.md). Incluyen inventario, perfiles, software y soporte retenidos por separado a 1440/390/320, geometría inicial/final y eventos PerformanceObserver.
|
|||
|
|
|
|||
|
|
### Condiciones comparables y límites de estabilidad
|
|||
|
|
|
|||
|
|
Las primeras medidas `carga-*` fueron exploratorias, sin limitar concurrencia. La API llegó a producir `SequelizeConnectionAcquireTimeoutError` en lecturas anidadas de Recursos; no es una regresión del skeleton y no se corrige desde el frontend. Para obtener muestras reproducibles se limita a dos el número de peticiones API simultáneas del **navegador de pruebas**, sin retardos temporales artificiales y sin modificar queries o servidor.
|
|||
|
|
|
|||
|
|
Se repitieron ambos skeletons bajo esa misma condición. Los registros **`control-carga-*`** comparan exclusivamente el skeleton anterior y el nuevo con el resto de M08 constante durante esa muestra, mismas fixtures y mismo origen. Las correcciones finales de color de contadores y teletrabajo se hicieron después y no alteran la geometría de esa serie. Para la medida anterior se sustituyó temporalmente solo el fichero de skeleton propio, con copia, comprobación de cambios concurrentes y restauración en `finally`. Las capturas iniciales completas de v2.2 permanecen separadas. No se mezclan las dos series para calcular mejoras.
|
|||
|
|
|
|||
|
|
PerformanceObserver registra valor, momento, `hadRecentInput` y rectángulos de fuentes. Se separan eventos anteriores a liberar la respuesta y eventos posteriores sin entrada reciente. El resumen utiliza ventanas de sesión de hasta cinco segundos, con menos de un segundo entre eventos, conforme a [la definición de CLS](https://web.dev/articles/cls). Son muestras de laboratorio de transiciones controladas, no un CLS de producción, percentil de usuarios ni benchmark repetido. No se promete una reducción de CLS a partir de la geometría o de un único recorrido.
|
|||
|
|
|
|||
|
|
La incidencia de concurrencia sin control de red queda abierta como deuda de infraestructura/Recursos ajena. Pasar los recorridos con concurrencia de prueba limitada no demuestra que esa incidencia esté resuelta en condiciones normales.
|
|||
|
|
|
|||
|
|
## Accesibilidad y tema oscuro
|
|||
|
|
|
|||
|
|
Se verifican los tokens oscuros efectivos aplicando `.dark` en la sesión de prueba. No se añade un selector de tema al producto. Tarjetas, textos y variantes se inspeccionan en claro/oscuro a 1440 y 390 px. El shell conserva sus superficies propias; no se confunde soporte de tokens CSS con una nueva preferencia de usuario implementada.
|
|||
|
|
|
|||
|
|
El atajo de zoom nativo no cambia `innerWidth` ni DPR. Un segundo intento mediante `chrome://settings/appearance` fue rechazado por Playwright: esos ajustes no están disponibles en su contexto aislado. No se modifica la configuración global ni se reemplaza por escalado CSS o emulación de DPR. **Zoom nativo 200/400 % no ejecutado.** Las pruebas responsive y las emulaciones históricas de reflow tienen su propia evidencia y no lo sustituyen.
|
|||
|
|
|
|||
|
|
No se encontraron Orca, speech-dispatcher, espeak-ng ni una integración NVDA; tampoco axe/pa11y instalados. **No se ejecutó un lector de pantalla real.** Se inspeccionó el árbol accesible nativo de Chromium mediante CDP, además de nombres, regiones, encabezados, tablas, estados expandido/contraído, teclado y foco. El árbol incluye encabezado de compañía fuera de main y un h1 de puesto dentro de main; la inspección ARIA/CDP no equivale a una prueba con tecnología de asistencia.
|
|||
|
|
|
|||
|
|
[Resultados de accesibilidad](auditorias/ficha-puesto-trabajo/implementacion-v3/comparaciones/accesibilidad.md).
|
|||
|
|
|
|||
|
|
## Regresión acumulada y evidencias
|
|||
|
|
|
|||
|
|
Las capturas de siete resoluciones cubren 1600×1000, 1440×900, 1280×900, 1024×768, 768×1024, 390×844 y 320×720. Se comprueban además 599/600/601 y 839/840/841 px de Card de Perfiles, y 899/900/901 y 999/1000/1001 px del contenedor de bandas. El ancho medido, no el viewport, determina cada distribución.
|
|||
|
|
|
|||
|
|
Fixtures reproducibles: 15 compañías; principal con 59 personas, 137 activos, 73 recursos, 57 puestos y 64 perfiles; puesto denso con 80 miembros y 50 perfiles activos más 10 archivados. Relaciones coherentes, nombres/cuentas/rutas extensas y otras compañías para comprobar aislamiento. Los cambios de formularios se restauran; las revisiones adicionales son historial sintético de la prueba.
|
|||
|
|
|
|||
|
|
Los recorridos y sus resultados finales se recogen en `mediciones.json`: edición/cancelación/historial/software; completar Equipamiento y restaurar foco; cero frente a desconocido/error; carga/refetch/reintentos; las seis regresiones v2.1 y cinco de v1. El runner reutiliza métodos con el destino v3 y adapta el selector accesible de Equipamiento en memoria; no escribe en las evidencias históricas.
|
|||
|
|
|
|||
|
|
Las tandas finales completan los seis recorridos de v2.1 y los cinco de v1, además de los seis métodos funcionales de v2.2. Las repeticiones aisladas completan los casos de carga a 320 px y recuperación de soporte que agotaron una espera en tandas largas. No se afirma una única ejecución conjunta sin fallos.
|
|||
|
|
|
|||
|
|
Los primeros intentos fallidos se distinguen de defectos de producto: simulación de carpetas ajustada al contrato `mappings`, selección de elementos HTML en la instrumentación de contraste para excluir SVG, selección inequívoca del párrafo de autorización frente a la columna con la misma etiqueta, pool agotado y un error de resolución Vite tras cambios concurrentes de búsqueda. Se reiniciaron solo API/Vite propios conservando base y configuración privada en memoria. No se instaló ni modificó el paquete interno de búsqueda.
|
|||
|
|
|
|||
|
|
## Validación técnica y consumidores
|
|||
|
|
|
|||
|
|
| Comando/comprobación | Resultado observado |
|
|||
|
|
| --- | --- |
|
|||
|
|
| Tipos dirigidos de Assets, Companies y Web | Correctos. Incluye consumidores de `WorkstationActions.editVariant`. |
|
|||
|
|
| Biome y ESLint dirigidos al delta propio | Correctos; comprobación final registrada al cierre. |
|
|||
|
|
| Prueba directa de `workstation-detail.test.tsx` | 26/26, incluidos casos es/en de los tres estados de Software y los cuatro estados técnicos con asignación y principal conservados. |
|
|||
|
|
| Pruebas directas de teletrabajo y entorno | 5/5 y 7/7; total de las tres suites dirigidas: 38 casos. |
|
|||
|
|
| Assets completo | Correcto; el runner informa 27 archivos. |
|
|||
|
|
| `pnpm build` | Correcto, dos tareas; aviso existente de tamaño de chunk. |
|
|||
|
|
| `pnpm typecheck` global | Falla en vendor `calendar.tsx:165`, TS2375 por `locale` opcional. Verificado de nuevo. |
|
|||
|
|
| `pnpm lint` global | 15 errores, 1 warning y 5 infos en la ejecución global registrada. |
|
|||
|
|
| `pnpm check` global | 206 errores, 2 warnings y 7 infos en la última ejecución, tras nuevos cambios concurrentes; el alcance propio se comprueba aparte. |
|
|||
|
|
| `pnpm test` global | Falla en Resources, `src/api/application/resource-scope.test.ts`; cinco tareas correctas de seis ejecutadas. No completa Assets/Companies en esa tanda. |
|
|||
|
|
| Prueba directa de `companies-page.test.tsx` | 10/12; siguen fallando los casos de líneas 180 y 210, ajenos a la ficha. |
|
|||
|
|
|
|||
|
|
No se trasladan los resultados históricos de v2.2 como si fueran actuales. Se separan las comprobaciones dirigidas y los fallos globales observados en este árbol concurrente. No se cambian vendor, contratos HTTP, DTO, migraciones, persistencia ni permisos.
|
|||
|
|
|
|||
|
|
Fuentes propias: ocho ficheros de código/pruebas, con `workstation-dashboard-skeleton`, `workstation-assets`, `workstation-software`, `workstation-detail-page`, `WorkstationActions`, `TeleworkAuthorizationSummary` y sus dos suites modificadas. Los consumidores de WorkstationActions en listado e inventario conservan la variante por defecto. `DetailPanel`, Badge, Skeleton y FormDialog conservan implementación y contratos; el ajuste compartido de TeleworkAuthorizationSummary queda limitado a sus colores y se comprueban sus tres consumidores; se documenta el uso local.
|
|||
|
|
|
|||
|
|
Comandos ejecutados: `pnpm --filter @metis/assets --filter @metis/companies --filter @metis/web typecheck`, `pnpm --filter @metis/assets test`, `pnpm build`, `pnpm typecheck`, `pnpm lint`, `pnpm test` y `pnpm check`. Biome y ESLint se ejecutaron con los ocho ficheros propios explícitos. Las suites de componentes se ejecutaron directamente con `TSX_TSCONFIG_PATH=../../tsconfig.json node --import tsx --test <fichero>` desde Companies; no se presenta el paquete completo de Companies como correcto. Los JSON de evidencias se comprueban con el límite de tamaño explícito `--files-max-size=16777216`; el check global conserva su límite por defecto y avisa del tamaño de mediciones.
|
|||
|
|
|
|||
|
|
## Reproducción y cierre
|
|||
|
|
|
|||
|
|
Procedimiento de preparación: `scripts/setup-playwright-wsl.sh`, `scripts/visual-audit.py`, `visual-audit-volume.py` y `workstation-dashboard-fixtures.py`. Mantener el preparador abierto y pasar su sesión privada solo mediante `METIS_PLAYWRIGHT_STORAGE_STATE`. El runner `scripts/workstation-uiux-v3.test.py` guarda exclusivamente en `implementacion-v3`; usar `METIS_UIUX_PHASE=antes` para preparar/capturar antes de modificar y `despues` para la versión final. `METIS_UIUX_LOAD_LABEL=control-carga` distingue la comparación controlada del ensayo exploratorio. Cambiar la variable de fase no cambia por sí solo el código.
|
|||
|
|
|
|||
|
|
El preparador propio y los supervisores sustitutos de API/Vite se cerraron por sus PID exactos. Se verificó que los cinco procesos registrados terminaron, que el contenedor propio desapareció y que `session.json`/`database.env` ya no existen. El cierre está registrado en mediciones; las capturas se conservan sin credenciales. No se realizan limpiezas globales ni se detienen procesos por nombres genéricos.
|
|||
|
|
|
|||
|
|
Riesgos residuales: zoom nativo y lector real pendientes; otras combinaciones de navegador/dispositivo sin probar; contraste global fuera del alcance sin certificación; fallo de concurrencia de Recursos y checks globales ajenos. No se presenta la ficha como una comprobación operativa o de permisos efectivos. La estabilización visual de M01–M09 se separa del cierre integral de accesibilidad e infraestructura.
|
|||
|
|
|
|||
|
|
La transición instrumentada utiliza el puesto principal con dos perfiles y dos activos. Los estados vacíos y de volumen se comprueban funcional y visualmente, sin un barrido de CLS para cada combinación de datos.
|