import { cn } from "@/lib/utils"; import { formatCurrency } from "@/lib/format-currency"; import { formatDateShort } from "@/lib/format-date"; import { STATEMENT_INK_MUTED, STATEMENT_RULE, STATEMENT_RULE_LIGHT, } from "@/components/ui/statement-primitives"; /** * StatementTransactionTable - WealthX DS (L3 Organism) * * The transaction ledger printed on a generated statement. Static and * print-density by design - no sorting, filtering, or row actions. For the * interactive screen equivalent see `DashboardTransactionsTable`. * * One column shape for every account type, matching the * `Sample_Open_Banking_statement_*` references: Date · Transaction · Debit · * Credit · Balance. Loan and card statements run the same ledger with signed * (negative) balances - a repayment is a credit, an interest charge a debit. * * Layer: L3 Organism */ // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- export interface StatementTransaction { id: string; /** ISO date string. */ date: string; description: string; /** Signed movement - positive is a credit, negative a debit. */ amount: number; /** Running account balance after this transaction - signed, negative when owing. */ balance?: number; } export interface StatementTransactionTableProps { transactions: StatementTransaction[]; /** Balance carried into the period - rendered as the first row. */ openingBalance?: number; /** Balance at the end of the period - rendered as the closing row. */ closingBalance?: number; openingLabel?: string; closingLabel?: string; /** Optional heading above the table. */ title?: string; /** Shown when `transactions` is empty. */ emptyMessage?: string; className?: string; } // --------------------------------------------------------------------------- // StatementTransactionTable // --------------------------------------------------------------------------- export function StatementTransactionTable({ transactions, openingBalance, closingBalance, openingLabel = "Opening balance", closingLabel = "Closing balance", title, emptyMessage = "No transactions for this statement period.", className, }: StatementTransactionTableProps) { return (
{title && {title}} {openingBalance !== undefined && ( )} {transactions.length === 0 ? ( ) : ( transactions.map((transaction) => { const isDebit = transaction.amount < 0; return ( ); }) )} {closingBalance !== undefined && ( )}
Date Transaction Debit Credit Balance
{openingLabel} {formatCurrency(openingBalance, { decimals: 2 })}
{emptyMessage}
{formatDateShort(transaction.date)} {transaction.description} {isDebit ? formatCurrency(Math.abs(transaction.amount), { decimals: 2, }) : ""} {isDebit ? "" : formatCurrency(transaction.amount, { decimals: 2 })} {transaction.balance !== undefined ? formatCurrency(transaction.balance, { decimals: 2 }) : ""}
{closingLabel} {formatCurrency(closingBalance, { decimals: 2 })}
); }