fix: export PDF A4 paysage, 1 seule page, taille police dynamique
This commit is contained in:
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user