fix: export PDF A4 paysage, 1 seule page, taille police dynamique

This commit is contained in:
Manus
2026-06-05 09:12:22 -04:00
parent db96b29c9f
commit 6224328331

View File

@@ -88,32 +88,36 @@ function exportToPdf(
importRecord: ImportRecord, importRecord: ImportRecord,
lines: VentilationLine[] lines: VentilationLine[]
) { ) {
const doc = new jsPDF({ orientation: "portrait", unit: "mm", format: "a4" }); // A4 paysage : 297mm × 210mm
const doc = new jsPDF({ orientation: "landscape", unit: "mm", format: "a4" });
const pageW = 297;
const pageH = 210;
const margin = 14;
// En-tête // En-tête
doc.setFontSize(14); doc.setFontSize(14);
doc.setFont("helvetica", "bold"); doc.setFont("helvetica", "bold");
doc.text("Ventiltion facture FREE PRO", 105, 15, { align: "center" }); doc.text("Ventilation facture FREE PRO", pageW / 2, 14, { align: "center" });
// Date du mois // Date du mois
const [moisStr, anneeStr] = importRecord.moisLabel.split("/"); const [moisStr, anneeStr] = importRecord.moisLabel.split("/");
const dateLabel = `01/${moisStr}/${anneeStr}`; const dateLabel = `01/${moisStr}/${anneeStr}`;
doc.setFontSize(12); doc.setFontSize(11);
doc.text(dateLabel, 105, 22, { align: "center" }); doc.text(dateLabel, pageW / 2, 21, { align: "center" });
// Date d'édition (haut droite) // Date d'édition (haut droite)
const now = new Date(); const now = new Date();
const editDate = `Edité le ${now.toLocaleDateString("fr-FR")} - ${now.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" })}`; const editDate = `Edité le ${now.toLocaleDateString("fr-FR")} - ${now.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" })}`;
doc.setFontSize(9); doc.setFontSize(8);
doc.setFont("helvetica", "normal"); doc.setFont("helvetica", "normal");
doc.text(editDate, 200, 10, { align: "right" }); doc.text(editDate, pageW - margin, 9, { align: "right" });
// Référence pièce // Référence pièce
doc.setFontSize(10); doc.setFontSize(9);
doc.setFont("helvetica", "bold"); doc.setFont("helvetica", "bold");
doc.text("ref_piece", 14, 32); doc.text("ref_piece :", margin, 29);
doc.setFont("helvetica", "normal"); doc.setFont("helvetica", "normal");
doc.text(importRecord.refPiece ?? "", 55, 32); doc.text(importRecord.refPiece ?? "", margin + 25, 29);
// Tableau principal // Tableau principal
const tableData = lines.map((l) => [ const tableData = lines.map((l) => [
@@ -125,21 +129,45 @@ function exportToPdf(
// Total général // Total général
const totalCentimes = lines.reduce((s, l) => s + l.montantCentimes, 0); const totalCentimes = lines.reduce((s, l) => s + l.montantCentimes, 0);
// Calcul dynamique des largeurs pour tenir sur 1 page
const usableW = pageW - margin * 2; // ~269mm
const colStructure = usableW * 0.50; // ~134mm
const colType = usableW * 0.30; // ~81mm
const colMontant = usableW * 0.20; // ~54mm
// Calcul de la taille de police pour tenir sur 1 page
// A4 paysage : ~170mm de hauteur utile (210 - 35 header - 10 footer)
const nbRows = lines.length + 2; // +1 header +1 footer
const availH = pageH - 38 - 12; // zone tableau
const rowH = Math.min(8, Math.floor(availH / nbRows));
const fontSize = rowH >= 7 ? 9 : rowH >= 6 ? 8 : 7;
autoTable(doc, { autoTable(doc, {
startY: 38, startY: 33,
head: [["structure", "Type", "Montant"]], head: [["Structure", "Type", "Montant TTC"]],
body: tableData, body: tableData,
foot: [["Total général", "", formatMontant(totalCentimes)]], foot: [["Total général", "", formatMontant(totalCentimes)]],
styles: { fontSize: 9, cellPadding: 2 }, styles: { fontSize, cellPadding: rowH >= 7 ? 2 : 1.5, overflow: "linebreak" },
headStyles: { fillColor: [255, 255, 255], textColor: [0, 0, 0], fontStyle: "bold", lineWidth: 0.3, lineColor: [0, 0, 0] }, headStyles: {
footStyles: { fillColor: [255, 255, 255], textColor: [0, 0, 0], fontStyle: "bold", lineWidth: 0.3, lineColor: [0, 0, 0] }, fillColor: [255, 255, 255], textColor: [0, 0, 0],
fontStyle: "bold", lineWidth: 0.3, lineColor: [0, 0, 0],
},
footStyles: {
fillColor: [255, 255, 255], textColor: [0, 0, 0],
fontStyle: "bold", lineWidth: 0.3, lineColor: [0, 0, 0],
},
bodyStyles: { lineWidth: 0.1, lineColor: [180, 180, 180] }, bodyStyles: { lineWidth: 0.1, lineColor: [180, 180, 180] },
columnStyles: { columnStyles: {
0: { cellWidth: 80 }, 0: { cellWidth: colStructure },
1: { cellWidth: 50 }, 1: { cellWidth: colType },
2: { cellWidth: 50, halign: "right" }, 2: { cellWidth: colMontant, halign: "right" },
}, },
alternateRowStyles: { fillColor: [255, 255, 255] }, alternateRowStyles: { fillColor: [248, 248, 248] },
// Forcer tout sur 1 page
pageBreak: "avoid",
rowPageBreak: "avoid",
margin: { left: margin, right: margin },
tableWidth: usableW,
}); });
const moisPad = moisStr.padStart(2, "0"); const moisPad = moisStr.padStart(2, "0");