import { Box, Button, Container, Flex, Flow, Screen, ScrollableList, Text, } from "wretched"; import { ClientResponse, InvoiceResponse, getAllClients, getAllInvoices, getAllProjects, } from "../services/pancakeApi.js"; import { compact, find, reverse, sortBy } from "lodash-es"; import Table from "cli-table3"; import { differenceInBusinessDays, format, parse } from "date-fns"; import { tableCellBox } from "./helpers/tableCellBox.js"; import { Theme } from "wretched/dist/Theme.js"; import { distanceInBizDays, parseServiceDateString, simpleFormat, } from "./helpers/dates.js"; export const renderInvoiceList = async ( clientId: string, onSelect: (selectedInvoiceId: string | number) => void, ) => { if (clientId === undefined) { console.warn("No Client Id"); return new Text({ text: " --" }); } const invResp = await getAllInvoices({ client_id: clientId }); const invoices: Array = invResp.invoices .sort((a, b) => Number(a.invoice_number) - Number(b.invoice_number)) .reverse(); if (!invoices?.length) { console.warn("No invoices"); return new Text({ text: " --" }); } type FormattedInvoice = InvoiceResponse & { dueDistance: string }; const transformInvoice = (invoice: InvoiceResponse): FormattedInvoice => { const ret: FormattedInvoice = { ...invoice, dueDistance: "" }; try { if (invoice.due_date?.length > 0) { const due = parseServiceDateString(invoice.due_date); ret.due_date = simpleFormat(due); ret.dueDistance = `Due in ${distanceInBizDays(due)} biz days.`; } if (invoice.payment_date?.length > 0) { ret.payment_date = simpleFormat( parseServiceDateString(invoice.payment_date), ); } ret.amount = "$" + Number(invoice.amount).toFixed(2).padEnd(2, "0"); } catch (error) { console.error("Error transforming date", error); } finally { return ret; } }; // const detailsTable = new Table({ // head: ["Invoice#", "Amount", "Due", "Paid?", "Overdue?"], // }); // const detailsTable: string[] | undefined = new Array(); // detailsTable.concat( // ...invoices.map((x) => [ // x.invoice_number, // Number(x.amount).toFixed(2), // x.due_date?.substring(0, 10), // x.is_paid ? "💰" : "⏳", // x.overdue ? "🔥" : "✅", // ]), // ); return new ScrollableList({ cellForItem: (item, row) => { return Flex.right({ children: [ new Button({ onClick: () => onSelect(item.id), border: "none", width: 6, text: item.invoice_number, }), tableCellBox(item.amount, { theme: item.is_paid ? Theme.green : Theme.secondary, padding: { left: 1, right: 1, top: 0, bottom: 0 }, borders: { right: false }, width: 15, alignment: "right", }), tableCellBox(item.dueDistance, { theme: !item.is_paid && item.overdue ? Theme.red : Theme.secondary, borders: { right: false }, padding: { left: 1, right: 1, top: 0, bottom: 0 }, width: 20, alignment: "center", }), ], }); }, items: invoices.map(transformInvoice), showScrollbars: undefined, }); };