diff --git a/resources/js/components/transactions/bulk-actions-bar.tsx b/resources/js/components/transactions/bulk-actions-bar.tsx index 005f85bc..c8ba4953 100644 --- a/resources/js/components/transactions/bulk-actions-bar.tsx +++ b/resources/js/components/transactions/bulk-actions-bar.tsx @@ -73,7 +73,7 @@ export function BulkActionsBar({ Delete diff --git a/resources/js/lib/sync-manager.ts b/resources/js/lib/sync-manager.ts index bd264d9b..19728c89 100644 --- a/resources/js/lib/sync-manager.ts +++ b/resources/js/lib/sync-manager.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import { uuidv7 } from 'uuidv7'; import { db } from './dexie-db'; export type StoreName = @@ -179,11 +180,14 @@ export class SyncManager { data: Omit, ): Promise { const timestamp = new Date().toISOString(); - const tempId = Date.now(); + + // Use UUID v7 for transactions, numeric IDs for other entities + const id = + this.options.storeName === 'transactions' ? uuidv7() : Date.now(); const record = { ...data, - id: tempId, + id, created_at: timestamp, updated_at: timestamp, } as T; diff --git a/resources/js/pages/transactions/index.tsx b/resources/js/pages/transactions/index.tsx index 50883e5d..92a84fb0 100644 --- a/resources/js/pages/transactions/index.tsx +++ b/resources/js/pages/transactions/index.tsx @@ -112,6 +112,7 @@ export default function Transactions({ categories, accounts, banks }: Props) { const [createDialogOpen, setCreateDialogOpen] = useState(false); const [deleteTransaction, setDeleteTransaction] = useState(null); + const [isBulkDeleteMode, setIsBulkDeleteMode] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const [isBulkDeleting, setIsBulkDeleting] = useState(false); const [isBulkUpdating, setIsBulkUpdating] = useState(false); @@ -569,7 +570,7 @@ export default function Transactions({ categories, accounts, banks }: Props) { } const selectedTransactions = transactions.filter((t) => - selectedIds.includes(t.id), + selectedIds.includes(t.id.toString()), ); consoleDebug( 'Processing transactions:', @@ -794,6 +795,8 @@ export default function Transactions({ categories, accounts, banks }: Props) { ), ); setDeleteTransaction(null); + setIsBulkDeleteMode(false); + setRowSelection({}); } catch (error) { console.error('Failed to delete transaction:', error); } finally { @@ -829,7 +832,7 @@ export default function Transactions({ categories, accounts, banks }: Props) { setTransactions((previous) => previous.map((transaction) => { - if (selectedIds.includes(transaction.id)) { + if (selectedIds.includes(transaction.id.toString())) { return { ...transaction, category_id: categoryId, @@ -850,14 +853,17 @@ export default function Transactions({ categories, accounts, banks }: Props) { function handleBulkDeleteClick() { const selectedIds = Object.keys(rowSelection); + if (selectedIds.length === 0) { return; } - const firstSelectedTransaction = transactions.find( - (t) => t.id === selectedIds[0], + const firstSelectedTransaction = filteredTransactions.find( + (t) => t.id.toString() === selectedIds[0], ); + if (firstSelectedTransaction) { + setIsBulkDeleteMode(true); setDeleteTransaction(firstSelectedTransaction); } } @@ -877,6 +883,7 @@ export default function Transactions({ categories, accounts, banks }: Props) { ), ); setDeleteTransaction(null); + setIsBulkDeleteMode(false); setRowSelection({}); } catch (error) { console.error('Failed to delete transactions:', error); @@ -997,16 +1004,21 @@ export default function Transactions({ categories, accounts, banks }: Props) { !open && setDeleteTransaction(null)} + onOpenChange={(open) => { + if (!open) { + setDeleteTransaction(null); + setIsBulkDeleteMode(false); + } + }} > Delete Transaction - {Object.keys(rowSelection).length > 1 ? 's' : ''} + {isBulkDeleteMode ? 's' : ''} - {Object.keys(rowSelection).length > 1 + {isBulkDeleteMode ? `Are you sure you want to delete ${Object.keys(rowSelection).length} transactions? This action cannot be undone.` : 'Are you sure you want to delete this transaction? This action cannot be undone.'} @@ -1019,7 +1031,7 @@ export default function Transactions({ categories, accounts, banks }: Props) { 1 + isBulkDeleteMode ? handleBulkDelete : handleDelete } diff --git a/resources/js/services/transaction-sync.ts b/resources/js/services/transaction-sync.ts index b264f610..fddc2dce 100644 --- a/resources/js/services/transaction-sync.ts +++ b/resources/js/services/transaction-sync.ts @@ -101,6 +101,7 @@ class TransactionSyncService { async update(id: string, data: Partial): Promise { const existing = await this.getById(id); + if (!existing) { throw new Error('Transaction not found'); } @@ -126,6 +127,7 @@ class TransactionSyncService { for (const id of ids) { const existing = await this.getById(id); + if (!existing) { console.warn(`Transaction ${id} not found, skipping`); continue; @@ -149,12 +151,13 @@ class TransactionSyncService { async delete(id: string): Promise { const transaction = await this.getById(id); + if (!transaction) { throw new Error('Transaction not found'); } const timestamp = new Date().toISOString(); - await db.transactions.delete(id); + await db.transactions.delete(transaction.id); await db.pending_changes.add({ store: 'transactions', operation: 'delete', @@ -168,12 +171,13 @@ class TransactionSyncService { for (const id of ids) { const transaction = await this.getById(id); + if (!transaction) { console.warn(`Transaction ${id} not found, skipping`); continue; } - await db.transactions.delete(id); + await db.transactions.delete(transaction.id); await db.pending_changes.add({ store: 'transactions', operation: 'delete',