# Sprint 1.5 — Etapa 4: PDF — Header y footer compartidos > **Objetivo:** refactor estructural de los headers y footers de PDFs. Crear módulo compartido que aplique identidad InQ consistente en los 3 PDFs (Actual, Automatizado, ROI). Aplicar paleta naranja InQ a elementos de marca. NO rediseñar layout de contenido — eso es Etapa 5+. > > **Pre-requisitos:** Etapas 1, 2 y 3 cerradas. Sistema de diseño con tokens InQ disponible. Web app con identidad InQ aplicada. > > **Etapa siguiente:** Etapa 5 — PDF: layout híbrido portrait + landscape (la página BPMN pasa a horizontal). --- ## 1. Alcance estricto de Etapa 4 ### Sí entra - ✅ Crear módulo compartido `pdf-sections-shared.ts` con `drawHeader` y `drawFooter` reutilizables - ✅ Refactorizar los 3 PDFs existentes (Actual, Automatizado, ROI) para usar el módulo compartido - ✅ Aplicar paleta naranja InQ en: - Border-bottom del header (color naranja `#F59845`, grosor variable según página) - Logo "InQ ROI" en color naranja en cada header - "Powered by InQuality" en color slate-500 en cada footer - ✅ Reemplazar `PDF.blue` por `PDF.inqOrange` en headers de tablas autotable (de pdf-sections.ts, pdf-export.ts, pdf-sections-roi.ts según audit Etapa 1) - ✅ Quitar versión "v0.1.0" del footer del PDF (decisión de Etapa 3 — la versión se queda solo en web app) - ✅ Tests E2E confirman que los 3 PDFs siguen generándose correctamente con la nueva estructura ### NO entra - ❌ Cambio de orientación de páginas (Etapa 5) - ❌ Rediseño de página 1 ROI con KPI Hero gradiente (Etapa 6) - ❌ Tabla comparativa rediseñada con paleta (Etapa 7) - ❌ Top 3 ahorros en página 1 ROI (Etapa 6) - ❌ Sección Transparencia rediseñada (Etapa 7) - ❌ Modificar el contenido de cualquier página más allá del header/footer **Si encontrás algo que parece "natural" agregar pero no está en "Sí entra", PARÁ y consultá. Aplicá la política de iniciativa proactiva de CLAUDE.md.** --- ## 2. Decisiones ya tomadas (no consultar de nuevo) | Decisión | Justificación | |---|---| | Logo "InQ ROI" en header de cada página | Brief sección 2.6, ya aplicado en Etapa 2 | | "Powered by InQuality" en footer de cada página | Regla de marca CLAUDE.md, ya aplicado en Etapa 2 | | Border-bottom 3px naranja en página 1, 2px en páginas siguientes | Brief sección 2.6 | | Quitar versión del PDF (mantener solo en web) | Decisión de Etapa 3 | | Color naranja InQ `#F59845` para elementos de marca | Manual de marca Etapa 1 | | Mantener fuente actual (Roboto o equivalente) | No cambiar de fuente en esta etapa | | Caracteres especiales (✓, ⚡, ⚠) reemplazados por equivalentes ASCII si la fuente no soporta | Decisión Etapa 2 — se mantiene | --- ## 3. Estructura del módulo compartido ### 3.1 Archivo nuevo: `src/lib/export/pdf-sections-shared.ts` Debe exportar al menos estas dos funciones: ```typescript import type { jsPDF } from 'jspdf'; export interface PdfHeaderOptions { pageNumber: number; // 1, 2, 3... totalPages: number; // necesario para "Página X de Y" productName: string; // "InQ ROI" sectionTitle?: string; // ej. "Análisis de retorno de inversión" clientName?: string; // ej. "Banco Atlántico S.A." processName?: string; // ej. "medium-with-gateways" simulatedAt: Date; // fecha de simulación } export interface PdfFooterOptions { pageNumber: number; totalPages: number; productName: string; // "InQ ROI" clientName?: string; simulatedAt: Date; } /** * Dibuja el header en la posición actual del documento. * - Página 1: border-bottom 3px naranja * - Otras páginas: border-bottom 2px naranja * - Logo "InQ ROI" en naranja InQ (esquina superior izquierda o derecha según diseño) * - Metadata del producto/proceso a la derecha (ver brief sección 2.6) */ export function drawHeader(doc: jsPDF, options: PdfHeaderOptions): void; /** * Dibuja el footer en la posición fija inferior (16-20px del bottom). * - Border-top 0.5px slate-200 * - Izquierda: "InQ ROI · Powered by InQuality · [cliente] · [fecha]" * - Derecha: "Página X de Y" * - NO incluir versión del producto */ export function drawFooter(doc: jsPDF, options: PdfFooterOptions): void; /** * Constantes de paleta para PDFs. */ export const PDF_COLORS = { inqOrange: [245, 152, 69], // #F59845 inqOrangeDark: [180, 83, 9], // #B45309 inqMagenta: [237, 62, 143], // #ED3E8F textPrimary: [15, 23, 42], // #0F172A textSecondary: [71, 85, 105], // #475569 textTertiary: [148, 163, 184], // #94A3B8 borderLight: [226, 232, 240], // #E2E8F0 // ... cualquier otro que necesites } as const; ``` ### 3.2 Eliminar `PDF.blue` del código Buscar todas las ocurrencias y reemplazar por `PDF_COLORS.inqOrange`: ```bash grep -rn "PDF.blue\|PDF\.blue" src/ ``` Archivos afectados según audit Etapa 1: - `pdf-sections.ts:9` (definición de la constante — eliminar) - `pdf-sections.ts:112` (uso en KPI card accent) - `pdf-export.ts:120` (header de tabla autotable) - `pdf-sections-roi.ts:203` (header de tabla comparativa ROI) ### 3.3 Refactorizar los 3 PDFs Los archivos que generan los PDFs deben: 1. Importar `drawHeader`, `drawFooter`, `PDF_COLORS` del módulo compartido 2. Reemplazar el código actual de header/footer por las llamadas al módulo 3. Mantener todo el resto del contenido sin cambios (esto NO es Etapa 5-7) Archivos a refactorizar: - `src/lib/export/pdf-export.ts` (PDFs Actual y Automatizado) - `src/lib/export/pdf-sections-roi.ts` (PDF de Comparación + ROI) - Cualquier helper que genere los PDFs anteriores --- ## 4. Validación visual mandatoria ### 4.1 Antes de declarar etapa completada Generar los 3 PDFs con el setup realista de pruebas y validarlos visualmente: **Setup de referencia:** - Proceso: `medium-with-gateways` - 3 actividades automatizables (`task_recv`, `task_score`, `task_analisis`) - Costos: directos $200, automatizados $20 - Volumetría: 5000/año, 3 años, USD 80.000 inversión **Archivos a generar en `tests/e2e/__output__/`:** - `etapa-4-actual.pdf` - `etapa-4-automatizado.pdf` - `etapa-4-roi.pdf` ### 4.2 Validaciones automatizadas mandatorias Antes de `present_files`, ejecutá y confirmá: ``` Para cada PDF generado: 1. pdf-parse confirma palabras clave en TODAS las páginas: - "InQ ROI" presente - "Powered by InQuality" presente en footer 2. pdf-parse rechaza términos prohibidos: - "Process Cost Platform" — NO debe aparecer - "v0.1.0" — NO debe aparecer en el PDF (solo en web) - "INQ", "Inq", "inq" — NO debe aparecer (regla de marca I-n-Q) 3. Cantidad de páginas: - actual.pdf: 3 páginas - automatizado.pdf: 3 páginas - roi.pdf: 4 páginas 4. Tamaño de cada página: entre 15-80 KB Si alguna queda <15KB: anomalía, investigar antes de presentar 5. Análisis de píxeles del border-bottom del header: - Confirmar presencia de naranja #F59845 (al menos N píxeles) - Ausencia de azul `#1E40AF` (color anterior que migramos) 6. Tests previos verdes: >= 455 ``` Si CUALQUIER validación falla, NO uses `present_files`. Reportá qué falló y esperá instrucciones. ### 4.3 Validación visual del humano Después de las validaciones automatizadas, presentar los 3 PDFs vía `present_files`. El humano va a verificar visualmente: 1. ¿El header tiene logo "InQ ROI" en naranja en las 3 (o 4) páginas? 2. ¿Hay un border-bottom naranja consistente en cada header? 3. ¿El footer dice exactamente "InQ ROI · Powered by InQuality · [cliente] · [fecha]" sin versión? 4. ¿La paginación "Página X de Y" es correcta en cada PDF? 5. ¿Las tablas internas usan headers naranjas en lugar de azules? 6. ¿El contenido de las páginas más allá del header/footer NO cambió respecto a la versión anterior? --- ## 5. Entregables (Definition of Done) ``` [ ] src/lib/export/pdf-sections-shared.ts creado con drawHeader, drawFooter y PDF_COLORS exportados [ ] pdf-export.ts refactorizado para usar el módulo compartido [ ] pdf-sections.ts refactorizado para usar el módulo compartido [ ] pdf-sections-roi.ts refactorizado para usar el módulo compartido [ ] Cero ocurrencias de PDF.blue en grep [ ] Versión "v0.1.0" eliminada del footer de PDFs (mantener en web) [ ] 3 PDFs generados en tests/e2e/__output__/: - etapa-4-actual.pdf (3 páginas) - etapa-4-automatizado.pdf (3 páginas) - etapa-4-roi.pdf (4 páginas) [ ] 6 validaciones automatizadas confirmadas (palabras clave, prohibidos, páginas, tamaño, píxeles naranja, tests previos) [ ] PDFs presentados con present_files [ ] 455 tests previos + nuevos tests del módulo compartido = ~460+ verdes [ ] Tests nuevos para drawHeader y drawFooter (3-5 casos mínimo) [ ] npm run build limpio (sin warnings TS nuevos) [ ] Decisiones tomadas por iniciativa documentadas en reporte (Patrón C.6) ``` --- ## 6. Tests obligatorios ### 6.1 Tests unitarios del módulo compartido Crear `tests/lib/export/pdf-sections-shared.test.ts`: ```typescript describe('PDF shared sections', () => { describe('PDF_COLORS', () => { it('expone inqOrange como array RGB válido', () => { expect(PDF_COLORS.inqOrange).toEqual([245, 152, 69]); }); it('NO incluye colores de CONCILIA', () => { const allColors = JSON.stringify(PDF_COLORS); expect(allColors).not.toContain('87, 47, 162'); // #572FA2 expect(allColors).not.toContain('203, 24, 137'); // #CB1889 }); }); describe('drawHeader', () => { it('dibuja border-bottom 3px en página 1', () => { // mock jsPDF, capturar llamadas, assertions }); it('dibuja border-bottom 2px en página 2+', () => { // ... }); }); describe('drawFooter', () => { it('incluye "InQ ROI" y "Powered by InQuality"', () => { // ... }); it('NO incluye versión del producto', () => { // ... }); }); }); ``` ### 6.2 Tests E2E Adaptar tests E2E existentes para verificar que los 3 PDFs siguen generándose correctamente después del refactor. --- ## 7. Reporte final a entregar Cuando termines, devolveme: 1. **Tabla de archivos modificados/creados** con líneas 2. **Resultado de las validaciones automatizadas** (los 6 puntos del 4.2) 3. **Cantidad final de tests verdes** (esperado 460+) 4. **3 PDFs presentados con `present_files`** para validación visual mía 5. **Hallazgos no esperados** — cualquier cosa que merezca decisión arquitectónica 6. **Decisiones tomadas por iniciativa** — si aplicaste algún cambio Nivel 2 según política de CLAUDE.md, listalo acá. Si encontrás algo Nivel 3, **NO LO HAGAS** y reportalo como propuesta NO arranques Etapa 5 sin mi OK explícito. --- ## 8. Reglas operativas (recordatorios) 1. **No tocar contenido de las páginas más allá del header/footer**. El rediseño de páginas viene en Etapas 5-7. 2. **No cambiar la orientación de ninguna página**. La página BPMN sigue vertical en esta etapa (cambia en Etapa 5). 3. **No agregar features nuevas al PDF**. Esta etapa es refactor + identidad, no nueva funcionalidad. 4. **No racionalizar problemas**. Si una validación automatizada falla, investigar causa raíz. 5. **Política de iniciativa proactiva (CLAUDE.md):** - Cambios Nivel 1 (refactor interno, mejor naming): ejecutar - Cambios Nivel 2 (visible pero reversible): ejecutar y reportar - Cambios Nivel 3 (marca, arquitectura, datos): CONSULTAR antes 6. **Si encontrás contradicción** entre este prompt y la realidad del código (un archivo no está donde decía, un import no resuelve, etc.): **PARÁ y consultá**, no asumas. --- ## 9. Notas sobre dependencia con Etapa 5 Etapa 5 va a cambiar la orientación de la página BPMN a landscape. El módulo `pdf-sections-shared.ts` que crees en esta etapa debe estar preparado para esto: - `drawHeader` y `drawFooter` deben recibir el ancho/alto disponible como parámetros implícitos del `doc` (jsPDF lo provee con `doc.internal.pageSize.getWidth()` y `getHeight()`) - NO hardcodear `pageWidth = 595` (A4 portrait). Si el header se llama desde una página landscape, debe adaptarse al ancho real - Probá esto con un test que llame `drawHeader` en una página landscape mock Esto preserva el contrato del módulo para que Etapa 5 no requiera refactor adicional.