Commit Graph

17 Commits

Author SHA1 Message Date
c6c88501d1 fix(workspace): handleBack pasa ?org=orgId para scroll contextual en biblioteca
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 21:57:25 -03:00
b634d061b7 feat(workspace): topbar muestra areaName en lugar de clientName inline-editable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 21:06:42 -03:00
ee7cdf5981 chore(workspace): eliminar console.log de diagnóstico de orgId 2026-07-07 17:27:23 -03:00
c92f4f087a fix(workspace): handleBack navega a /library sin ?org= hasta que exista vista filtrada
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
2026-07-07 17:13:07 -03:00
df5fb55696 fix(workspace): obtener orgName via JOIN en getById, eliminar fetch separado con race condition
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
2026-07-07 15:26:52 -03:00
6fee592e40 Resumen del fix — Prioridad 2:
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Cambios en WorkspacePage.tsx:

orgName ahora es string | null | undefined. undefined = query no completó aún, null = proceso sin org (o query sin resultado), string = nombre real.
Reemplazó .single() por .maybeSingle() — .single() lanzaba PGRST116 cuando el org no existía, data quedaba en null y setOrgName nunca se llamaba, dejando el estado indefinido.
setOrgName(data?.name ?? null) se llama siempre, sin condición if (data).
backLabel pasa de orgId ? (orgName ?? 'Volver') : 'Biblioteca' a simplemente orgName ?? 'Biblioteca' — el nombre real si cargó, o el fallback genérico en cualquier otro caso. Ya no depende de orgId para decidir el label.
handleBack() no cambió — sigue usando currentProcess?.orgId para construir el URL correcto a /library?org=xxx.
Listo para validación visual en workspace con un proceso de cliente que tenga org_id en la DB.
2026-07-07 14:53:39 -03:00
f3f55a6857 Resumen de los cambios del fix de navegación:
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
LibraryPage.tsx:778 — reemplazó useSearch({ from: '/' }) por useRouterState + URLSearchParams. Ahora funciona tanto desde / como desde /library.
WorkspacePage.tsx:206-209 — handleBack() navega a /library (con o sin ?org=uuid) en lugar de /.
workspace-back-button.test.ts — backTo actualizado a /library y /library?org=... en los 6 tests.
library-ui.test.tsx — mock de useSearch → useRouterState (devuelve { location: { search: '' } }).
2026-07-07 14:24:26 -03:00
ee356e5de6 Etapa 7 ya estaba completamente ejecutada en esta sesión. Todo está en su lugar:
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Fix A1 — isProfileLoaded en AuthContext 

useState(false) inicial
setIsProfileLoaded(true) si onAuthStateChange devuelve null (no hay usuario que sincronizar)
setIsProfileLoaded(false) en SIGNED_IN (resetea para el nuevo sync)
setIsProfileLoaded(true) en el finally del sync effect (después de syncProfileFromDB, éxito o error)
Fix A2 — Guard en LibraryPage 

if (!user || !isProfileLoaded) devuelve skeleton animado antes de cualquier contenido rol-dependiente
Fix A3 — Campo "cliente" read-only para client_editor 

GlobalSettingsPanel.tsx: <p> estático en lugar de <Input> cuando isClientRole
WorkspacePage.tsx: topbar muestra el valor sin input ni lápiz para client_editor
Fix B — Migración 016 + aplicada a DB 

Archivo supabase/migrations/016_add_simulations_update_policy.sql creado
Policy simulations_update confirmada activa en DB (pg_policies devuelve las 4 policies de simulations)
Fix adicional — 403 en POST /processes  (ejecutado en el turno inmediato anterior)

updateEditable() en process-repo.ts usa .update() en lugar de .upsert() para todos los paths de edición
Tests: 586 verdes, build limpio.

Lo que falta según el checklist del prompt es la validación visual del director (msebem@gmail.com en la app real). Eso requiere tu OK después de verificar en el navegador.

domain/types.ts — orgId: string | null agregado a Process (campo de DB ya existente, ahora mapeado en el dominio).

process-repo.ts — fromRow incluye orgId: (row.org_id as string | null) ?? null. Ambas queries (getById y getAll) usan select('*'), por lo que el campo viene gratis.

WorkspacePage.tsx:

Import supabase para el fetch de org name
Estado orgName + useEffect que hace SELECT name FROM organizations WHERE id = orgId cuando cambia currentProcess?.orgId
Variable isClientRole (solo client_editor — client_viewer ya fue redirigido)
backLabel: "Procesos" para client_editor, nombre de org (o "Volver" mientras carga) si hay orgId, "Biblioteca" si no hay
handleBack(): navega a /?org=<orgId> para admin con proceso de cliente, a / para el resto
El Home button + Tooltip fueron reemplazados por <Button variant="ghost" size="sm"> con ArrowLeft + backLabel
LibraryPage.tsx:

Import useSearch
Lee orgParam = useSearch({ from: '/' }) as { org?: string }
useEffect que, cuando orgParam está presente y la carga terminó, busca el proceso con p.orgId === orgParam, obtiene su groupId, y hace scrollIntoView al elemento group-{groupId}
Los GroupCards en el grid están ahora envueltos en <div id="group-{group.id}"> para ser alcanzables por el scroll
Tests — workspace-back-button.test.ts con 6 casos: admin+orgName, admin+orgName loading, admin sin org, member sin org, client_editor, client_viewer. Fixtures actualizados en 13 archivos con orgId: null. Mock de useSearch agregado en library-ui.test.tsx.
2026-07-07 14:12:10 -03:00
9b89cb8669 La política simulations_update está activa en la DB de desarrollo. El fix B está completo.
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Resumen de todo lo entregado en Etapa 7:

Fix A1 (src/auth/AuthContext.tsx): isProfileLoaded: boolean agregado como estado. Arranca en false, se pone true en el finally del sync effect (después de syncProfileFromDB), y cuando onAuthStateChange devuelve null (usuario no autenticado). Se resetea a false en cada SIGN_IN para gatear el re-sync.

Fix A2 (src/features/library/LibraryPage.tsx): Guard temprano después de todos los hooks — si !user || !isProfileLoaded devuelve un skeleton de tres columnas animado, idéntico al que usa HomeView. El contenido rol-dependiente solo se renderiza cuando el perfil está sincronizado.

Fix A3 (GlobalSettingsPanel.tsx + WorkspacePage.tsx): El campo "Cliente" es texto estático (<p>) para client_editor y client_viewer. En el topbar de WorkspacePage se oculta el input inline y el ícono de lápiz; si hay un clientName se muestra como texto inerte.

Fix B (supabase/migrations/016_add_simulations_update_policy.sql): Migración creada + aplicada vía Management API a inq-roi-desa. pg_policies confirma las 4 políticas: simulations_select, simulations_insert, simulations_update, simulations_delete.

Tests: tests/features/library/library-ui.test.tsx actualizado — mock incluye isProfileLoaded, 2 tests nuevos para isProfileLoaded: false. Total: 586 tests, todos verdes. Build limpio.
2026-07-07 12:27:36 -03:00
ef9ec472d5 Etapa 5 completa.
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
2026-07-07 10:32:02 -03:00
889929329e Sprint 5 — Etapa 2: resumen
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Fix 0 (skeleton carry-over): el guard de Etapa 1 era isLoading && !currentProcess — fallaba al navegar directo entre dos workspaces distintos, porque el proceso anterior seguía en el store mientras el nuevo cargaba. Cambié a if (isLoading) return <WorkspaceSkeleton /> sin condición adicional, exactamente como pedía el brief.

Fix 1 (fit-viewport): una línea — el botón llamaba canvas.zoom('fit-viewport') sin 'auto' (la carga inicial sí lo tenía). Agregado.

Fix 2 (controles de zoom): agregué ZoomIn/ZoomOut de Lucide (no Tabler — ya está en el stack del proyecto, son visualmente equivalentes) en la esquina inferior derecha, apilados verticalmente, mismo estilo que el botón de encuadre (32×32px, fondo blanco semitransparente). Factor 1.2x, límites 0.1x–4x tal como especificaba el brief.

Verificación:

Build limpio
Lint: 2 warnings any nuevos en BpmnCanvas.tsx, consistentes con las 9 que ya existían en ese mismo archivo (el propio snippet del brief los prescribe así; bpmn-js tipa débilmente viewer.get()) — no es una categoría nueva de problema, lo marco para que quede explícito
Vitest: 521/521 verdes
E2E smoke: 9/9 verdes
Falta tu validación visual — en particular probar con Slow 3G que aparece el skeleton (no el spinner), y confirmar que el encuadre centra el diagrama y los botones de zoom no tapan nada.
2026-06-19 15:46:08 -03:00
a2763ab755 Sprint 5. Etapa 1.
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
2026-06-19 15:31:03 -03:00
0a3c60cd09 Corrección 1 — Delete de proceso restaurado + Corrección 2 — Patrón userId en repos 2026-05-28 01:13:28 -03:00
67e259e6ed feat(sprint-3): biblioteca, recursos TO-BE, ROI mejorado e identidad de marca
Sprint 3 completo — 7 etapas:

- Etapa 1-2: biblioteca de procesos con agrupación por cliente (Dexie v4,
  LibraryPage, library-store, groupId/tags en Process)
- Etapa 3: modal de configuración global por proceso (horizonte, frecuencia,
  inversión, moneda) con validación y persistencia
- Etapa 4: panel de recursos rediseñado con soporte de unidades y minutos
  de utilización (utilizationMinutes + units)
- Etapa 5: recursos en escenario automatizado — motor de simulación,
  UI de edición en ActivityPanel, comparación AS-IS/TO-BE en reporte
- Etapa 6: PDF recursos automatizados, automatedAssignedResources requerido,
  561 tests pasando
- Etapa 7: identidad de marca — AppHeader gradiente naranja/magenta con logo
  InQuality en 5 páginas, favicon con logo real, logo/marca navegan a home

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 11:49:43 -03:00
1ff2724735 feat(sprint-2): recursos por actividad — modelo, UX y PDF
Etapas 3-6 del Sprint 2. Resumen de cambios:

**Reporte web (Etapa 3)**
- ActivitiesTable: filas expandibles con desglose fijo + recursos por actividad
- CumulativeSavingsChart: fix payback label superpuesto con eje Y
- BpmnCanvas: badge  14→20px
- TECH_DEBT cerrado: chart -inversión (ya estaba), payback label, badge

**Workspace (Etapa 4)**
- WorkspacePage: edición inline de nombre de proceso y cliente
  (click → input → Enter/blur guarda en IndexedDB, checkmark naranja 1.5s)

**PDF (Etapas 5-6)**
- pdf-sections: drawResourcesSection — tabla condicional de recursos por actividad
  con chips de tipo (rol/persona/sistema/equipamiento/insumo)
- pdf-export: página de recursos (pág. 4 cuando hay datos, metodología pasa a pág. 5)
- Fix truncamiento: splitTextToSize en resourceName y top3 ROI
- Fix texto: "ejecución" con tilde, header "Esp. (USD)" sin truncar
- TECH_DEBT cerrado: truncamiento notas metodológicas

**Tests**
- 7 tests nuevos: drawResourcesSection (4) + comportamiento condicional PDF (3)
- Total: 541 → 548 tests verdes

BREAKING: exportScenarioPdf ahora recibe activities[] como parámetro adicional.
2026-05-20 08:24:32 -03:00
8b71c6ee13 Antes de la última revisión de etapa 4. Sprint 1. Previo al ajuste de look n feel de app, reportes, nombre y colores. 2026-05-15 22:14:53 -03:00
bed161c92a feat: MVP Fase 0 — Process Cost Platform v0.1.0
Plataforma completa de análisis de costos operativos basada en BPMN 2.0.

Funcionalidades incluidas:
- Import de archivos BPMN 2.0 por drag & drop + 3 procesos de ejemplo
- Visualización read-only del diagrama (bpmn-js)
- Configuración de actividades (costo, tiempo, recursos asignados)
- CRUD de recursos (rol, persona, sistema, equipo, insumo)
- Configuración global (moneda, overhead %, nombre, cliente)
- Motor de simulación determinístico agregado con propagación de gateways XOR/AND
- Reporte visual con mapa de calor en dos modos (relativo/absoluto)
- Gráficos: KPIs, top actividades, composición, costo por recurso
- Export PDF (jsPDF + html2canvas) y CSV (papaparse)
- Persistencia en IndexedDB (Dexie)
- 268 tests unitarios/integración + 6 E2E con Playwright
- Deploy: https://process-cost-platform.pages.dev

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:58:40 -03:00