From 05b9c151c404a092e310f2e12ab3f6ac85ed61b2 Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Fri, 29 Dec 2023 09:55:11 +0100 Subject: [PATCH] experiment(PDFKit): demo table --- package-lock.json | 9 +++ package.json | 1 + pages/api/test-table.js | 144 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 pages/api/test-table.js diff --git a/package-lock.json b/package-lock.json index e8471b932..05badb061 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "next-transpile-modules": "9.1.0", "node-fetch": "2.6.12", "pdfkit": "0.14.0", + "pdfkit-table": "0.1.99", "polished": "4.2.2", "prop-types": "15.8.1", "qr-image": "3.2.0", @@ -13303,6 +13304,14 @@ "png-js": "^1.0.0" } }, + "node_modules/pdfkit-table": { + "version": "0.1.99", + "resolved": "https://registry.npmjs.org/pdfkit-table/-/pdfkit-table-0.1.99.tgz", + "integrity": "sha512-BaunFJ7cvKqIPONzX9FXUpeC/3iJeLo0v2nVNjCccAxdMXKvDMBjxyF4wZhKOYlmP+nYZcikf9ByVJeCzjNK6g==", + "dependencies": { + "pdfkit": "latest" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", diff --git a/package.json b/package.json index 0cc4bd677..b50fbe08b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "next-transpile-modules": "9.1.0", "node-fetch": "2.6.12", "pdfkit": "0.14.0", + "pdfkit-table": "0.1.99", "polished": "4.2.2", "prop-types": "15.8.1", "qr-image": "3.2.0", diff --git a/pages/api/test-table.js b/pages/api/test-table.js new file mode 100644 index 000000000..439be55fa --- /dev/null +++ b/pages/api/test-table.js @@ -0,0 +1,144 @@ +import PDFDocument from 'pdfkit-table'; +import fs from 'fs'; + +// Unit: 1pt = 1/72 inch = 0.352777239 mm +const MARGIN_IN_PTS = 40; // The margin between the edge of the page and cards +const SPACING_IN_PTS = 35; // The spacing between cards +const CARD_WIDTH_IN_PTS = 243; +const CARD_HEIGHT_IN_PTS = 153; +const CARD_PADDING = 10; +const NB_CARDS_PER_PAGE = 8; +const FONT_NORMAL = '.fonts/Inter-Regular.otf'; +const FONT_BOLD = '.fonts/Inter-Bold.otf'; + +const OC_SVG_LOGO = fs.readFileSync('public/static/images/opencollective-icon.svg', 'utf8'); +const LINK_SVG = fs.readFileSync('public/static/images/external-link.svg', 'utf8'); + +/** + * Generate a PDF using PDFKit and return it as a buffer. + */ +export default async function handler(req, res) { + // Set response headers + res.setHeader('Cache-Control', 'no-store'); + res.setHeader('Content-Type', 'application/pdf'); + // res.setHeader('Content-Disposition', 'attachment; filename="gift-cards.pdf"'); + + // Generate doc + const doc = new PDFDocument(); + doc.pipe(res); + doc.fillColor('#000000').fontSize(10); + doc.font(FONT_NORMAL); + + doc.table( + { + title: 'Payment Receipt', + headers: [ + { label: 'Date', align: 'left', headerColor: '#36bcff' }, + { label: 'Description', align: 'left', headerColor: '#36bcff' }, + { label: 'QTY', align: 'left', headerColor: '#36bcff' }, + { label: 'Unit Price', align: 'left', headerColor: '#36bcff' }, + { label: 'Tax', align: 'left', headerColor: '#36bcff' }, + { label: 'Net Amount', align: 'right', headerColor: '#36bcff' }, + ], + rows: [ + ['2020-01-01', 'Financial contribution to Dark Reader', '1', '$5.00', '0%', '$5.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-06-01', 'TShirt from Babel', '1', '$20.00', '0%', '$20.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ['2021-01-01', 'Financial contribution to Webpack', '1', '$15.00', '0%', '$15.00'], + ], + }, + { + columnsSize: [60, 150, 20, 100, 20, 100], + }, + ); + + // Show Subtotal + Total on the bottom right of the table + // Subtotal + doc + .font(FONT_BOLD) + .fontSize(10) + .text('Subtotal', 350, doc.y, { lineBreak: false, align: 'right' }) + .text('$5.00', 490, doc.y, { lineBreak: false, align: 'right' }); + + // Blue box for the total + doc + .rect(325, doc.y + 20, 200, 25) + .fillColor('#F0F8FF') + .fill(); + + // Total + doc + .font(FONT_BOLD) + .fontSize(10) + .fillColor('#000000') + .text('Total', 350, doc.y + 25, { lineBreak: false, align: 'right' }) + .text('$5.00', 490, doc.y, { lineBreak: false, align: 'right' }); + + doc.end(); +}