diff --git a/nuxt4/app/utils/pdf/pdfFormulario.ts b/nuxt4/app/utils/pdf/pdfFormulario.ts index eb54411..a832cec 100644 --- a/nuxt4/app/utils/pdf/pdfFormulario.ts +++ b/nuxt4/app/utils/pdf/pdfFormulario.ts @@ -50,11 +50,11 @@ export function renderizarFormulario( renderizarEncabezado(doc, xBase, yBase, muestra) renderizarTablaIntensidades(doc, xBase, yBase + 14, muestra) renderizarSeccionFraganciaAroma(doc, xBase + 55, yBase + 14, muestra) - renderizarSeccionSabores(doc, xBase + 55, yBase + 55, muestra) - renderizarSeccionSensacionGustos(doc, xBase, yBase + 76, muestra) - renderizarSeccionTazasDefectos(doc, xBase, yBase + 96, muestra) - renderizarSeccionOtrasNotas(doc, xBase, yBase + 112, muestra) - renderizarSeccionSubTotal(doc, xBase, yBase + 122, muestra) + renderizarSeccionSabores(doc, xBase + 55, yBase + 49, muestra) // Sabores ahora tiene 34mm igual que Fragancia-Aroma + renderizarSeccionSensacionGustos(doc, xBase, yBase + 84, muestra) + renderizarSeccionTazasDefectos(doc, xBase, yBase + 100, muestra) + renderizarSeccionOtrasNotas(doc, xBase, yBase + 116, muestra) + renderizarSeccionSubTotal(doc, xBase, yBase + 124, muestra) } /** @@ -184,26 +184,26 @@ function renderizarSeccionFraganciaAroma( muestra: Muestra ): void { const width = 144.9 // Ancho total de la sección derecha - const sectionHeight = 41 + const sectionHeight = 34 // Borde de la sección dibujarRectangulo(doc, x, y, width, sectionHeight, PDF_CONFIG.lineWidth.normal) // Header - doc.setFontSize(PDF_CONFIG.fontSize.body) + doc.setFontSize(PDF_CONFIG.fontSize.small) doc.setFont('helvetica', 'bold') - doc.text('Fragancia - Aroma', x + 3, y + 5) + doc.text('Fragancia - Aroma', x + 3, y + 4) // Línea después del header - dibujarLineaHorizontal(doc, x, y + 7, x + width, PDF_CONFIG.lineWidth.thin) + dibujarLineaHorizontal(doc, x, y + 5.5, x + width, PDF_CONFIG.lineWidth.thin) // Determinar qué está seleccionado const categoriasSeleccionadas = muestra.fraganciaAromaNotas.categorias const subcategoriasSeleccionadas = muestra.fraganciaAromaNotas.subcategorias - // Espaciado entre checkboxes (mayor margen vertical) - const checkSpacing = 3.2 - const startY = y + 10 + // Espaciado entre checkboxes (compacto) + const checkSpacing = 2.6 + const startY = y + 8 // Columna izquierda de checkboxes let checkY = startY @@ -228,7 +228,7 @@ function renderizarSeccionFraganciaAroma( }) // Notas específica (sin recuadro, solo texto) - doc.setFontSize(PDF_CONFIG.fontSize.small) + doc.setFontSize(PDF_CONFIG.fontSize.tiny) doc.setFont('helvetica', 'bold') doc.text('Notas:', x + 3, y + sectionHeight - 2) @@ -237,15 +237,15 @@ function renderizarSeccionFraganciaAroma( const notaTruncada = truncarTexto( doc, muestra.fraganciaAromaNotas.notaEspecifica, - width - 25, - PDF_CONFIG.fontSize.small + width - 22, + PDF_CONFIG.fontSize.tiny ) - doc.text(notaTruncada, x + 18, y + sectionHeight - 2) + doc.text(notaTruncada, x + 15, y + sectionHeight - 2) } } /** - * Renderiza la sección de Sabores + * Renderiza la sección de Sabores (exactamente igual a Fragancia-Aroma) */ function renderizarSeccionSabores( doc: jsPDF, @@ -254,50 +254,51 @@ function renderizarSeccionSabores( muestra: Muestra ): void { const width = 144.9 - const sectionHeight = 21 + const sectionHeight = 34 // Mismo tamaño que Fragancia-Aroma // Borde de la sección dibujarRectangulo(doc, x, y, width, sectionHeight, PDF_CONFIG.lineWidth.normal) // Header - doc.setFontSize(PDF_CONFIG.fontSize.body) + doc.setFontSize(PDF_CONFIG.fontSize.small) doc.setFont('helvetica', 'bold') - doc.text('Sabores', x + 3, y + 5) + doc.text('Sabores', x + 3, y + 4) // Línea después del header - dibujarLineaHorizontal(doc, x, y + 7, x + width, PDF_CONFIG.lineWidth.thin) + dibujarLineaHorizontal(doc, x, y + 5.5, x + width, PDF_CONFIG.lineWidth.thin) + // Determinar qué está seleccionado const categoriasSeleccionadas = muestra.saborNotas.categorias const subcategoriasSeleccionadas = muestra.saborNotas.subcategorias - // Checkboxes en una sola fila (solo categorías principales sin subcategorías) - const checkSpacing = 3 - const startY = y + 11 + // Espaciado entre checkboxes (compacto, igual que Fragancia-Aroma) + const checkSpacing = 2.6 + const startY = y + 8 - // Mostrar solo categorías principales - const categoriasPrincipales = [ - { key: 'Floral', label: 'Floral' }, - { key: 'Afrutado', label: 'Afrutado' }, - { key: 'Verde Vegetal', label: 'Verde/Vegetal' }, - { key: 'Otro', label: 'Otra' }, - { key: 'Tostado', label: 'Tostado' }, - { key: 'Nueces/Cacao', label: 'Nueces/Cacao' }, - { key: 'Especias', label: 'Especias' }, - { key: 'Dulce', label: 'Dulce' }, - ] - - let checkX = x + 3 - categoriasPrincipales.forEach((cat) => { + // Columna izquierda de checkboxes (mismas categorías que Fragancia-Aroma) + let checkY = startY + CATEGORIAS_PDF.columnaIzquierda.forEach((cat) => { const isChecked = categoriasSeleccionadas.includes(cat.key as any) || subcategoriasSeleccionadas.includes(cat.key) - dibujarCheckboxConLabel(doc, checkX, startY, cat.label, isChecked) - checkX += 18 + dibujarCheckboxConLabel(doc, x + 3, checkY, cat.label, isChecked, cat.indent) + checkY += checkSpacing }) - // Notas específica de sabor (sin recuadro) - doc.setFontSize(PDF_CONFIG.fontSize.small) + // Columna derecha de checkboxes + checkY = startY + CATEGORIAS_PDF.columnaDerecha.forEach((cat) => { + const isChecked = + categoriasSeleccionadas.includes(cat.key as any) || + subcategoriasSeleccionadas.includes(cat.key) + + dibujarCheckboxConLabel(doc, x + 75, checkY, cat.label, isChecked, cat.indent) + checkY += checkSpacing + }) + + // Notas específica (sin recuadro, solo texto) + doc.setFontSize(PDF_CONFIG.fontSize.tiny) doc.setFont('helvetica', 'bold') doc.text('Notas:', x + 3, y + sectionHeight - 2) @@ -306,15 +307,16 @@ function renderizarSeccionSabores( const notaTruncada = truncarTexto( doc, muestra.saborNotas.notaEspecifica, - width - 25, - PDF_CONFIG.fontSize.small + width - 22, + PDF_CONFIG.fontSize.tiny ) - doc.text(notaTruncada, x + 18, y + sectionHeight - 2) + doc.text(notaTruncada, x + 15, y + sectionHeight - 2) } } /** * Renderiza la sección de Sensación en boca y Gustos predominantes + * Layout horizontal en 2 filas para cada sección */ function renderizarSeccionSensacionGustos( doc: jsPDF, @@ -323,7 +325,7 @@ function renderizarSeccionSensacionGustos( muestra: Muestra ): void { const width = PDF_CONFIG.formWidth - const sectionHeight = 20 + const sectionHeight = 16 // Más compacto con layout horizontal // Borde de la sección dibujarRectangulo(doc, x, y, width, sectionHeight, PDF_CONFIG.lineWidth.normal) @@ -331,45 +333,59 @@ function renderizarSeccionSensacionGustos( // Sección Sensación en boca const sensacionWidth = width * 0.6 - doc.setFontSize(PDF_CONFIG.fontSize.body) + doc.setFontSize(PDF_CONFIG.fontSize.small) doc.setFont('helvetica', 'bold') - doc.text('Sensación en boca', x + 3, y + 5) + doc.text('Sensación en boca', x + 3, y + 4) // Línea divisoria vertical dibujarLineaVertical(doc, x + sensacionWidth, y, y + sectionHeight) - // Checkboxes de sensación con más espacio vertical - const checkSpacing = 3.5 - let checkY = y + 9 + // Sensaciones - Layout horizontal en 2 filas + // Fila 1: Áspero, Aceitoso, Metálico + // Fila 2: Suave, Deja seca la boca + const sensacionesLabels = [ + { key: 'Áspero', label: 'Áspero' }, + { key: 'Aceitoso', label: 'Aceitoso' }, + { key: 'Metálico', label: 'Metálico' }, + { key: 'Suave', label: 'Suave' }, + { key: 'Deja seca la boca', label: 'Astringente' }, + ] - SENSACIONES_PDF.forEach((sens) => { + const checkSpacingX = 40 // Espacio horizontal entre checkboxes + const row1Y = y + 7 + const row2Y = y + 12 + + // Fila 1: primeros 3 + sensacionesLabels.slice(0, 3).forEach((sens, idx) => { const isChecked = muestra.sensacionEnBoca === sens.key + dibujarCheckboxConLabel(doc, x + 3 + idx * checkSpacingX, row1Y, sens.label, isChecked) + }) - // Usar label corto para ahorrar espacio - const labelCorto = - sens.key === 'Deja seca la boca' - ? 'Deja seca la boca (Astringente)' - : sens.key === 'Áspero' - ? 'Áspero (Arenoso, Rugoso)' - : sens.key === 'Suave' - ? 'Suave (Aterciopelado)' - : sens.key - - dibujarCheckboxConLabel(doc, x + 3, checkY, labelCorto, isChecked) - checkY += checkSpacing + // Fila 2: últimos 2 + sensacionesLabels.slice(3).forEach((sens, idx) => { + const isChecked = muestra.sensacionEnBoca === sens.key + dibujarCheckboxConLabel(doc, x + 3 + idx * checkSpacingX, row2Y, sens.label, isChecked) }) // Sección Gustos predominantes doc.setFont('helvetica', 'bold') - doc.text('Gustos predominantes (2)', x + sensacionWidth + 3, y + 5) + doc.text('Gustos predominantes (2)', x + sensacionWidth + 3, y + 4) - // Checkboxes de gustos con más espacio vertical - checkY = y + 9 + // Gustos - Layout horizontal en 2 filas + // Fila 1: Salado, Amargo, Ácido + // Fila 2: Dulce, Umami + const gustosSpacingX = 26 - GUSTOS_PDF.forEach((gusto) => { + // Fila 1: primeros 3 + GUSTOS_PDF.slice(0, 3).forEach((gusto, idx) => { const isChecked = muestra.gustosPredominantes.includes(gusto.key as any) - dibujarCheckboxConLabel(doc, x + sensacionWidth + 3, checkY, gusto.label, isChecked) - checkY += checkSpacing + dibujarCheckboxConLabel(doc, x + sensacionWidth + 3 + idx * gustosSpacingX, row1Y, gusto.label, isChecked) + }) + + // Fila 2: últimos 2 + GUSTOS_PDF.slice(3).forEach((gusto, idx) => { + const isChecked = muestra.gustosPredominantes.includes(gusto.key as any) + dibujarCheckboxConLabel(doc, x + sensacionWidth + 3 + idx * gustosSpacingX, row2Y, gusto.label, isChecked) }) }