diff options
Diffstat (limited to 'lib/utils.js')
| -rw-r--r-- | lib/utils.js | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/utils.js b/lib/utils.js index c68d222b..389f8a57 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -75,4 +75,80 @@ export let getInvoice = async (hash) => { if (iid && iid.id) iid = iid.id; else if (iid && iid.hash) iid = iid.hash; return await g(`invoice:${iid}`); +}; + +export let f = (s, currency) => + new Intl.NumberFormat("en-US", { + style: "currency", + currency, + }) + .format(s) + .replace("CA", ""); + +export function formatReceipt(items, currency) { +function wrapText(text, maxWidth) { + const words = text.split(" "); + const lines = []; + let currentLine = ""; + words.forEach((word) => { + if (currentLine.length + word.length + 1 > maxWidth) { + lines.push(currentLine); + currentLine = word; + } else { + currentLine += (currentLine.length > 0 ? " " : "") + word; + } + }); + if (currentLine) lines.push(currentLine); + return lines; } + +function calculateColumnWidths(items) { + let maxQuantityLength = 0; + let maxPriceLength = 0; + + items.forEach((item) => { + const quantityLength = String(item.quantity).length; + if (quantityLength > maxQuantityLength) { + maxQuantityLength = quantityLength; + } + + const priceLength = f(item.price * item.quantity, currency).length; + if (priceLength > maxPriceLength) { + maxPriceLength = priceLength; + } + }); + + // Add padding to the widths for aesthetic spacing + return { + quantityColumnWidth: maxQuantityLength + 1, // Space after quantity + priceColumnWidth: maxPriceLength + 1, // Space before price + }; +} + const maxLineWidth = 32; + const { quantityColumnWidth, priceColumnWidth } = calculateColumnWidths( + items, + ); + const nameColumnWidth = maxLineWidth - quantityColumnWidth - priceColumnWidth; + + return items + .map((item) => { + const quantityStr = String(item.quantity).padEnd(quantityColumnWidth); + const priceStr = f(item.price * item.quantity, currency).padStart( + priceColumnWidth, + ); + const nameLines = wrapText(item.name, nameColumnWidth); + + // Construct the full line(s) with the first line including the price + let fullLines = [ + `${quantityStr}${nameLines[0].padEnd(nameColumnWidth)}${priceStr}`, + ]; + // Add any additional name lines, properly indented + for (let i = 1; i < nameLines.length; i++) { + fullLines.push(" ".repeat(quantityColumnWidth) + nameLines[i]); + } + + return fullLines.join("\n"); + }) + .join("\n\n"); +} + |
