mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 12:28:48 +02:00
Bulk selection UI and import-review modal
Transactions gain a checkbox column with select-all; a bulk bar offers assign-category, defer/restore and delete (confirmed) via the new bulk endpoint, with toasts and invalidation. The paste-import modal now lists each skipped duplicate with the matched existing row and offers 'Importar duplicados de todos modos' — re-importing ONLY the skipped lines so first-pass rows can't double-import (UX-20). Two real fixes found en route: the mobile list ignored undo-pending deletes and used en-US dates; the desktop date column also lost its en-US stray. Note: UX-11 (no mobile layout) was a false positive — a card layout already existed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,12 +8,20 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { DataTableColumnHeader } from '@/components/ui/data-table-column-header';
|
||||
|
||||
export interface RowSelection {
|
||||
selected: Set<number>;
|
||||
allSelected: boolean;
|
||||
onToggle: (id: number) => void;
|
||||
onToggleAll: () => void;
|
||||
}
|
||||
|
||||
interface TransactionColumnOptions {
|
||||
showCategory: boolean;
|
||||
showSourceIcon?: boolean;
|
||||
onEdit: (tx: Transaction) => void;
|
||||
onDelete: (txId: number) => void;
|
||||
onToggleDeferred?: (tx: Transaction) => void;
|
||||
selection?: RowSelection;
|
||||
}
|
||||
|
||||
export function getTransactionColumns({
|
||||
@@ -22,14 +30,43 @@ export function getTransactionColumns({
|
||||
onEdit,
|
||||
onDelete,
|
||||
onToggleDeferred,
|
||||
selection,
|
||||
}: TransactionColumnOptions): ColumnDef<Transaction, unknown>[] {
|
||||
const columns: ColumnDef<Transaction, unknown>[] = [
|
||||
const columns: ColumnDef<Transaction, unknown>[] = [];
|
||||
|
||||
if (selection) {
|
||||
columns.push({
|
||||
id: 'select',
|
||||
size: 36,
|
||||
enableSorting: false,
|
||||
header: () => (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="accent-primary w-4 h-4 cursor-pointer align-middle"
|
||||
aria-label="Seleccionar todas las transacciones"
|
||||
checked={selection.allSelected}
|
||||
onChange={selection.onToggleAll}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="accent-primary w-4 h-4 cursor-pointer align-middle"
|
||||
aria-label={`Seleccionar ${row.original.merchant}`}
|
||||
checked={selection.selected.has(row.original.id)}
|
||||
onChange={() => selection.onToggle(row.original.id)}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
columns.push(
|
||||
{
|
||||
accessorKey: 'date',
|
||||
header: ({ column }) => <DataTableColumnHeader column={column} title="Date" />,
|
||||
cell: ({ row }) => (
|
||||
<span className="font-mono text-muted-foreground text-xs whitespace-nowrap">
|
||||
{new Date(row.original.date).toLocaleDateString('en-US', {
|
||||
{new Date(row.original.date).toLocaleDateString('es-CR', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
@@ -74,7 +111,7 @@ export function getTransactionColumns({
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
);
|
||||
|
||||
if (showCategory) {
|
||||
columns.push({
|
||||
|
||||
Reference in New Issue
Block a user