Files
cataRio/nuxt4/app/composables/usePdfExport.ts
josedario87 ce460a17c2
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m12s
fix: Ajustes al layout del PDF de catación
- Cambiar a 2 formularios por hoja para más espacio vertical
- Corregir distribución de familias de notas (Floral, Afrutado, Verde/Vegetal, Otra, Tostado, etc.)
- Aumentar margen vertical entre checkboxes
- Corregir "beberse" → "haberse" en sección de defectos
- Alinear checkboxes de defectos bajo el header
- Quitar recuadro de Notas y mostrar solo "Notas: valor"
2025-11-24 17:37:47 -06:00

151 lines
3.8 KiB
TypeScript

/**
* Composable para exportar formularios de catación a PDF
* Genera PDFs en formato EVC-IH01 (formulario físico de IHCAFE)
*/
import { jsPDF } from 'jspdf'
import type { Muestra, SesionCatacion } from '~/types/catacion'
import { renderizarFormulario } from '~/utils/pdf'
const FORMULARIOS_POR_PAGINA = 2
export const usePdfExport = () => {
const exportando = ref(false)
const error = ref<string | null>(null)
/**
* Exporta una muestra individual a PDF
*/
const exportarMuestra = async (
muestra: Muestra,
nombreArchivo?: string
): Promise<void> => {
try {
exportando.value = true
error.value = null
const doc = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'letter',
})
renderizarFormulario(doc, muestra, 0)
const filename =
nombreArchivo || `catacion-${sanitizarNombre(muestra.nombre)}-${Date.now()}.pdf`
doc.save(filename)
} catch (err) {
error.value = err instanceof Error ? err.message : 'Error al exportar PDF'
console.error('Error exportando PDF:', err)
throw err
} finally {
exportando.value = false
}
}
/**
* Exporta toda la sesión a PDF (máximo 3 formularios por página)
*/
const exportarSesion = async (
sesion: SesionCatacion,
nombreArchivo?: string
): Promise<void> => {
try {
exportando.value = true
error.value = null
const doc = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'letter',
})
const muestras = sesion.muestras
muestras.forEach((muestra, index) => {
const posicionEnPagina = index % FORMULARIOS_POR_PAGINA
// Nueva página si es necesario (excepto primera)
if (index > 0 && posicionEnPagina === 0) {
doc.addPage()
}
renderizarFormulario(doc, muestra, posicionEnPagina as 0 | 1 | 2)
})
const filename = nombreArchivo || `catacion-sesion-${sesion.fecha}.pdf`
doc.save(filename)
} catch (err) {
error.value = err instanceof Error ? err.message : 'Error al exportar PDF'
console.error('Error exportando PDF de sesión:', err)
throw err
} finally {
exportando.value = false
}
}
/**
* Exporta muestras seleccionadas a PDF
*/
const exportarMuestrasSeleccionadas = async (
muestras: Muestra[],
nombreArchivo?: string
): Promise<void> => {
try {
exportando.value = true
error.value = null
if (muestras.length === 0) {
throw new Error('No hay muestras seleccionadas para exportar')
}
const doc = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'letter',
})
muestras.forEach((muestra, index) => {
const posicionEnPagina = index % FORMULARIOS_POR_PAGINA
// Nueva página si es necesario (excepto primera)
if (index > 0 && posicionEnPagina === 0) {
doc.addPage()
}
renderizarFormulario(doc, muestra, posicionEnPagina as 0 | 1 | 2)
})
const filename = nombreArchivo || `catacion-seleccion-${Date.now()}.pdf`
doc.save(filename)
} catch (err) {
error.value = err instanceof Error ? err.message : 'Error al exportar PDF'
console.error('Error exportando PDFs seleccionados:', err)
throw err
} finally {
exportando.value = false
}
}
return {
exportando: readonly(exportando),
error: readonly(error),
exportarMuestra,
exportarSesion,
exportarMuestrasSeleccionadas,
}
}
/**
* Sanitiza un nombre para usar como nombre de archivo
*/
function sanitizarNombre(nombre: string): string {
return nombre
.toLowerCase()
.replace(/[^a-z0-9áéíóúñ]/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
.substring(0, 50)
}