import * as XLSX from "xlsx"; import { PDFDocument, rgb, StandardFonts } from 'pdf-lib'; /** * Export JSON data to CSV * @param {Array} data - Array of objects to export * @param {string} fileName - File name without extension */ export const exportToCSV = (data, fileName = "data") => { const headers = Object.keys(data[0] || {}); const csvContent = [ headers.join(","), // header row ...data.map(row => headers.map(field => `"${row[field] ?? ""}"`).join(",")), ].join("\n"); const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.setAttribute("download", `${fileName}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); }; /** * Export JSON data to Excel * @param {Array} data - Array of objects to export * @param {string} fileName - File name without extension */ export const exportToExcel = (data, fileName = "data") => { const ws = XLSX.utils.json_to_sheet(data); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); XLSX.writeFile(wb, `${fileName}.xlsx`); }; /** * Export JSON data to PDF using pdf-lib * @param {Array} data - Array of objects to export * @param {string} fileName - File name for the PDF (optional) */ const sanitizeText = (text) => { if (!text) return ""; // Replace all non-ASCII characters with "?" or remove them return text.replace(/[^\x00-\x7F]/g, "?"); }; export const exportToPDF = async (data, fileName = "data", columns = null, options = {}) => { if (!data || data.length === 0) return; const pdfDoc = await PDFDocument.create(); const font = await pdfDoc.embedFont(StandardFonts.Helvetica); // Default options const { columnWidths = [], // array of widths per column fontSizeHeader = 12, fontSizeRow = 10, rowHeight = 25, } = options; const pageWidth = 1000; const pageHeight = 600; let page = pdfDoc.addPage([pageWidth, pageHeight]); const margin = 30; let y = pageHeight - margin; const headers = columns || Object.keys(data[0]); // Draw headers headers.forEach((header, i) => { const x = margin + (columnWidths[i] ? columnWidths.slice(0, i).reduce((a, b) => a + b, 0) : i * 150); page.drawText(header, { x, y, font, size: fontSizeHeader }); }); y -= rowHeight; // Draw rows data.forEach(row => { headers.forEach((header, i) => { const x = margin + (columnWidths[i] ? columnWidths.slice(0, i).reduce((a, b) => a + b, 0) : i * 150); const text = row[header] || ''; page.drawText(text, { x, y, font, size: fontSizeRow }); }); y -= rowHeight; if (y < margin) { page = pdfDoc.addPage([pageWidth, pageHeight]); y = pageHeight - margin; } }); const pdfBytes = await pdfDoc.save(); const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `${fileName}.pdf`; link.click(); }; /** * Export JSON data to PDF in a card-style format * @param {Array} data - Array of objects to export * @param {string} fileName - File name for the PDF (optional) */ export const exportToPDF1 = async (data, fileName = "data") => { if (!data || data.length === 0) return; const pdfDoc = await PDFDocument.create(); const font = await pdfDoc.embedFont(StandardFonts.Helvetica); const boldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold); const pageWidth = 600; const pageHeight = 800; const margin = 30; const cardSpacing = 20; const cardPadding = 10; let page = pdfDoc.addPage([pageWidth, pageHeight]); let y = pageHeight - margin; for (const item of data) { const title = item.ContactName || ""; const subtitle = `by ${item.CreatedBy || ""} on ${item.CreatedAt || ""}`; const body = item.Note || ""; const cardHeight = 80 + (body.length / 60) * 14; // approximate height for body text if (y - cardHeight < margin) { page = pdfDoc.addPage([pageWidth, pageHeight]); y = pageHeight - margin; } // Draw card border page.drawRectangle({ x: margin, y: y - cardHeight, width: pageWidth - 2 * margin, height: cardHeight, borderColor: rgb(0.7, 0.7, 0.7), borderWidth: 1, color: rgb(1, 1, 1), }); // Draw title page.drawText(title, { x: margin + cardPadding, y: y - 20, font: boldFont, size: 12, color: rgb(0.1, 0.1, 0.1), }); // Draw subtitle page.drawText(subtitle, { x: margin + cardPadding, y: y - 35, font, size: 10, color: rgb(0.4, 0.4, 0.4), }); // Draw body text (wrap manually) const lines = body.match(/(.|[\r\n]){1,80}/g) || []; lines.forEach((line, i) => { page.drawText(line, { x: margin + cardPadding, y: y - 50 - i * 12, font, size: 10, color: rgb(0.2, 0.2, 0.2), }); }); y -= cardHeight + cardSpacing; } const pdfBytes = await pdfDoc.save(); const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `${fileName}.pdf`; link.click(); }; /** * Print the HTML table by accepting the table element or a reference. * @param {HTMLElement} table - The table element (or ref) to print */ export const printTable = (table) => { if (table) { const clone = table.cloneNode(true); // Remove last column (Actions) from all rows clone.querySelectorAll("tr").forEach((row) => { row.removeChild(row.lastElementChild); }); const newWindow = window.open("", "", "width=600,height=600"); newWindow.document.write("