All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m12s
- 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"
151 lines
3.8 KiB
TypeScript
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)
|
|
}
|