import autoTable from "jspdf-autotable"; import { createBrandedPdf, addBrandedFooter, COLORS, TABLE_HEAD_STYLES, TABLE_BODY_STYLES, TABLE_STYLES, } from "./pdf-template"; interface PackingPdfData { packing_number: string; created_at: string; po_number: string; customer_ref?: string | null; customer_name: string; customer_code: string; customer_email?: string | null; customer_phone?: string | null; customer_address?: string | null; customer_contact?: string | null; product_name: string; product_sku: string; quantity: number; notes?: string | null; serials: { serial_number: string }[]; } export function generatePackingPdf(data: PackingPdfData) { const { doc, contentY } = createBrandedPdf({ title: "PACKING LIST", documentNumber: data.packing_number, date: new Date(data.created_at).toLocaleDateString("en-GB"), recipient: { label: "SHIP TO", name: data.customer_name, code: data.customer_code, contact: data.customer_contact, address: data.customer_address, phone: data.customer_phone, email: data.customer_email, }, }); const pageWidth = doc.internal.pageSize.getWidth(); const margin = 14; const contentWidth = pageWidth - margin * 2; // --- Order details row --- let y = contentY; doc.setFillColor(...COLORS.bgLight); doc.setDrawColor(...COLORS.border); doc.setLineWidth(0.2); doc.roundedRect(margin, y, contentWidth, 16, 1.5, 1.5, "FD"); const colWidth = contentWidth / 4; const labels = ["PO Number", "Customer Ref", "Product", "Qty Shipped"]; const values = [ data.po_number, data.customer_ref || "-", `${data.product_name} (${data.product_sku})`, String(data.quantity), ]; labels.forEach((label, i) => { const x = margin + 4 + i * colWidth; doc.setFontSize(6.5); doc.setFont("helvetica", "normal"); doc.setTextColor(...COLORS.muted); doc.text(label, x, y + 5); doc.setFontSize(8); doc.setFont("helvetica", "bold"); doc.setTextColor(...COLORS.primary); const val = doc.splitTextToSize(values[i], colWidth - 8); doc.text(val[0], x, y + 11); }); y += 22; // --- Serial Numbers section (clean list layout like PO Order Items) --- doc.setFontSize(9); doc.setFont("helvetica", "bold"); doc.setTextColor(...COLORS.primary); doc.text("Serial Numbers", margin, y); y += 4; const tableData = data.serials.map((s, i) => [String(i + 1), s.serial_number]); autoTable(doc, { startY: y, head: [["#", "Serial Number"]], body: tableData, theme: "plain", headStyles: { ...TABLE_HEAD_STYLES, fillColor: COLORS.bgLight, lineWidth: 0, }, bodyStyles: { ...TABLE_BODY_STYLES, font: "courier", lineWidth: 0, }, alternateRowStyles: { fillColor: [250, 250, 250] }, columnStyles: { 0: { cellWidth: 14, halign: "center" }, 1: { cellWidth: "auto" }, }, margin: { left: margin, right: margin }, styles: { lineColor: COLORS.border, lineWidth: 0, cellPadding: 2, }, }); // --- Notes --- // eslint-disable-next-line @typescript-eslint/no-explicit-any const finalY = (doc as any).lastAutoTable?.finalY || y + 30; if (data.notes) { const noteY = finalY + 6; doc.setFillColor(...COLORS.bgLight); doc.setDrawColor(...COLORS.border); doc.setLineWidth(0.2); doc.roundedRect(margin, noteY, contentWidth, 16, 1.5, 1.5, "FD"); doc.setFontSize(6.5); doc.setFont("helvetica", "bold"); doc.setTextColor(...COLORS.accent); doc.text("NOTES", margin + 4, noteY + 5); doc.setFontSize(7.5); doc.setFont("helvetica", "normal"); doc.setTextColor(...COLORS.secondary); const noteLines = doc.splitTextToSize(data.notes, contentWidth - 8); doc.text(noteLines, margin + 4, noteY + 11); } addBrandedFooter(doc); return doc; }