# Implementación UI/UX v1 de la ficha de puesto Fecha: 24 de octubre de 2026. Alcance implementado: M01 y M02 de [la auditoría](auditoria-uiux-ficha-puesto-trabajo.md). Ruta: `/companies/:companyId/workstations/:id`. M03–M09 siguen fuera de alcance. ## 1. Resultado La cabecera estrecha utiliza un retorno directo al listado, conserva el nombre completo y compacta las separaciones. Soporte presenta métodos documentados en una lista compacta y ofrece una única acción **Gestionar soporte**. La gestión conserva las operaciones anteriores dentro de un diálogo estable del módulo de activos. No cambian el shell, las proporciones del dashboard, la paleta, la tipografía, vendor, dependencias, API, modelos ni persistencia. Los cambios preexistentes del árbol se conservan y no se atribuyen a esta entrega. ## 2. Estado inicial y contraste con la documentación Se consultaron DESIGN.md, ambos patrones de listados, diálogos, estructura web, procedimiento Playwright, auditoría y las secciones vigentes WD04.1–WD04.3 del documento de implementación. El código ya contiene equipamiento unificado, perfiles/configuraciones integrados y contexto organizativo del responsable en Popover. No se recuperan las tarjetas ni los selectores retirados. La ficha actual utiliza el primario rojo. Las descripciones históricas de otra etapa azul no prevalecen sobre los tokens y consumidores vigentes. Las dimensiones iniciales se volvieron a medir; no se reutilizan los resultados históricos como prueba de esta entrega. Preflight: `/home/david/dev/metis-desk`, Node v24.20.0 y PNPM 11.25.0, compatibles con `package.json`. Se registró el estado inicial en un archivo local de `/tmp` antes de modificar producción. Había cambios ajenos en documentación, búsqueda, controllers, listados, tests y scripts de auditoría; no se revierten. ## 3. Skills aplicadas Se consultaron las skills instaladas y las referencias pertinentes; no se instalaron ni actualizaron skills. | Skill | Decisión efectiva | | --- | --- | | ux-dashboard | Priorizar lectura de método/destino frente a controles de administración; mantener ordenador y persona como ámbitos distintos. | | frontend-design | Conservar recetas/tokens y densidad; compactar el espacio de cabecera solo bajo capacidad estrecha. Revisar capturas antes/después. | | shadcn | Componer mediante APIs Base UI existentes y wrappers rdx-ui; usar Badge, Button, FormDialog/FormBody y el mecanismo finalFocus. | | ux-navigation | Retorno móvil con BrowserLink y destino real; mantener breadcrumb completo en escritorio y entrada directa por URL. | | ux-tables | CompactList/CompactListItem con metadatos, estado textual y ausencia «—»; sin herramientas de inventario en la tarjeta. | | vercel-composition-patterns | Componentes separados para resumen, elemento y diálogo; reutilizar la gestión anterior sin añadir variantes booleanas a AssetSupport. | | ux-microcopy | «Gestionar soporte»/«Manage support», avisos específicos de actualización, acceso y referencia no resuelta; paridad es/en. | | vercel-react-best-practices | Reutilizar query key/API; derivar selección y orden durante render, sin copiar la caché a estado ni introducir efectos. | | ux-design-review | Consolidar revisión de jerarquía, densidad, navegación, estados y foco al cierre; sus auditores especializados siguen ausentes y no se simulan. | El CLI local shadcn 4.21.1 se ejecutó, pero `docs dialog badge` falló con `EAI_AGAIN` al resolver `ui.shadcn.com`. Se comprobaron las APIs instaladas de Breadcrumb, Button, Badge y FormDialog/Dialog, junto con la referencia local Base frente a Radix. No se descargó otra versión ni se regeneró vendor. ## 4. M01: orientación y cabecera [WorkstationDetailPage](../modules/companies/src/web/workstations/detail/ui/workstation-detail-page.tsx) conserva el breadcrumb completo desde **640 px de su contenedor**. Por debajo ofrece «Volver a puestos de trabajo» mediante BrowserLink, `navigation="return"` y el destino existente de la compañía. El breadcrumb largo queda fuera del árbol accesible al ocultarse por CSS; no hay dos navegaciones visibles simultáneas. Se reducen localmente los gaps y el padding vertical de la cabecera estrecha. No cambia el tamaño tipográfico del h1, ni se trunca su contenido. Se conservan nombre editable, compañía, sede, responsable, estado, edición, historial, ciclo de vida y Popover organizativo. Las recetas de escritorio recuperan los mismos gaps/padding anteriores. No fue necesario modificar WorkstationNameEditor ni WorkstationActions. No se reordenan visualmente elementos respecto al DOM ni se añaden breakpoints globales. ## 5. M02: soporte como resumen operativo Assets incorpora **AssetSupportOverview**, que usa `getSupportConnections` y `supportKeys.asset(companyId, assetId)` existentes. Ordena el método preferido primero, preservando el orden restante; filtra métodos de otros ámbitos y retirados. Los retirados continúan accesibles desde gestión y se indica su existencia cuando corresponde. **SupportConnectionOverview** presenta herramienta, destino, estado documental, VPN y preferencia mediante CompactListItem y Badge. Las notas y las advertencias de activo retirado/herramienta inactiva permanecen disponibles. Una herramienta no resuelta muestra «—» y una explicación; no sustituye el nombre por un UUID. **AssetSupportManagementDialog** vive en el módulo propietario. Usa FormDialog de tamaño medio, `layout="stable"`, icono/título, FormBody desplazable y Cerrar en pie fijo. Monta el AssetSupport existente, que conserva alta, edición, eliminación confirmada, historial y visualización de retirados. El cierre devuelve foco al botón Gestionar soporte. Las altas/ediciones se mantienen en sus diálogos independientes y no se copian formularios ni mutaciones. WorkstationSupport sustituye únicamente la sección de gestión embebida por el nuevo resumen. **RemoteSummary y TeleworkAuthorizationSummary conservan su implementación y sus datos**: persona del perfil seleccionado, extremos, método remoto, estado, VPN, autorización, fechas, notas y accesos de gestión. La advertencia de disponibilidad registrada sin comprobación en tiempo real sigue visible. No se añade ninguna acción Conectar. ## 6. Estados y restricciones El resumen reutiliza EntityListStatus/entityListState y Skeleton: - Carga inicial: mensaje y skeleton, gestión deshabilitada. - Respuesta vacía: mensaje de ausencia confirmada y gestión disponible. - Actualización fallida: conserva datos anteriores y explica su antigüedad; reintento dirigido y destino estable de foco. - Error inicial: mensaje recuperable sin confundirlo con un listado vacío. - 401/403 comunicados como UNAUTHENTICATED/FORBIDDEN: no presenta la caché como datos autorizados y deshabilita la gestión. - Herramienta no resuelta: mantiene el método y el destino, informa de la referencia incompleta. - Sin ordenador principal: conserva la explicación existente; no monta el resumen ni su consulta. - Activo retirado: mantiene el mismo `retired` que recibía AssetSupport y sus restricciones de alta/edición existentes. El servidor continúa aplicando autenticación/autorización. Las pruebas de 403 del nuevo resumen simulan la denegación en la frontera HTTP; no se atribuye al sistema un rol nuevo ni se modifica la política de acceso. ## 7. Archivos y contratos | Archivo principal | Cambio | | --- | --- | | [workstation-detail-page.tsx](../modules/companies/src/web/workstations/detail/ui/workstation-detail-page.tsx) | Retorno y densidad responsive locales. | | [workstation-support.tsx](../modules/companies/src/web/workstations/detail/ui/workstation-support.tsx) | Consume el nuevo resumen de Assets. | | [asset-support-overview.tsx](../modules/assets/src/web/support-connections/list/ui/asset-support-overview.tsx) | Query, disponibilidad, resumen y apertura de gestión. | | [support-connection-overview.tsx](../modules/assets/src/web/support-connections/detail/ui/support-connection-overview.tsx) | Elemento documental compacto. | | [asset-support-management-dialog.tsx](../modules/assets/src/web/support-connections/list/ui/asset-support-management-dialog.tsx) | Superficie independiente de gestión. | | [Assets web index](../modules/assets/src/web/index.ts) | Exportación pública aditiva de AssetSupportOverview para Companies. | | [support.test.tsx](../modules/assets/src/web/support-connections/shared/support.test.tsx) | Resumen es/en, referencia ausente, retirados, orden preferido y conservación de gestión original. | | [runner MCP](../scripts/workstation-uiux-v1.test.py) | Capturas comparables y recorridos de soporte/cabecera. | | Assets `common/locales/es.json` y `en.json` | Cinco claves nuevas de soporte en ambos idiomas. | El contrato de AssetSupport no cambia. Sus consumidores de ficha completa/lateral de activos y entorno de perfil conservan sus composiciones. No se modifica rdx-ui ni se le añaden DTOs, queries o endpoints. La exportación nueva y su uso se documentan también en [componentes de interfaz](componentes-de-interfaz.md). ## 8. Decisiones y alternativas descartadas Se conserva el contexto de compañía visible en móvil; no se depende exclusivamente de la franja del shell para identificarlo. La reducción procede del retorno breve y el espaciado, no de eliminar información o reducir el h1. Se elige un componente de consulta y otro diálogo frente a añadir flags a AssetSupport o copiar sus operaciones. El diálogo de gestión mantiene altura estable aunque se muestren retirados. Las confirmaciones de borrado siguen interrumpiendo la operación antes de ejecutarla. No se pliega la VPN, el estado ni las advertencias documentales para reducir altura. Tampoco se igualan alturas con Personas y perfiles, se alteran las proporciones del grid o se rediseña el contexto remoto. Estas decisiones evitan ampliar M02 hacia M03–M09. ## 9. Capturas y mediciones comparables Evidencias nuevas en [implementacion-v1](auditorias/ficha-puesto-trabajo/implementacion-v1/comparaciones/comparacion.md), con `antes/`, `despues/`, `comparaciones/` y [mediciones.json](auditorias/ficha-puesto-trabajo/implementacion-v1/mediciones.json). Las evidencias originales de la auditoría no se sobrescriben. La línea base se capturó antes de modificar producción. Se repitió tras esperar perfil, método de soporte, autorización, fuente tipográfica y render. La fixture principal tiene nombre largo, dos activos, dos perfiles activos, un método preferido y una conexión remota de la persona. Se añadieron vistas del puesto sin principal y del nuevo diálogo en tamaños estrechos. | Viewport | Alto cabecera antes → después | Inicio Equipamiento antes → después | Alto Soporte antes → después | | --- | --- | --- | --- | | 1600×1000 | 84 → 84 px | 240 → 240 px | 778 → 642 px | | 1440×900 | 84 → 84 px | 240 → 240 px | 798 → 642 px | | 1024×768 | 84 → 84 px | 290 → 290 px | 702 → 566 px | | 768×1024 | 140 → 140 px | 346 → 346 px | 702 → 566 px | | 390×844 | 244 → 220 px | 437 → 391 px | 862 → 706 px | | 320×720 | 244 → 220 px | 457 → 391 px | 998 → 886 px | En escritorio la cabecera conserva sus medidas. A 390/320 px Equipamiento comienza 46/66 px antes, respectivamente. El panel a 1440 reduce cuatro controles de gestión visibles a uno. No se impone una reducción porcentual ni se afirma una ganancia de productividad. Heurísticamente, herramienta/destino/estado se localizan en una fila agrupada, sin recorrer primero controles de alta/retirados y acciones por registro. ## 10. Preparación reproducible y aislamiento Se usaron los scripts existentes de Playwright MCP con la imagen Docker fijada y Chromium 155.0.8059.12. El preparador creó su propia MariaDB `metis_desk_test`, API/Vite en puertos libres y sesión ordinaria real; sin `.env`, bases reales ni credenciales copiadas a docs. Origen anunciado y APP_ORIGIN: `http://localhost:48235`. Preparación ejecutada: ```bash bash scripts/setup-playwright-wsl.sh python3 scripts/visual-audit.py # Utilizar la ruta privada anunciada por el preparador, sin copiar su contenido. METIS_PLAYWRIGHT_STORAGE_STATE= PYTHONDONTWRITEBYTECODE=1 python3 scripts/visual-audit-volume.py METIS_PLAYWRIGHT_STORAGE_STATE= PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-dashboard-fixtures.py METIS_PLAYWRIGHT_STORAGE_STATE= METIS_UIUX_PHASE=antes PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-uiux-v1.test.py WorkstationUiuxV1Tests.test_01_comparable_captures # Tras implementar, con la misma instalación y datos: METIS_PLAYWRIGHT_STORAGE_STATE= METIS_UIUX_PHASE=despues PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-uiux-v1.test.py ``` Las capturas comparables se obtuvieron antes de los recorridos que guardan cambios. Estos últimos crean/eliminan un método temporal o restauran los valores de puesto. Los cambios en su historial no se usan para comparar las capturas iniciales/finales. La preparación de volumen produjo 15 compañías y, en la principal, 59 personas, 135 activos, 73 recursos y 64 perfiles. El escenario denso conserva 80 miembros y 60 perfiles (50 activos y diez archivados). Después de cerrar las capturas comparables se ampliaron los puestos de cinco a **55**, mediante HTTP real sobre la misma base desechable; no se mezclan capturas con ambos volúmenes en la comparación. Las pruebas unitarias siguen pequeñas. No se considera este volumen un benchmark de rendimiento. El PID exacto **142688** del preparador se registró antes de `exec`; solo se señaliza ese PID al finalizar. No se seleccionan procesos por nombre ni se hacen limpiezas globales. Los clientes MCP y subprocesos se cierran mediante sus contextos propietarios. ## 11. Recorridos funcionales El runner nuevo comprueba capturas/sin principal, Enter/Escape y cancelación anidada, foco de retorno, alta y edición real de método temporal, varias conexiones, historial, retirados y borrado con cancelación y confirmación. Comprueba 503/403 iniciales, reintento, referencia de herramienta incompleta, carga retenida, caché obsoleta y vacío confirmado. La gestión se abre y cierra en 1440/390/320 px, sin overflow interior del diálogo. Se ejecutaron además seis recorridos de regresión existentes, en una tanda de cinco y otra dirigida: - Historial, edición/cancelación, software, enlace al principal y acceso a pendientes con foco/filtro. - Guardado de edición y renombrado con Enter; restauración del nombre original. - Ampliación de Equipamiento conservada durante refetch. - Expansión integrada única de perfiles/configuraciones. - Enlaces de compañía, sede, responsable y ficha de persona del Popover. - Teclado/foco visible, muestra de contraste y expansión a 50 perfiles activos, 60 con archivados y los 80 miembros de Equipamiento. El nuevo recorrido de cabecera prueba retorno móvil mediante enlace/Enter y apertura/cancelación de Desactivar y Eliminar definitivamente. No se elimina ni desactiva el puesto principal de comparación. La muestra de 27 textos/acciones/enlaces dio un mínimo de **4,53:1** en tema claro. No certifica todos los pares/estados. Se abrieron también la ficha del activo y el entorno del perfil: ambos conservan Añadir método y carecen del nuevo resumen de gestión, como corresponde a sus consumidores anteriores. Véanse los resultados sanitizados en [regresiones.json](auditorias/ficha-puesto-trabajo/implementacion-v1/regresiones.json). Los resultados finales por tanda y sus limitaciones se registran en el cierre de este documento; no se atribuye una única ejecución conjunta a tandas separadas. ## 12. Validación técnica | Comando | Resultado observado | | --- | --- | | Typecheck inicial de Assets y Companies | Correctos antes de modificar producción. | | Typecheck dirigido de Assets, Companies y Web tras implementar | Correctos. | | Biome y ESLint dirigidos a los archivos propios afectados | Correctos; repetición final registrada al cierre. | | `pnpm build` | Correcto, dos tareas. Persiste aviso de chunks grandes. | | `pnpm typecheck` | Falla en vendor `calendar.tsx:165`, incompatibilidad de `locale` con exactOptionalPropertyTypes. No se modifica vendor. | | `pnpm lint` | 15 errores fuera del cambio en código de fotos/procesos/persistencia y otros archivos ajenos. | | `pnpm check` | 167 errores fuera del alcance. Los archivos propios se validan de forma dirigida. | | `pnpm test` | Assets pasa 27 archivos; Companies pasa 45 de 46, falla `companies-page.test.tsx`. Siete paquetes completan; fallo global de Companies. | Los fallos globales coinciden con los registrados en documentación previa y no se corrigen dentro de M01/M02. Los comandos anteriores se ejecutaron en esta entrega; no se presentan los resultados históricos como una ejecución actual. La suite nueva de soporte y los tests del dashboard figuran entre los archivos correctos. ## 13. Problemas encontrados y revisión correctiva El primer recorrido posterior buscaba el destino por texto exacto. El resumen ahora añade una etiqueta sr-only, por lo que el selector se ajustó a texto contenido; el recorrido completo se repitió correctamente. Fue un problema del selector, no de la aplicación. La primera simulación de carga retenía una promesa del handler y provocó `Route is already handled` al liberarla. Se sustituyó por el mecanismo de retención de Route utilizado por la suite existente. Se repite el escenario de carga, actualización fallida y vacío; no se silencian sus errores iniciales. El typecheck final detectó una ruta relativa con un nivel de más en el import de tipo del test ampliado. Se corrigió en origen y se repitieron TypeScript y los checks dirigidos; no se introdujeron casts ni supresiones para ocultarlo. Se inspeccionaron capturas de cabecera móvil, escritorio, tarjeta de soporte y gestión estrecha. La composición final mantiene métodos y estados agrupados; la ventana de gestión permite reflujo de controles y conserva el pie visible. No se detectó una necesidad de cambiar paleta, tamaños de texto o proporciones. La revisión usa ux-design-review directamente, sin simular auditores ausentes. ## 14. Límites y riesgos residuales La verificación corresponde a Chromium headless y las resoluciones indicadas, no dispositivos físicos. No certifica WCAG. No se ejecutaron lector de pantalla, contraste exhaustivo, tema oscuro, zoom 200/400 %, orientación móvil horizontal ni pruebas completas de localización en navegador inglés. Las traducciones nuevas se verifican por paridad y render unitario es/en. No se midieron tiempos reales de usuario. Se abrió y comprobó la superficie de soporte de la ficha de activo y del entorno de perfil; no se repitió el CRUD completo en cada consumidor. Se conserva su implementación, se comprueba la gestión anterior en tests y se ejecuta la suite Assets completa. No se cambia su contrato ni su comportamiento. El diálogo de gestión puede abrir diálogos anidados de formulario/historial/confirmación ya existentes. Los recorridos comprueban cancelación, cierre y operaciones; una auditoría completa de los formularios antiguos excede este cambio. La representación de estados/documentación de VPN conserva la semántica previa. ## 15. Siguiente versión M03–M09 permanecen propuestas sin implementar: capacidad de perfiles, metadatos de configuraciones, acciones repetidas, alcance del preview, vacíos, homogeneización de estados y skeleton. No se ha comenzado ninguna de ellas. Antes de ampliarlas, valorar la ficha completa con sus datos reales de uso y completar las verificaciones de accesibilidad pendientes. ## Cierre Completadas M01 y M02. Se conservan **31 PNG** (14 anteriores, 17 posteriores), una comparación Markdown y dos JSON sanitizados de mediciones/regresiones. Los 31 hashes SHA-256 coinciden; enlaces locales del informe/comparación, paridad de claves es/en, sintaxis Python y `git diff --check` correctos. Los **seis métodos MCP nuevos** pasaron entre las tandas ejecutadas, incluidas las repeticiones de los selectores/carga y la comprobación del resumen con dos conexiones. Las **seis regresiones existentes** pasaron en una tanda de cinco y otra de teclado/contraste/expansión. No se afirma una ejecución conjunta única. Biome de los nueve archivos propios y ESLint de sus siete TS/TSX terminaron correctamente; el typecheck final de Assets pasó tras corregir el import del test. Companies y Web también pasaron sus comprobaciones dirigidas. El preparador confirmó su retirada tras recibir SIGINT exclusivamente en el PID **142688**. Se verificó que su sesión privada ya no existe y se retiró el archivo local de seguimiento del PID. No se señalizaron otros preparadores ni se realizaron limpiezas globales. Permanecen los fallos globales ajenos y las limitaciones enumeradas; no quedan propuestas M01/M02 sin implementar. M03–M09 no forman parte de esta entrega.