250 lines
12 KiB
Markdown
250 lines
12 KiB
Markdown
# Sprint 5 — BRIEF
|
||
|
||
> InQ ROI — Sprint de UX polish + quick wins
|
||
> Inicio: 2026-06-19
|
||
> Foco: experiencia del usuario, mejoras visuales, features de alto impacto/bajo esfuerzo
|
||
|
||
---
|
||
|
||
## Contexto
|
||
|
||
Sprint 4 fue un refactor arquitectural completo (IndexedDB → Supabase, auth, recursos globales). El producto está estable y en uso interno. Sprint 5 vuelve al rebalanceo normal: **60-70% features de producto, 10-15% infra/deuda técnica**.
|
||
|
||
Sin features de gran escala (historial de simulaciones, compartir con guests). Solo mejoras que suman experiencia real.
|
||
|
||
---
|
||
|
||
## Etapas
|
||
|
||
### Etapa 1 — Fix crítico: workspace loading
|
||
|
||
**Problema:** Al navegar desde la biblioteca a un proceso, el workspace se queda cargando indefinidamente. La pantalla solo carga correctamente después de refrescar la página manualmente.
|
||
|
||
**Diagnóstico a confirmar:** probable race condition entre `useEffect` de carga del proceso y disponibilidad del usuario autenticado. El `processId` llega por route params antes de que el store tenga el usuario listo, y el query a Supabase se dispara con un contexto incompleto o se omite silenciosamente.
|
||
|
||
**Alcance:**
|
||
- Diagnosticar el flujo completo: `WorkspacePage` → `useProcess` hook → `process-repo.getById()` → render
|
||
- Identificar dónde el guard de auth interactúa mal con la carga del proceso
|
||
- Corregir sin introducir flickering ni doble render
|
||
- El workspace debe cargar al primer intento, sin refresh
|
||
|
||
**Criterios:**
|
||
- [ ] Navegar desde la biblioteca a cualquier proceso carga el workspace en el primer intento
|
||
- [ ] Sin errores en consola durante la navegación
|
||
- [ ] El estado de loading muestra un skeleton o spinner visible (no pantalla en blanco)
|
||
- [ ] Tests Vitest verdes (sin regresiones)
|
||
- [ ] Validación visual del director
|
||
|
||
---
|
||
|
||
### Etapa 2 — Fix + mejora: zoom BPMN
|
||
|
||
**Problema:** El botón de fit-viewport actual posiciona el diagrama pegado al borde superior, sin padding. Además no hay controles de zoom explícitos.
|
||
|
||
**Alcance:**
|
||
|
||
**Fix fit-viewport:**
|
||
- Corregir `canvas.zoom('fit-viewport')` para que el diagrama quede centrado con padding uniforme (sugerido: 40px en todos los bordes)
|
||
- bpmn-js expone `canvas.zoom('fit-viewport', true)` y opciones de padding — usar la API correcta
|
||
|
||
**Controles de zoom (versión wow):**
|
||
- Botón "+" (zoom in) y "−" (zoom out) en el canvas
|
||
- Botón de reset/fit (ícono de encuadre) — corrige el bug actual + sirve de reset
|
||
- Posición: esquina inferior derecha del canvas, sin tapar el diagrama
|
||
- Estilo: botones cuadrados de 32px, fondo blanco semitransparente, borde sutil, ícono Tabler
|
||
- No interferir con el zoom por scroll/pinch que ya funciona
|
||
|
||
**Íconos sugeridos:** `ti-zoom-in`, `ti-zoom-out`, `ti-focus-2` (para fit)
|
||
|
||
**Criterios:**
|
||
- [ ] Fit-viewport centra el diagrama con padding uniforme (no clip al borde)
|
||
- [ ] Botones +/−/fit visibles en el canvas
|
||
- [ ] +/− hacen zoom in/out incremental (factor 1.2x por click)
|
||
- [ ] Fit resetea a la vista centrada
|
||
- [ ] Los controles no aparecen encima de los paneles laterales
|
||
- [ ] Tests Vitest verdes
|
||
- [ ] Validación visual del director
|
||
|
||
---
|
||
|
||
### Etapa 3 — Heatmap con gradiente continuo + toggle de modo
|
||
|
||
**Problema actual:** el heatmap usa 3 buckets discretos (verde/amarillo/rojo) con colores fijos. Sin matices intermedios, sin gradiente.
|
||
|
||
**Alcance:**
|
||
|
||
**Escala de color continua:**
|
||
Reemplazar la lógica de 3 buckets por una función de interpolación de 4 stops:
|
||
```
|
||
0.0 → #10b981 (verde)
|
||
0.33 → #f59e0b (amarillo)
|
||
0.67 → #f97316 (naranja)
|
||
1.0 → #ef4444 (rojo vivo)
|
||
```
|
||
|
||
Implementar en `src/lib/colors.ts` como `intensityToColor(normalized: number): string` usando interpolación lineal en RGB entre stops consecutivos.
|
||
|
||
**Dos modos de normalización:**
|
||
|
||
`percentile` (default): cada actividad se posiciona según su rango relativo entre todas las actividades del proceso. No sufre distorsión por outliers.
|
||
|
||
`minmax`: `(costo - mínimo) / (máximo - mínimo)`. Refleja valores absolutos pero se comprime con outliers.
|
||
|
||
**Persistencia del modo:** guardar la preferencia en `localStorage` (key: `heatmap-mode`). Default: `percentile`.
|
||
|
||
**Toggle en UI:**
|
||
- Un toggle compacto en el panel del reporte o en la barra de herramientas del workspace
|
||
- Label: "Escala de color: Relativa (percentil) / Absoluta (min-max)"
|
||
- Tamaño pequeño, no protagonista — es una preferencia técnica, no el flujo principal
|
||
|
||
**Dónde aplica el heatmap:**
|
||
- Nodos del canvas BPMN (overlay de color en actividades)
|
||
- Tabla del reporte web (fondo de celdas de costo)
|
||
- PDF: usa los mismos valores calculados pero sin el toggle (renderiza el modo activo al exportar)
|
||
|
||
**Recalibrar E2E de píxeles:** los tests que verifican colores del canvas BPMN necesitan actualizar sus umbrales/valores esperados para la nueva escala. Identificar los specs afectados y corregirlos.
|
||
|
||
**Criterios:**
|
||
- [ ] El gradiente muestra transiciones suaves (no saltos abruptos de verde a rojo)
|
||
- [ ] Modo percentil: actividades distribuidas a lo largo de la escala incluso con outliers
|
||
- [ ] Modo min-max: outlier extremo domina la escala (comportamiento esperado)
|
||
- [ ] Toggle funciona y persiste entre sesiones
|
||
- [ ] PDF exporta con el modo activo al momento de la exportación
|
||
- [ ] Tests E2E de heatmap recalibrados y verdes
|
||
- [ ] Tests Vitest verdes (nueva función `intensityToColor` con tests unitarios)
|
||
- [ ] Validación visual del director
|
||
|
||
---
|
||
|
||
### Etapa 4 — Ver procesos por recurso + campo empresa en perfil
|
||
|
||
Dos features pequeñas en una etapa.
|
||
|
||
**Feature A — Ver procesos asociados a un recurso:**
|
||
|
||
En `ResourceCatalogPage` (`/recursos`), cada fila de la tabla debe mostrar cuántos procesos usan ese recurso.
|
||
|
||
- Nueva columna "Procesos" en la tabla: muestra un badge con el número (ej: `3 procesos`)
|
||
- Si es 0: muestra "—" con color muted
|
||
- Si es > 0: el badge es clickeable y expande una lista de los procesos (nombre + link directo al workspace)
|
||
- La expansión puede ser inline (fila expandible) o un popover/tooltip al hover
|
||
- Dato: query a `activity_resource_assignments` agrupado por `resource_id`, con JOIN a `processes` para el nombre
|
||
- Esto complementa la protección de borrado existente — ahora el usuario ve *qué* proceso usa el recurso antes de intentar eliminarlo
|
||
|
||
**Feature B — Campo empresa en perfil de usuario:**
|
||
|
||
- Nueva columna `company text` en tabla `users` de Supabase (nullable, sin default)
|
||
- Migración: `ALTER TABLE users ADD COLUMN IF NOT EXISTS company text;`
|
||
- UI: en el dropdown del AppHeader (donde aparece nombre y email), agregar una línea con la empresa si está definida
|
||
- Edición: agregar un botón "Editar perfil" en el dropdown que abre un Sheet con campos editables: nombre y empresa (email es de solo lectura — viene de Google OAuth)
|
||
- La empresa se muestra también en la tabla de la biblioteca si hay espacio (opcional, decidir con validación visual)
|
||
|
||
**Criterios:**
|
||
- [ ] Columna "Procesos" visible en `/recursos` con conteo correcto
|
||
- [ ] Click en el badge con conteo > 0 muestra la lista de procesos con links funcionales
|
||
- [ ] Columna `company` creada en Supabase sin romper datos existentes
|
||
- [ ] El dropdown del AppHeader muestra la empresa si está definida
|
||
- [ ] Sheet de edición de perfil guarda nombre y empresa en Supabase
|
||
- [ ] Tests Vitest verdes
|
||
- [ ] Validación visual del director
|
||
|
||
---
|
||
|
||
### Etapa 5 — Columna "Eficiencia de automatización"
|
||
|
||
**Contexto:** la tabla de comparación (ComparisonTable) hoy muestra costo AS-IS, costo TO-BE, ahorro y probabilidad. Le falta una métrica que permita *rankear* actividades por valor de automatización — no solo quién ahorra más en valor absoluto, sino qué actividades ofrecen el mejor retorno por peso invertido.
|
||
|
||
**Métrica:**
|
||
```
|
||
eficiencia = (ahorro$ × probabilidad) / tiempo_ejecucion_minutos
|
||
```
|
||
|
||
Alternativa si no hay inversión por actividad: usar `ahorro$ × probabilidad` como proxy simple (ahorro esperado ponderado). Decidir en implementación cuál es más interpretable para un consultor.
|
||
|
||
**Alcance:**
|
||
- Nueva columna "Eficiencia" en `ComparisonTable` del reporte web
|
||
- Valor = ahorro esperado ponderado por probabilidad de automatización
|
||
- Ordenar la tabla por esta columna por defecto (mayor eficiencia primero) — con posibilidad de cambiar el orden haciendo click en el header
|
||
- Versión wow: barra de progreso inline de ancho relativo (la actividad más eficiente = 100%, las demás proporcionales). Mismo estilo que las barras del heatmap
|
||
- Tooltip en el header de la columna explicando la fórmula
|
||
- Si `isAutomatable = false`: mostrar "—" (em dash), igual que columna Ahorro
|
||
|
||
**En PDF:**
|
||
- Incluir la columna en la tabla de comparación del PDF si entra sin truncamiento
|
||
- Si no entra, omitirla (el PDF ya es denso) — decidir en validación visual
|
||
|
||
**Criterios:**
|
||
- [ ] Columna visible en el reporte web con valores correctos
|
||
- [ ] Actividades no automatizables muestran "—"
|
||
- [ ] Orden por defecto: mayor eficiencia primero
|
||
- [ ] Click en header reordena la tabla
|
||
- [ ] Barra de progreso proporcional visible
|
||
- [ ] Tooltip en header con explicación de la fórmula
|
||
- [ ] Cálculo tiene tests unitarios en Vitest
|
||
- [ ] Validación visual del director
|
||
|
||
---
|
||
|
||
### Etapa 6 — Limpieza técnica
|
||
|
||
**6a — E2E: reescribir specs Dexie → Supabase**
|
||
- `export-pdf.spec.ts` y `validate-dod-etapa4.spec.ts` inyectan datos vía Dexie/IndexedDB, que fue eliminado en Sprint 4
|
||
- Reescribir fixtures para usar el test user `martin.bernal@inquality.com.py` via Supabase
|
||
- Limpiar datos de test después de cada corrida (usar `afterAll` con `service_role_key`)
|
||
|
||
**6b — E2E: fix flakiness "Guardar cambios"**
|
||
- 3 specs fallan intermitentemente por timing: Playwright no encuentra el botón en estado habilitado
|
||
- Fix: `await page.waitForSelector('[data-testid="save-btn"]:not([disabled])')` o equivalente
|
||
- Agregar `data-testid="save-btn"` al botón en `ActivityPanel.tsx` si no existe
|
||
|
||
**6c — Limpieza de BACKLOG y documentación**
|
||
- Marcar como `[RESOLVED]` en `BACKLOG.md`: "Indicador de simulación desactualizada", "Edición inline de proceso/cliente", "Controles de zoom BPMN" (resueltos en Sprints 2/3 y Etapa 2 de este sprint)
|
||
- Actualizar `STRATEGIC_DIRECTION.md` con cierre de Sprint 4 (pendiente desde sesión anterior)
|
||
- Vaciar `OBSERVATIONS.md` y preparar encabezado para Sprint 5
|
||
- Marcar como `[RESOLVED]` en `TECH_DEBT.md` los ítems resueltos en esta etapa
|
||
|
||
**Criterios:**
|
||
- [ ] `export-pdf.spec.ts` y `validate-dod-etapa4.spec.ts` verdes en CI con Supabase real
|
||
- [ ] 3 specs flaky del botón "Guardar" estables
|
||
- [ ] `npm run test` — mantener o superar conteo anterior de Vitest
|
||
- [ ] `npx playwright test` — 0 specs permanentemente rojos
|
||
- [ ] BACKLOG, TECH_DEBT, STRATEGIC_DIRECTION y OBSERVATIONS actualizados
|
||
- [ ] Validación del director sobre el estado de los archivos
|
||
|
||
---
|
||
|
||
## Distribución del sprint
|
||
|
||
| Área | Etapas | % |
|
||
|---|---|---|
|
||
| Features de producto / UX | 1, 2, 3, 4, 5 | ~83% |
|
||
| Infraestructura / deuda técnica | 6 | ~17% |
|
||
| PDF | (toca en Etapa 3 y 5, sin etapa dedicada) | — |
|
||
|
||
Dentro del rango válido del rebalanceo (60-70% web, 10-15% infra). PDF sin etapa dedicada — aceptable este sprint dado que Sprint 4 no tocó PDF.
|
||
|
||
---
|
||
|
||
## Qué NO entra en Sprint 5
|
||
|
||
- Historial de simulaciones / múltiples simulaciones por proceso
|
||
- Implementación real de `setShared()` (diferida hasta primer guest)
|
||
- Keycloak / migración de auth
|
||
- Modo offline / PWA
|
||
- i18n
|
||
- Export Excel
|
||
- Gateway OR inclusivo
|
||
|
||
---
|
||
|
||
## Definition of Done del sprint
|
||
|
||
- [ ] 6 etapas con OK formal del director (validación visual de cada una)
|
||
- [ ] `npm run build` limpio
|
||
- [ ] `npm run lint` sin warnings
|
||
- [ ] Tests Vitest: mantener o superar conteo de Sprint 4
|
||
- [ ] Tests E2E: 0 specs permanentemente rojos
|
||
- [ ] CHECKLIST_ENTREGA.md ejecutado antes de cada entrega de etapa
|
||
- [ ] OBSERVATIONS.md con hallazgos del sprint al cierre
|
||
- [ ] STRATEGIC_DIRECTION.md actualizado con Sprint 4 y 5
|