From 3d71234a6105f3095251d9c10f3dbf14e09a5e15 Mon Sep 17 00:00:00 2001 From: Carlos Escalante Date: Sat, 4 Jul 2026 09:38:36 -0600 Subject: [PATCH] Budget: unify transactions section into one card Toolbar (source tabs, search, CSV, add) and a summary strip (billing cycle range, count, per-currency total) now live inside the table card instead of five loose control rows. Cycle range 18-to-18 is finally visible. Stray English strings translated; back-button spacing fixed. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/components/TransactionList.tsx | 86 ++++++++++++------- .../transactions/transaction-columns.tsx | 12 +-- frontend/src/pages/Budget.tsx | 59 ++++++++----- 3 files changed, 96 insertions(+), 61 deletions(-) diff --git a/frontend/src/components/TransactionList.tsx b/frontend/src/components/TransactionList.tsx index 2976615..97c01b9 100644 --- a/frontend/src/components/TransactionList.tsx +++ b/frontend/src/components/TransactionList.tsx @@ -48,6 +48,11 @@ export interface TransactionListProps { addLabel?: string; onToggleDeferred?: (tx: Transaction) => void; onConvertTasaCero?: (tx: Transaction) => void; + /** Extra toolbar content, e.g. source tabs (left) and the CSV button (right). */ + toolbarLeft?: React.ReactNode; + toolbarRight?: React.ReactNode; + /** Period hint shown in the summary strip, e.g. "Ciclo 18 jun – 18 jul". */ + summaryLabel?: string; } export default function TransactionList({ @@ -61,9 +66,12 @@ export default function TransactionList({ emptyMessage = 'No transactions found', showCategory = true, showSourceIcon = false, - addLabel = 'Add Transaction', + addLabel = 'Agregar transacción', onToggleDeferred, onConvertTasaCero, + toolbarLeft, + toolbarRight, + summaryLabel, }: TransactionListProps) { const [modalOpen, setModalOpen] = useState(false); const [editing, setEditing] = useState(null); @@ -212,45 +220,58 @@ export default function TransactionList({ return ( <> - {/* Search + Add */} -
-
+ + + + {/* Toolbar: source tabs · search · CSV · add */} +
+ {toolbarLeft} +
onSearchChange(e.target.value)} className="pl-10" - placeholder="Search merchants..." + placeholder="Buscar comercio…" />
- +
+ {toolbarRight} + +
- {/* Total of the listed transactions */} - {totalsByCurrency.length > 0 && ( -
- - {visibleTransactions.length} transaccion{visibleTransactions.length === 1 ? '' : 'es'} · Total: + {/* Summary strip: period · count · total */} + {visibleTransactions.length > 0 && ( +
+ + {summaryLabel ? `${summaryLabel} · ` : ''} + {visibleTransactions.length} transaccion{visibleTransactions.length === 1 ? '' : 'es'} - {totalsByCurrency.map(([currency, net], i) => ( - - {i > 0 && +} - {net < 0 ? '+' : ''} - {formatAmount(net, currency)} + {totalsByCurrency.length > 0 && ( + + Total: + {totalsByCurrency.map(([currency, net], i) => ( + + {i > 0 && +} + {net < 0 ? '+' : ''} + {formatAmount(net, currency)} + + ))} - ))} + )}
)} {/* Bulk action bar */} {selected.size > 0 && ( -
+
{selected.size} seleccionada{selected.size === 1 ? '' : 's'} @@ -327,8 +348,7 @@ export default function TransactionList({ )} {/* Mobile list */} - - +
{empty ? (
{emptyIcon || } @@ -422,13 +442,13 @@ export default function TransactionList({ )} -
)) )} - - +
{/* Desktop table */} - - +
- +
+ +
{/* Modals */} diff --git a/frontend/src/components/transactions/transaction-columns.tsx b/frontend/src/components/transactions/transaction-columns.tsx index c12577b..20f6370 100644 --- a/frontend/src/components/transactions/transaction-columns.tsx +++ b/frontend/src/components/transactions/transaction-columns.tsx @@ -65,7 +65,7 @@ export function getTransactionColumns({ columns.push( { accessorKey: 'date', - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => ( {new Date(row.original.date).toLocaleDateString('es-CR', { @@ -78,7 +78,7 @@ export function getTransactionColumns({ }, { accessorKey: 'merchant', - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const tx = row.original; return ( @@ -129,7 +129,7 @@ export function getTransactionColumns({ columns.push({ accessorFn: (row) => row.category?.name ?? '', id: 'category', - header: ({ column }) => , + header: ({ column }) => , cell: ({ row }) => { const category = row.original.category; return category ? ( @@ -146,7 +146,7 @@ export function getTransactionColumns({ accessorKey: 'amount', meta: { className: 'text-right' }, header: ({ column }) => ( - + ), cell: ({ row }) => { const tx = row.original; @@ -204,7 +204,7 @@ export function getTransactionColumns({ -
+ {txQuery.isError ? ( setTxSource(v as typeof txSource)} + > + + Tarjeta + Efectivo y Transferencias + + + } + toolbarRight={ + + } /> )}