Files
cataRio/nuxt4/app/utils/pdf/pdfLayout.ts
josedario87 701d0c8fdb
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 2m51s
feat: Agregar exportación PDF del formulario de catación EVC-IH01
- Implementar módulo de generación PDF con jsPDF
- Crear composable usePdfExport para exportar muestras y sesiones
- Añadir botones de exportación PDF en header y por muestra
- Replicar layout exacto del formulario físico IHCAFE
- Soportar máximo 3 formularios por hoja carta
2025-11-24 17:20:49 -06:00

224 lines
5.2 KiB
TypeScript

/**
* Constantes y configuración del layout para el formulario PDF EVC-IH01
* Tamaño: Carta (Letter) - 8.5" x 11" (215.9mm x 279.4mm)
* Máximo 3 formularios por página
*/
export const PDF_CONFIG = {
// Página Carta (Letter)
pageWidth: 215.9, // mm (8.5")
pageHeight: 279.4, // mm (11")
// Márgenes
marginTop: 8,
marginBottom: 8,
marginLeft: 8,
marginRight: 8,
// Formulario individual (3 por página)
formHeight: 85, // ~85mm cada formulario
formWidth: 199.9, // pageWidth - marginLeft - marginRight
formSpacing: 2, // Espacio entre formularios
// Tipografía
fontSize: {
title: 9,
header: 7,
body: 6,
small: 5,
tiny: 4.5,
},
// Colores
colors: {
black: '#000000',
gray: '#666666',
lightGray: '#CCCCCC',
},
// Grosor de líneas
lineWidth: {
thin: 0.1,
normal: 0.2,
thick: 0.4,
},
// Tamaño de checkbox
checkboxSize: 2.5,
checkboxSpacing: 0.8,
} as const
/**
* Calcula la posición Y inicial para un formulario según su posición en la página
* @param posicion - Posición del formulario (0, 1, o 2)
* @returns Coordenada Y inicial en mm
*/
export function calcularYInicio(posicion: 0 | 1 | 2): number {
const { marginTop, formHeight, formSpacing } = PDF_CONFIG
return marginTop + posicion * (formHeight + formSpacing)
}
/**
* Secciones del formulario con sus posiciones relativas
*/
export const FORM_SECTIONS = {
// Encabezado
header: {
y: 0,
height: 10,
},
// Tabla de intensidades (lado izquierdo)
intensidades: {
x: 0,
y: 10,
width: 48,
height: 32,
},
// Fragancia-Aroma (centro-derecha superior)
fraganciaAroma: {
x: 48,
y: 10,
width: 76,
height: 18,
},
// Notas Fragancia-Aroma (derecha superior)
notasFragancia: {
x: 124,
y: 10,
width: 75.9,
height: 18,
},
// Sabores (centro-derecha medio)
sabores: {
x: 48,
y: 28,
width: 76,
height: 14,
},
// Notas Sabores (derecha medio)
notasSabor: {
x: 124,
y: 28,
width: 75.9,
height: 14,
},
// Sensación en boca y gustos
sensacionGustos: {
x: 48,
y: 42,
width: 151.9,
height: 12,
},
// Tazas y defectos
tazasDefectos: {
x: 0,
y: 54,
width: 199.9,
height: 12,
},
// Otras notas
otrasNotas: {
x: 0,
y: 66,
width: 199.9,
height: 8,
},
// Sub total
subTotal: {
x: 0,
y: 74,
width: 199.9,
height: 10,
},
} as const
/**
* Nombres de los parámetros de intensidad para la tabla
*/
export const PARAMETROS_INTENSIDAD = [
{ key: 'fragancia', label: 'Fragancia' },
{ key: 'aroma', label: 'Aroma' },
{ key: 'sabor', label: 'Sabor' },
{ key: 'saborResidual', label: 'Sabor Residual' },
{ key: 'acidez', label: 'Acidez' },
{ key: 'dulzor', label: 'Dulzor' },
{ key: 'sensacionBoca', label: 'Sensación Boca' },
{ key: 'impresionGlobal', label: 'Impresión Global' },
] as const
/**
* Tipo para categoría de nota en PDF
*/
export interface CategoriaPdf {
key: string
label: string
indent?: boolean
}
/**
* Categorías de notas para el formulario PDF
* Columna izquierda y derecha de checkboxes
*/
export const CATEGORIAS_PDF: {
columnaIzquierda: CategoriaPdf[]
columnaDerecha: CategoriaPdf[]
} = {
columnaIzquierda: [
{ key: 'Floral', label: 'Floral' },
{ key: 'Afrutado', label: 'Afrutado' },
{ key: 'Bayas', label: 'Bayas', indent: true },
{ key: 'Ácido', label: 'Ácido', indent: true },
{ key: 'Frutas Deshidratadas', label: 'Frutas Deshid.', indent: true },
{ key: 'Fermentado', label: 'Fermentado', indent: true },
{ key: 'Cítricos', label: 'Cítricos' },
{ key: 'Verde Vegetal', label: 'Verde/Vegetal' },
{ key: 'Químico', label: 'Químico' },
{ key: 'Humedad/Tierra', label: 'Humedad/Tierra' },
{ key: 'Madera', label: 'Madera' },
],
columnaDerecha: [
{ key: 'Tostado', label: 'Tostado' },
{ key: 'Cereal', label: 'Cereal', indent: true },
{ key: 'Quemado', label: 'Quemado', indent: true },
{ key: 'Tabaco', label: 'Tabaco', indent: true },
{ key: 'Nueces/Cacao', label: 'Nueces/Cacao' },
{ key: 'Nueces', label: 'Nueces', indent: true },
{ key: 'Cacao', label: 'Cacao', indent: true },
{ key: 'Especias', label: 'Especias' },
{ key: 'Dulce', label: 'Dulce' },
{ key: 'Vainilla', label: 'Vainilla', indent: true },
{ key: 'Azúcar Morena', label: 'Azúcar Morena', indent: true },
],
}
/**
* Sensaciones en boca para el formulario PDF
*/
export const SENSACIONES_PDF = [
{ key: 'Áspero', label: 'Áspero (Arenoso, Rugoso, Rasposo)' },
{ key: 'Aceitoso', label: 'Aceitoso' },
{ key: 'Metálico', label: 'Metálico' },
{ key: 'Suave', label: 'Suave (Aterciopelado, Sedoso)' },
{ key: 'Deja seca la boca', label: 'Deja seca la boca (Astringente)' },
] as const
/**
* Gustos predominantes para el formulario PDF
*/
export const GUSTOS_PDF = [
{ key: 'Salado', label: 'Salado' },
{ key: 'Amargo', label: 'Amargo' },
{ key: 'Ácido', label: 'Ácido' },
{ key: 'Dulce', label: 'Dulce' },
{ key: 'Umami', label: 'Umami' },
] as const
/**
* Defectos para el formulario PDF
*/
export const DEFECTOS_PDF = [
{ key: 'Mohoso', label: 'Mohoso' },
{ key: 'Fenólico', label: 'Fenólico' },
{ key: 'Papa', label: 'Papa' },
] as const