Antes de meterle a sprint 1 etapa 4 y 5
This commit is contained in:
56
CLAUDE.md
56
CLAUDE.md
@@ -5,6 +5,49 @@
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Reglas de Marca — NO NEGOCIABLES (Sprint 1.5+)
|
||||
|
||||
Estas reglas aplican a TODO string que aparezca en código, PDFs, CSVs, tests y documentación.
|
||||
|
||||
### 1. Ortografía de "InQ" — SIEMPRE I-n-Q
|
||||
|
||||
```
|
||||
✅ InQ ← correcto
|
||||
✅ InQuality ← correcto (nombre completo)
|
||||
✅ InQ ROI ← nombre del producto
|
||||
|
||||
❌ INQ ← bug
|
||||
❌ Inq ← bug
|
||||
❌ inq ← bug
|
||||
❌ inQ ← bug
|
||||
```
|
||||
|
||||
Cualquier desviación es un bug que debe corregirse antes de hacer commit.
|
||||
|
||||
### 2. Nombre del producto
|
||||
|
||||
`InQ ROI` — nombre de trabajo para Sprint 1.5. Se reemplazará en Sprint 3-4. No debatir el nombre ahora.
|
||||
|
||||
### 3. Color protagonista
|
||||
|
||||
```
|
||||
Primario: #F59845 (naranja InQ)
|
||||
Gradiente: #F59845 → #ED3E8F (naranja → magenta InQ)
|
||||
```
|
||||
|
||||
El gradiente se usa SOLO en KPI Hero y banners principales.
|
||||
**NO usar morado de CONCILIA** (`#572FA2`, `#CB1889`) en este producto.
|
||||
|
||||
### 4. Footer de PDFs
|
||||
|
||||
Tagline obligatorio: `"Powered by InQuality"` — en todos los footers de PDF, siempre.
|
||||
|
||||
### 5. Rol del consultor
|
||||
|
||||
Si aparece un nombre de consultor en algún campo, es como "consultor responsable", no como "creador" ni "founder" del producto.
|
||||
|
||||
---
|
||||
|
||||
## Identidad del Proyecto
|
||||
|
||||
**Nombre de trabajo**: Process Cost Platform (nombre comercial por definir)
|
||||
@@ -231,4 +274,15 @@ npx playwright test # tests E2E (Playwright headless)
|
||||
- Casos de uso confirmados:
|
||||
- Análisis de costos operativos en consultoría de procesos
|
||||
- **Pre-venta de proyectos de automatización con cálculo de ROI** (caso estrella del Sprint 1)
|
||||
- Valora: claridad, robustez, pulido visual, mantenibilidad, validación rigurosa
|
||||
- Valora: claridad, robustez, pulido visual, mantenibilidad, validación rigurosa
|
||||
|
||||
---
|
||||
|
||||
## Reglas de marca NO NEGOCIABLES
|
||||
|
||||
- "InQ" siempre se escribe I-n-Q (mayúscula-minúscula-mayúscula)
|
||||
- Color protagonista: naranja #F59845
|
||||
- Gradiente identidad: #F59845 → #ED3E8F
|
||||
- NO usar morado CONCILIA (#572FA2, #CB1889)
|
||||
- Footer obligatorio: "Powered by InQuality"
|
||||
- No promover a Marcos como creador
|
||||
330
DESIGN_SYSTEM.md
Normal file
330
DESIGN_SYSTEM.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# InQ ROI — Sistema de Diseño
|
||||
|
||||
> Documento de referencia visual para Sprint 2+.
|
||||
> Fuente de verdad para la paleta, tipografía y componentes.
|
||||
> Actualizar en cada sprint que modifique la identidad visual.
|
||||
|
||||
---
|
||||
|
||||
## 1. Identidad de Marca
|
||||
|
||||
### Nombre del producto
|
||||
**InQ ROI** — herramienta interna de InQuality para cuantificación de ROI de automatización.
|
||||
|
||||
### Regla de ortografía (NO NEGOCIABLE)
|
||||
```
|
||||
✅ InQ ← I mayúscula, n minúscula, Q mayúscula
|
||||
✅ InQuality ← nombre completo
|
||||
❌ INQ / Inq / inq / inQ ← cualquiera es bug
|
||||
```
|
||||
|
||||
### Tagline en footers PDF
|
||||
`"Powered by InQuality"` — obligatorio en todos los footers de PDF.
|
||||
|
||||
---
|
||||
|
||||
## 2. Paleta Cromática
|
||||
|
||||
### 2.1 InQ Orange — Color protagonista
|
||||
|
||||
| Token Tailwind | CSS Var | Hex | HSL | Uso |
|
||||
|---|---|---|---|---|
|
||||
| `bg-inq-orange` | `--inq-orange` | `#F59845` | 28° 90% 62% | Principal: logo, KPIs hero, CTAs primarios |
|
||||
| `bg-inq-orange-dark` | `--inq-orange-dark` | `#B45309` | 34° 93% 37% | Texto sobre fondos claros, hover de CTAs |
|
||||
| `bg-inq-orange-light` | `--inq-orange-light` | `#FEF3E2` | 36° 95% 88% | Fondos de KPI cards |
|
||||
| `bg-inq-orange-lighter` | `--inq-orange-lighter` | `#FFF8ED` | 36° 100% 94% | Fondos de banner narrativo, hover sutiles |
|
||||
|
||||
### 2.2 InQ Magenta — Gradiente identidad
|
||||
|
||||
| Token Tailwind | CSS Var | Hex | Uso |
|
||||
|---|---|---|---|
|
||||
| `bg-inq-magenta` | `--inq-magenta` | `#ED3E8F` | Segundo color del gradiente identidad |
|
||||
|
||||
#### Gradiente identidad
|
||||
```css
|
||||
background: linear-gradient(135deg, #F59845 0%, #ED3E8F 100%);
|
||||
```
|
||||
|
||||
**Uso exclusivo:** KPI Hero "Ahorro proyectado" en PDF y web. NUNCA en bordes, separadores ni fondos secundarios.
|
||||
|
||||
### 2.3 Semánticos
|
||||
|
||||
| Token Tailwind | CSS Var | Hex | Uso |
|
||||
|---|---|---|---|
|
||||
| `bg-success` | `--color-success` | `#16A34A` | Ahorros positivos, payback alcanzado |
|
||||
| `bg-success-light` | `--color-success-light` | `#F0FDF4` | Fondos de mensajes positivos |
|
||||
| `bg-warning` | `--color-warning` | `#F59E0B` | Advertencias, sección transparencia |
|
||||
| `bg-warning-bg` | `--color-warning-bg` | `#FFFBEB` | Fondo de sección transparencia |
|
||||
| `bg-destructive` / `--color-danger` | — | `#EF4444` | Costos altos, valores negativos |
|
||||
| `--color-danger-light` | — | `#FEE2E2` | Fondos de heatmap alto costo |
|
||||
|
||||
### 2.4 Heatmap — Paleta saturada (FIJA hasta Sprint 3-4)
|
||||
|
||||
| Token Tailwind | Hex | RGB | Uso |
|
||||
|---|---|---|---|
|
||||
| `bg-heatmap-low` | `#10B981` | (16, 185, 129) | Actividades de bajo costo |
|
||||
| `bg-heatmap-mid` | `#F59E0B` | (245, 158, 11) | Actividades de costo medio |
|
||||
| `bg-heatmap-high` | `#EF4444` | (239, 68, 68) | Actividades de alto costo |
|
||||
|
||||
#### Decisión sobre paleta de heatmap
|
||||
|
||||
**Se mantiene saturada** (verde-ámbar-rojo) en lugar de la variante pastel del brief por dos razones:
|
||||
|
||||
1. **Tests E2E calibrados**: los análisis de píxeles del heatmap (`export-pdf.spec.ts`, `validate-dod-etapa4.spec.ts`) tienen umbrales calibrados para estos colores. Cambiar la paleta requiere recalibrar todos esos umbrales.
|
||||
|
||||
2. **Visibilidad en pantallas grandes**: el producto se usa en talleres y charlas InQuality proyectadas en pantalla. Los colores saturados mantienen contraste a distancia. Los pasteles se "lavan" a 3+ metros.
|
||||
|
||||
**Revisión programada**: Sprint 3-4 con feedback real de uso en talleres.
|
||||
|
||||
**Invariante crítica**: los valores de `tailwind.config.js` `heatmap.*` DEBEN coincidir con las constantes `HEATMAP_LOW/MID/HIGH` en `src/lib/colors.ts`. Si se modifica uno, debe actualizarse el otro.
|
||||
|
||||
### 2.5 Neutrales
|
||||
|
||||
| Hex | Tailwind equivalente | Uso |
|
||||
|---|---|---|
|
||||
| `#0F172A` | `slate-900` | Títulos, números importantes |
|
||||
| `#475569` | `slate-600` | Texto del cuerpo |
|
||||
| `#64748B` | `slate-500` | Labels, metadatos |
|
||||
| `#94A3B8` | `slate-400` | Placeholders, texto muy secundario |
|
||||
| `#E2E8F0` | `slate-200` | Bordes generales |
|
||||
| `#F1F5F9` | `slate-100` | Separadores sutiles |
|
||||
| `#F8FAFC` | `slate-50` | Fondo de la app, canvas BPMN |
|
||||
|
||||
### 2.6 Colores que NO usar
|
||||
|
||||
```
|
||||
❌ #572FA2 Morado primario de CONCILIA — marca hermana, no mezclar
|
||||
❌ #CB1889 Magenta de CONCILIA
|
||||
❌ azul shadcn por defecto (221.2 83.2% 53.3%) — reemplazado por InQ orange
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Tipografía
|
||||
|
||||
### 3.1 Familias
|
||||
|
||||
```css
|
||||
/* Primaria — web app y body de PDFs */
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
|
||||
/* Mono — números en tablas, datos financieros */
|
||||
font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
|
||||
```
|
||||
|
||||
Tailwind: `font-sans` / `font-mono`
|
||||
|
||||
### 3.2 Escala PDF
|
||||
|
||||
| Elemento | Tamaño | Peso | Tracking |
|
||||
|---|---|---|---|
|
||||
| Logo "InQ ROI" en header | 22px | 700 | −0.8px |
|
||||
| Título de sección | 16px | 500 | normal |
|
||||
| KPI Hero (cifra) | 30px | 700 | −1px |
|
||||
| KPI secundario (cifra) | 16px | 700 | normal |
|
||||
| Body text | 11px | 400 | normal |
|
||||
| Labels en cards | 8px | 500 | 1px uppercase |
|
||||
| Tabla header | 10px | 500 | normal |
|
||||
| Tabla body | 10px | 400 | normal |
|
||||
| Footer | 9px | 400 | normal |
|
||||
|
||||
### 3.3 Escala Web App
|
||||
|
||||
| Elemento | Tamaño |
|
||||
|---|---|
|
||||
| Logo header | 18px / 700 |
|
||||
| Page title | 16px / 500 |
|
||||
| KPI Hero | 28px / 700 |
|
||||
| KPI secundario | 16px / 700 |
|
||||
| Nav / Tabs | 12px / 400-500 |
|
||||
| Body | 12-13px / 400 |
|
||||
| Labels en panels | 10-11px / 400-500 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Componentes
|
||||
|
||||
### 4.1 KPI Hero (gradiente naranja → magenta)
|
||||
|
||||
```
|
||||
Fondo: linear-gradient(135deg, #F59845 0%, #ED3E8F 100%)
|
||||
Padding: 16-18px
|
||||
Border-radius: 6-8px
|
||||
Label: 9-10px / uppercase / letter-spacing 1.2px / white opacity 0.9
|
||||
Cifra: 28-30px / 700 / letter-spacing −1px / white
|
||||
Subtítulo: 10-11px / white opacity 0.85
|
||||
```
|
||||
|
||||
Uso: el KPI "Ahorro proyectado a N años" — el más importante del reporte ROI.
|
||||
|
||||
### 4.2 KPI Card (secundario, fondo naranja claro)
|
||||
|
||||
```
|
||||
Fondo: #FEF3E2 (inq-orange-light)
|
||||
Padding: 10px 12px
|
||||
Border-radius: 6px
|
||||
Label: 8px / 500 / letter-spacing 1px / color #92400E / uppercase
|
||||
Cifra: 16px / 700 / color #0F172A
|
||||
Delta: 10px / 500 / color #B45309
|
||||
```
|
||||
|
||||
### 4.3 Banner narrativo (resumen ejecutivo)
|
||||
|
||||
```
|
||||
Fondo: #FFF8ED (inq-orange-lighter)
|
||||
Border-left: 3px solid #F59845
|
||||
Padding: 10-12px 14px
|
||||
Border-radius: 0 4px 4px 0
|
||||
Texto: 11px / 400 / line-height 1.55 / color #475569
|
||||
```
|
||||
|
||||
### 4.4 Sección Transparencia Metodológica
|
||||
|
||||
```
|
||||
Fondo: #FFFBEB (warning-bg)
|
||||
Border: 0.5px solid #F59E0B
|
||||
Padding: 12px 14px
|
||||
Border-radius: 6px
|
||||
Título: 11px / 500 / color #92400E / con ícono ⚠
|
||||
Texto: 10px / 400 / line-height 1.6 / color #78350F
|
||||
```
|
||||
|
||||
4 condiciones que activan la sección:
|
||||
1. Actividades `automatable=true` con `automatedCostFixed=0` y `automatedTimeMinutes=0`
|
||||
2. `automationInvestment=0`
|
||||
3. `roiAnnualPercent > 1000` (finito)
|
||||
4. (reservado para futuras reglas)
|
||||
|
||||
### 4.5 Tabla comparativa PDF
|
||||
|
||||
```
|
||||
Header row:
|
||||
Fondo: #FFF8ED
|
||||
Border-bottom: 1px solid #F59845
|
||||
Texto: 10px / 500 / #92400E
|
||||
|
||||
Body row — automatizable:
|
||||
Fondo: white
|
||||
|
||||
Body row — no automatizable:
|
||||
Fondo: #F8FAFC
|
||||
Texto: color #64748B (más tenue)
|
||||
|
||||
Total row:
|
||||
Fondo: #FFF8ED
|
||||
Border-top: 1.5px solid #F59845
|
||||
Texto: 10px / 500 / #0F172A
|
||||
```
|
||||
|
||||
### 4.6 Header PDF
|
||||
|
||||
```
|
||||
Layout: flex justify-between
|
||||
Border-bottom: 3px solid #F59845 (pág. 1) / 2px (otras)
|
||||
Padding-bottom: 10-12px
|
||||
Margin-bottom: 14-16px
|
||||
|
||||
Izquierda:
|
||||
"InQ ROI" 18-22px / 700 / #F59845
|
||||
Tagline: 9px / letter-spacing 1.5px / #94A3B8 (solo pág. 1)
|
||||
|
||||
Derecha:
|
||||
"UN PRODUCTO DE" 9px / letter-spacing 1px / #94A3B8
|
||||
"InQ" 16px / 700 / #475569
|
||||
"InQuality" 9px / #64748B
|
||||
```
|
||||
|
||||
### 4.7 Footer PDF
|
||||
|
||||
```
|
||||
Position: absolute bottom 14-16mm
|
||||
Padding-top: 6-8px
|
||||
Border-top: 0.5px solid #E2E8F0
|
||||
Layout: flex justify-between
|
||||
Font: 9px / 400 / #94A3B8
|
||||
|
||||
Izquierda: "InQ ROI" bold #F59845 " · Powered by InQuality · " cliente · fecha
|
||||
Derecha: "Página X de Y"
|
||||
```
|
||||
|
||||
### 4.8 Badge ⚡ (Automatizable)
|
||||
|
||||
#### En canvas BPMN overlay
|
||||
```
|
||||
Diámetro: 14px
|
||||
Fondo: #F59845 (naranja sólido)
|
||||
Border: 1.5px solid white
|
||||
Posición: { top: -8, left: nodeWidth - 12 }
|
||||
Símbolo: ⚡ blanco 8px
|
||||
```
|
||||
|
||||
Nota: en Sprint 1 el badge usa fondo `#fffbeb` (ámbar-50) con ícono ámbar. La migración a naranja sólido se hace en **Etapa 9** de Sprint 1.5.
|
||||
|
||||
#### En tablas y leyendas
|
||||
```
|
||||
Diámetro: 14px inline
|
||||
Fondo: #F59845
|
||||
Color: white
|
||||
```
|
||||
|
||||
### 4.9 Layout híbrido de PDFs (portrait + landscape)
|
||||
|
||||
Los PDFs combinan orientaciones por página:
|
||||
|
||||
- **Páginas SIN diagrama**: A4 vertical (210×297mm) — texto, tablas, KPIs
|
||||
- **Página DEL diagrama BPMN**: A4 horizontal (297×210mm) — para que el diagrama ocupe espacio real
|
||||
|
||||
Implementación jsPDF: `doc.addPage([297, 210], 'landscape')`
|
||||
|
||||
---
|
||||
|
||||
## 5. Tokens en código
|
||||
|
||||
### Web (Tailwind)
|
||||
|
||||
```tsx
|
||||
// Colores de marca
|
||||
<div className="bg-inq-orange"> // #F59845
|
||||
<div className="bg-inq-orange-dark"> // #B45309
|
||||
<div className="bg-inq-orange-light"> // #FEF3E2
|
||||
<div className="text-inq-orange"> // texto naranja
|
||||
<div className="border-inq-orange"> // borde naranja
|
||||
|
||||
// Gradiente identidad (como style prop — Tailwind no soporta gradientes dinámicos)
|
||||
<div style={{ background: 'linear-gradient(135deg, #F59845 0%, #ED3E8F 100%)' }}>
|
||||
|
||||
// Semánticos
|
||||
<div className="bg-success text-white"> // #16A34A
|
||||
<div className="bg-warning-bg"> // #FFFBEB
|
||||
```
|
||||
|
||||
### PDF (jsPDF)
|
||||
|
||||
```typescript
|
||||
// Constante en pdf-sections.ts (a migrar en Etapas 4-8)
|
||||
const PDF_ORANGE: [number, number, number] = [245, 152, 69] // #F59845
|
||||
const PDF_ORANGE_LIGHT: [number, number, number] = [254, 243, 226] // #FEF3E2
|
||||
const PDF_MAGENTA: [number, number, number] = [237, 62, 143] // #ED3E8F
|
||||
|
||||
// Gradiente en jsPDF se simula con pasos (ver pdf-sections-roi.ts)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Reglas de uso — DO / DON'T
|
||||
|
||||
### DO ✅
|
||||
- Usar `bg-primary` / `text-primary` para todos los CTAs — hereda el naranja de `--primary`
|
||||
- Usar gradiente identidad en exactamente 1 KPI Hero por página/vista
|
||||
- Usar `font-mono` para todos los números financieros
|
||||
- Escribir siempre **InQ** con I-n-Q
|
||||
|
||||
### DON'T ❌
|
||||
- Usar `bg-blue-*` donde debería ir naranja InQ
|
||||
- Aplicar el gradiente en más de un elemento por vista
|
||||
- Usar colores de CONCILIA (`#572FA2`, `#CB1889`)
|
||||
- Cambiar los colores del heatmap sin recalibrar los tests E2E
|
||||
|
||||
---
|
||||
|
||||
*Actualizado: Sprint 1.5 Etapa 1 — 2026-05-16*
|
||||
2
TODO.md
2
TODO.md
@@ -31,6 +31,8 @@
|
||||
|
||||
- [ ] **Indicador visual en el reporte de actividades automatable** (borde punteado o ícono diferenciador): en Sprint 1 se usa solo leyenda de texto. Evaluar si el cliente necesita más claridad visual al comparar Actual vs Automatizado.
|
||||
|
||||
- [ ] **Sprint 3-4: revisar paleta del heatmap** (verde/ámbar/rojo saturados vs. pasteles). Los colores saturados actuales (`#10B981`, `#F59E0B`, `#EF4444`) funcionan bien en pantallas grandes de talleres. El brief de Sprint 1.5 propone pasteles más "consultivos" (`#BBF7D0`, `#FED7AA`, `#FECACA`), pero el cambio requiere recalibrar los tests E2E de análisis de píxeles (umbrales de verde/ámbar/rojo). Hacer con feedback real de uso en talleres InQuality.
|
||||
|
||||
- [ ] **Columna "Eficiencia de automatización" en ComparisonTable**: métrica = `(ahorro$ × probabilidad) / inversión-prorrateada`. Permite rankear actividades por "qué tan valiosa es automatizar cada una" en lugar de solo "cuánto cuestan". Útil en conversaciones de pre-venta donde el cliente quiere priorizar qué automatizar primero.
|
||||
|
||||
## Baja prioridad / Fase 2
|
||||
|
||||
90
etapa-1-audit.md
Normal file
90
etapa-1-audit.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Auditoría de colores — Etapa 1 Sprint 1.5
|
||||
|
||||
> Hallazgos del audit de azules, hardcodes y `primary` en el código fuente.
|
||||
> **No se resuelven en Etapa 1.** Las acciones se ejecutan en Etapas 3 (Web App) y 4-8 (PDFs).
|
||||
>
|
||||
> Fecha: 2026-05-16 · Ejecutado por: Claude Code
|
||||
> Comandos: `grep -rn "blue|sky|indigo|3B82F6|2563EB" src/` + `grep -rn "#[0-9a-fA-F]{6}" src/`
|
||||
|
||||
---
|
||||
|
||||
## Categorías
|
||||
|
||||
- **Migrar a InQ orange**: color azul que debería ser naranja de marca
|
||||
- **Mantener azul funcional**: azul donde es convención semántica (info, links, paralelo AND)
|
||||
- **Migrar a neutral**: azul accidental que debería ser slate/gray
|
||||
- **Migrar a token**: hex hardcodeado que tiene un token equivalente en tailwind.config.js
|
||||
|
||||
---
|
||||
|
||||
## Hallazgos — Azules en clases Tailwind
|
||||
|
||||
| Archivo:línea | Clase actual | Categoría | Acción sugerida |
|
||||
|---|---|---|---|
|
||||
| `GatewayPanel.tsx:122` | `bg-blue-50 border-blue-200` | **Mantener azul funcional** | El azul en gateways AND paralelos es convención visual (flujo paralelo = azul). Evaluar en Sprint 2 si cambiar a slate-50 sin perder semántica. |
|
||||
| `GatewayPanel.tsx:124` | `text-blue-500` | **Mantener azul funcional** | Ídem — ícono Info en bloque paralelo |
|
||||
| `GatewayPanel.tsx:126-127` | `text-blue-800`, `text-blue-700` | **Mantener azul funcional** | Texto del bloque informativo de gateway AND |
|
||||
| `GatewayPanel.tsx:144` | `text-blue-600` | **Mantener azul funcional** | "100%" en gateway paralelo — valor fijo, semántica coherente |
|
||||
| `ResourcesPanel.tsx:22` | `bg-blue-100 text-blue-700` (rol "role") | **Migrar a neutral** | Badge de tipo "role" no tiene razón de ser azul. Migrar a slate o usar color propio del sistema de recursos. Etapa 3. |
|
||||
|
||||
## Hallazgos — `PDF.blue` en exportación
|
||||
|
||||
| Archivo:línea | Color actual | Categoría | Acción sugerida |
|
||||
|---|---|---|---|
|
||||
| `pdf-sections.ts:9` | `blue: [30, 64, 175]` (`#1E40AF`) | **Migrar a InQ orange** | Header de tabla PDF usa azul corporativo. Reemplazar por naranja InQ `[245, 152, 69]` (`#F59845`) en Etapa 4 (PDF: header y footer). |
|
||||
| `pdf-sections.ts:112` | `PDF.blue` en KPI card accent | **Migrar a InQ orange** | El KPI "Costo total" usa azul como accent. Cambiar a naranja InQ en Etapa 6 (PDF: rediseño página 1). |
|
||||
| `pdf-export.ts:120` | `fillColor: PDF.blue` en autotable | **Migrar a InQ orange** | Header de tabla de costos en azul. Migrar en Etapa 7 (PDF: páginas 3-4). |
|
||||
| `pdf-sections-roi.ts:203` | `fillColor: PDF.blue` en autotable | **Migrar a InQ orange** | Header de tabla comparativa ROI. Migrar en Etapa 7. |
|
||||
|
||||
## Hallazgos — Hex hardcodes en componentes React
|
||||
|
||||
| Archivo:línea | Hex | Descripción | Categoría | Acción sugerida |
|
||||
|---|---|---|---|---|
|
||||
| `BpmnCanvas.tsx:24` | `#f59e0b` | Stroke del ícono Bot en SVG inline | **Migrar a InQ orange** | En Etapa 9 el badge ⚡ cambia a fondo naranja sólido `#F59845`. El stroke del SVG se rediseña en esa etapa. |
|
||||
| `BpmnCanvas.tsx:40` | `#fffbeb` | Fondo del badge Bot (amber-50) | **Migrar a InQ orange** | Reemplazar por `var(--inq-orange-lighter)` `#FFF8ED` en Etapa 9. |
|
||||
| `BpmnCanvas.tsx:41` | `#e2e8f0` | Borde del badge Bot | **Mantener neutral** | Borde sutil, está bien como slate-200. |
|
||||
| `CumulativeSavingsChart.tsx:32,34` | `#10b981` | Color del marker de payback | **Migrar a token** | Verde éxito = `var(--color-success)` `#16A34A`. Migrar en Etapa 3. |
|
||||
| `CumulativeSavingsChart.tsx:55` | `#10b981`, `#ef4444` | Colores del tooltip (positivo/negativo) | **Migrar a token** | Usar `--color-success` y `--color-danger`. Etapa 3. |
|
||||
| `CumulativeSavingsChart.tsx:91,102` | `#3b82f6` | Línea y punto del chart acumulado | **Migrar a InQ orange** | La línea del gráfico de trayectoria debería ser naranja InQ `#F59845` para coherencia de marca. Etapa 3. |
|
||||
| `HeatmapCanvas.tsx:118` | `#f8fafc` | Background del canvas | **Mantener neutral** | slate-50 es correcto para fondo del diagrama BPMN. |
|
||||
| `TopSavingsChart.tsx:73,79` | `#10b981` | Barras y labels del chart | **Migrar a token** | Verde éxito correcto. Usar `--color-success` vía `style={{ color: 'var(--color-success)' }}`. Etapa 3. |
|
||||
| `HeatmapLegend.tsx:24` | `#10b981`, `#f59e0b`, `#ef4444` | Gradiente de la leyenda del heatmap | **Migrar a token** | Usar constantes exportadas de `colors.ts` o tokens `heatmap.*`. Etapa 3. |
|
||||
| `chart-options.ts:12` | `#3b82f6` (role) | Color del tipo de recurso "role" | **Migrar a neutral** | El azul para "roles" no es marca InQ. Evaluar paleta diferenciadora de tipos en Sprint 2. |
|
||||
| `chart-options.ts:12` | `#8b5cf6` (system) | Color del tipo "system" | **Mantener azul funcional** | Violeta para sistemas es una convención razonable. Evaluar en Sprint 2. |
|
||||
| `chart-options.ts:123` | `#3b82f6` | Costo directo en donut chart | **Migrar a InQ orange** | El donut de composición directo/overhead debería usar naranja InQ. Etapa 3. |
|
||||
| `chart-options.ts:57,69,211,224` | `#f1f5f9`, `#e2e8f0` | Grid lines y ejes de charts | **Mantener neutral** | slate-100/200 son correctos para UI de soporte. |
|
||||
| `chart-options.ts:63,107,209` | `#475569` | Labels de ejes | **Mantener neutral** | slate-600, correcto. |
|
||||
| `chart-options.ts:78,217,237` | `#64748b`, `#94a3b8` | Labels secundarios | **Mantener neutral** | slate-500/400, correctos. |
|
||||
| `chart-options.ts:136` | `#1e293b` | Fill del label de total en donut | **Mantener neutral** | slate-800, correcto para texto. |
|
||||
|
||||
## Hallazgos — `primary` en JSX
|
||||
|
||||
| Archivo | Usos | Evaluación |
|
||||
|---|---|---|
|
||||
| `router.tsx`, `WorkspacePage.tsx` | `text-primary` spinner | ✅ Correcto — spinner naranja InQ ahora |
|
||||
| `ResourcesPanel.tsx:101` | `border-primary/20 bg-primary/5` | ✅ Correcto — borde/fondo naranja sutil |
|
||||
| `RoiKpiBar.tsx:88-89` | `text-primary`, `bg-primary/10` | ✅ Correcto — ícono Calendar naranja |
|
||||
| `KpiBar.tsx:46-47` | `text-primary`, `bg-primary/10` | ✅ Correcto — ícono DollarSign naranja |
|
||||
| `ActivitiesTable.tsx:22-23` | `text-primary` arrows | ✅ Correcto — flechas de ordenamiento naranjas |
|
||||
| `ActivitiesTable.tsx:96` | `bg-primary/5 ring-primary/20` | ✅ Correcto — highlight de fila naranja |
|
||||
| `ImportPage.tsx:173,198-199,205,210-211,252,255-258` | `text-primary`, `bg-primary/*`, `border-primary` | ✅ Correcto — AccentS de la landing page naranjas |
|
||||
| `SampleProcessLoader.tsx:77,83-84,92` | `hover:border-primary/30`, `bg-primary/10`, `text-primary` | ✅ Correcto |
|
||||
| `WorkspacePage.tsx:178,243` | `text-primary border-primary/30`, `bg-primary` | ✅ Correcto |
|
||||
| `slider.tsx` | `bg-primary/20`, `bg-primary`, `border-primary/50` | ✅ Correcto — slider naranja |
|
||||
| `tooltip.tsx` | `bg-primary text-primary-foreground` | ✅ Correcto — tooltip naranja |
|
||||
| `switch.tsx` | `bg-primary` when checked | ✅ Correcto — switch naranja |
|
||||
| `button.tsx` | `bg-primary text-primary-foreground` default | ✅ Correcto — botón naranja |
|
||||
| `badge.tsx` | `bg-primary text-primary-foreground` | ✅ Correcto — badge naranja |
|
||||
|
||||
---
|
||||
|
||||
## Resumen de acciones pendientes
|
||||
|
||||
| Etapa | Archivos afectados | Acción |
|
||||
|---|---|---|
|
||||
| Etapa 3 (Web App) | `CumulativeSavingsChart.tsx`, `TopSavingsChart.tsx`, `HeatmapLegend.tsx`, `chart-options.ts` | Migrar hex a tokens CSS/constantes |
|
||||
| Etapa 4-8 (PDFs) | `pdf-sections.ts`, `pdf-export.ts`, `pdf-sections-roi.ts` | Reemplazar `PDF.blue` por array naranja InQ |
|
||||
| Etapa 9 (Badge ⚡) | `BpmnCanvas.tsx` | Rediseño completo del badge a naranja sólido |
|
||||
| Sprint 2 | `ResourcesPanel.tsx`, `GatewayPanel.tsx`, `chart-options.ts` | Evaluar paleta de tipos de recurso y gateways |
|
||||
|
||||
**No se toca nada de lo anterior en Etapa 1.**
|
||||
0
sprints/sprint-1-5/ETAPA_2_PROMPT.md
Normal file
0
sprints/sprint-1-5/ETAPA_2_PROMPT.md
Normal file
@@ -26,7 +26,7 @@ const TabsTrigger = React.forwardRef<
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',
|
||||
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-inq-orange data-[state=active]:shadow data-[state=active]:font-semibold',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -9,14 +9,19 @@
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* ── Shadcn/ui tokens — primary cambiado a InQ Orange ─────────────────
|
||||
Antes: azul (221.2 83.2% 53.3%).
|
||||
Ahora: naranja InQ #F59845 ≈ HSL(28, 90%, 62%).
|
||||
Esto actualiza automáticamente Button default, Switch checked,
|
||||
Tabs ring, Slider y cualquier componente que use bg-primary/text-primary. */
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--primary: 221.2 83.2% 53.3%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--primary: 28 90% 62%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
@@ -27,8 +32,25 @@
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 221.2 83.2% 53.3%;
|
||||
--ring: 28 90% 62%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* ── InQ ROI brand variables ─────────────────────────────────────────
|
||||
Para uso en CSS inline, SVG y contextos donde Tailwind no aplica.
|
||||
En componentes React, preferir las clases Tailwind (bg-inq-orange, etc.) */
|
||||
--inq-orange: #F59845;
|
||||
--inq-orange-dark: #B45309;
|
||||
--inq-orange-light: #FEF3E2;
|
||||
--inq-orange-lighter: #FFF8ED;
|
||||
--inq-magenta: #ED3E8F;
|
||||
|
||||
/* ── Semánticos ──────────────────────────────────────────────────────*/
|
||||
--color-success: #16A34A;
|
||||
--color-success-light: #F0FDF4;
|
||||
--color-warning: #F59E0B;
|
||||
--color-warning-bg: #FFFBEB;
|
||||
--color-danger: #EF4444;
|
||||
--color-danger-light: #FEE2E2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,35 @@ export default {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
// ── InQ ROI brand tokens ──────────────────────────────────────────
|
||||
// Uso: bg-inq-orange, bg-inq-orange-dark, bg-inq-magenta, etc.
|
||||
// El gradiente identidad (#F59845 → #ED3E8F) se usa SOLO en KPI Hero
|
||||
// y banners principales. NUNCA en bordes ni fondos secundarios.
|
||||
inq: {
|
||||
orange: {
|
||||
DEFAULT: '#F59845',
|
||||
dark: '#B45309',
|
||||
light: '#FEF3E2',
|
||||
lighter: '#FFF8ED',
|
||||
},
|
||||
magenta: '#ED3E8F',
|
||||
},
|
||||
// ── Heatmap (saturado, calibrado para análisis de píxeles E2E) ──
|
||||
// DEBE coincidir con HEATMAP_LOW/MID/HIGH en src/lib/colors.ts.
|
||||
// Cambiar solo en conjunto con recalibración de tests E2E.
|
||||
heatmap: {
|
||||
low: '#10b981',
|
||||
mid: '#f59e0b',
|
||||
high: '#ef4444',
|
||||
low: '#10B981',
|
||||
mid: '#F59E0B',
|
||||
high: '#EF4444',
|
||||
},
|
||||
// ── Semánticos ───────────────────────────────────────────────────
|
||||
success: {
|
||||
DEFAULT: '#16A34A',
|
||||
light: '#F0FDF4',
|
||||
},
|
||||
warning: {
|
||||
DEFAULT: '#F59E0B',
|
||||
bg: '#FFFBEB',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
|
||||
49
tests/design-system/tokens.test.ts
Normal file
49
tests/design-system/tokens.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Tests del sistema de diseño InQ ROI — Sprint 1.5.
|
||||
*
|
||||
* Verifican que los tokens de marca estén correctamente definidos en
|
||||
* tailwind.config.js y que no haya contaminación de la marca hermana CONCILIA.
|
||||
*
|
||||
* Estos tests son la fuente de verdad del contrato de marca: si cambiás
|
||||
* un token, el test falla y te fuerza a ser explícito con el cambio.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest'
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const tailwindConfig = require('../../tailwind.config.js').default ?? require('../../tailwind.config.js')
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const colors = (tailwindConfig.theme.extend.colors) as Record<string, any>
|
||||
|
||||
describe('Design tokens — paleta InQ ROI', () => {
|
||||
it('expone tokens de marca InQ con estructura anidada correcta', () => {
|
||||
const inq = colors.inq
|
||||
|
||||
expect(inq.orange.DEFAULT).toBe('#F59845')
|
||||
expect(inq.orange.dark).toBe('#B45309')
|
||||
expect(inq.orange.light).toBe('#FEF3E2')
|
||||
expect(inq.orange.lighter).toBe('#FFF8ED')
|
||||
expect(inq.magenta).toBe('#ED3E8F')
|
||||
})
|
||||
|
||||
it('NO incluye los colores de CONCILIA (marca hermana, no mezclar)', () => {
|
||||
const configStr = JSON.stringify(tailwindConfig)
|
||||
|
||||
// Morado primario de CONCILIA
|
||||
expect(configStr).not.toContain('#572FA2')
|
||||
expect(configStr).not.toContain('#572fa2')
|
||||
|
||||
// Magenta de CONCILIA
|
||||
expect(configStr).not.toContain('#CB1889')
|
||||
expect(configStr).not.toContain('#cb1889')
|
||||
})
|
||||
|
||||
it('expone tokens del heatmap saturado (calibrado para tests E2E)', () => {
|
||||
const heatmap = colors.heatmap
|
||||
|
||||
// Valores en mayúscula: #10B981, #F59E0B, #EF4444
|
||||
// Deben coincidir con HEATMAP_LOW/MID/HIGH en src/lib/colors.ts
|
||||
expect(heatmap.low).toBe('#10B981')
|
||||
expect(heatmap.mid).toBe('#F59E0B')
|
||||
expect(heatmap.high).toBe('#EF4444')
|
||||
})
|
||||
})
|
||||
65
tests/e2e/screenshots-etapa-1.spec.ts
Normal file
65
tests/e2e/screenshots-etapa-1.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Screenshots de validación visual — Etapa 1 Sprint 1.5.
|
||||
*
|
||||
* Captura 3 vistas que muestran la identidad InQ aplicada:
|
||||
* 1. workspace.png — CTAs naranjas, Simular button, tabs
|
||||
* 2. report-tabs.png — tab activo naranja en el reporte
|
||||
* 3. switch-on.png — switch de automatización en estado ON naranja
|
||||
*
|
||||
* Estos screenshots son evidencia de que el cambio de --primary a naranja
|
||||
* se ve correctamente en la aplicación real.
|
||||
*/
|
||||
import { test } from '@playwright/test'
|
||||
import { resolve } from 'path'
|
||||
import { mkdirSync } from 'fs'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
||||
const BPMN_DIR = resolve(__dirname, '../../public/sample-processes')
|
||||
const OUT_DIR = resolve(__dirname, '../screenshots/etapa-1')
|
||||
|
||||
test.beforeAll(() => { mkdirSync(OUT_DIR, { recursive: true }) })
|
||||
|
||||
test('screenshot workspace — CTAs naranjas visibles', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await page.locator('#bpmn-file-input').setInputFiles(resolve(BPMN_DIR, 'simple-linear.bpmn'))
|
||||
await page.waitForURL(/\/workspace\//, { timeout: 15_000 })
|
||||
await page.waitForSelector('button:has-text("Simular")', { timeout: 10_000 })
|
||||
await page.waitForTimeout(1_000)
|
||||
|
||||
await page.screenshot({ path: resolve(OUT_DIR, 'workspace.png'), fullPage: false })
|
||||
})
|
||||
|
||||
test('screenshot switch ON — switch de automatización naranja', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await page.locator('#bpmn-file-input').setInputFiles(resolve(BPMN_DIR, 'simple-linear.bpmn'))
|
||||
await page.waitForURL(/\/workspace\//, { timeout: 15_000 })
|
||||
await page.waitForSelector('button:has-text("Simular")', { timeout: 10_000 })
|
||||
await page.waitForTimeout(1_500)
|
||||
|
||||
// Hacer click en el primer task del BPMN para abrir el ActivityPanel
|
||||
await page.locator('[data-element-id="task1"]').first().click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Encender el switch de automatización
|
||||
const toggle = page.getByRole('switch', { name: /automatizable/i })
|
||||
await toggle.click()
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
await page.screenshot({ path: resolve(OUT_DIR, 'switch-on.png'), fullPage: false })
|
||||
})
|
||||
|
||||
test('screenshot report-tabs — tab activo naranja', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await page.locator('#bpmn-file-input').setInputFiles(resolve(BPMN_DIR, 'medium-with-gateways.bpmn'))
|
||||
await page.waitForURL(/\/workspace\//, { timeout: 15_000 })
|
||||
await page.waitForSelector('button:has-text("Simular")', { timeout: 10_000 })
|
||||
await page.waitForTimeout(1_500)
|
||||
|
||||
const simBtn = page.getByRole('button', { name: 'Simular' })
|
||||
await simBtn.click()
|
||||
await page.waitForURL(/\/report\//, { timeout: 20_000 })
|
||||
await page.waitForSelector('button:has-text("Exportar PDF")', { timeout: 20_000 })
|
||||
|
||||
await page.screenshot({ path: resolve(OUT_DIR, 'report-tabs.png'), fullPage: false })
|
||||
})
|
||||
21
tests/lib/format-payback.test.ts
Normal file
21
tests/lib/format-payback.test.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Tests de formatPayback — Sprint 1.5 Etapa 2.
|
||||
*
|
||||
* Stubs preparados. La implementación se agrega en Etapa 2.
|
||||
* Los 7 casos están definidos en SPRINT_1_5_BRIEF_REDISENIO_VISUAL.md § 3.4.
|
||||
*
|
||||
* Regla: un payback de "0.0 meses" (como mostraba el sistema con costos
|
||||
* artificialmente bajos) es confuso. formatPayback resuelve esto con
|
||||
* una escala legible para el consultor y el cliente.
|
||||
*/
|
||||
import { describe, it } from 'vitest'
|
||||
|
||||
describe('formatPayback', () => {
|
||||
it.todo('0 → "Inmediato" (inversión cero con ahorro positivo)')
|
||||
it.todo('0.05 → "< 1 día" (payback de horas, prácticamente instantáneo)')
|
||||
it.todo('0.5 → "< 1 mes (0.50 meses)"')
|
||||
it.todo('6 → "6.0 meses"')
|
||||
it.todo('15 → "15.0 meses (~1.3 años)"')
|
||||
it.todo('30 → "2.5 años"')
|
||||
it.todo('Infinity → "No recupera en horizonte"')
|
||||
})
|
||||
BIN
tests/screenshots/etapa-1/report-tabs.png
Normal file
BIN
tests/screenshots/etapa-1/report-tabs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
tests/screenshots/etapa-1/switch-on.png
Normal file
BIN
tests/screenshots/etapa-1/switch-on.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
BIN
tests/screenshots/etapa-1/workspace.png
Normal file
BIN
tests/screenshots/etapa-1/workspace.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Reference in New Issue
Block a user