feat: enhance transaction management with optimistic updates and error handling for reconciliation and category changes

This commit is contained in:
Julien Froidefond
2025-11-27 11:55:10 +01:00
parent ef668510c8
commit e469656e0d

View File

@@ -157,34 +157,113 @@ export default function TransactionsPage() {
}); });
}; };
const toggleReconciled = (transactionId: string) => { const toggleReconciled = async (transactionId: string) => {
const transaction = data.transactions.find((t) => t.id === transactionId);
if (!transaction) return;
const updatedTransaction = { ...transaction, isReconciled: !transaction.isReconciled };
// Optimistic update
const updatedTransactions = data.transactions.map((t) => const updatedTransactions = data.transactions.map((t) =>
t.id === transactionId ? { ...t, isReconciled: !t.isReconciled } : t, t.id === transactionId ? updatedTransaction : t,
); );
update({ ...data, transactions: updatedTransactions }); update({ ...data, transactions: updatedTransactions });
// Persist to database
try {
await fetch("/api/banking/transactions", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedTransaction),
});
} catch (error) {
console.error("Failed to update transaction:", error);
// Revert on error
refresh();
}
}; };
const setCategory = (transactionId: string, categoryId: string | null) => { const setCategory = async (transactionId: string, categoryId: string | null) => {
const transaction = data.transactions.find((t) => t.id === transactionId);
if (!transaction) return;
const updatedTransaction = { ...transaction, categoryId };
// Optimistic update
const updatedTransactions = data.transactions.map((t) => const updatedTransactions = data.transactions.map((t) =>
t.id === transactionId ? { ...t, categoryId } : t, t.id === transactionId ? updatedTransaction : t,
); );
update({ ...data, transactions: updatedTransactions }); update({ ...data, transactions: updatedTransactions });
// Persist to database
try {
await fetch("/api/banking/transactions", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedTransaction),
});
} catch (error) {
console.error("Failed to update transaction:", error);
refresh();
}
}; };
const bulkReconcile = (reconciled: boolean) => { const bulkReconcile = async (reconciled: boolean) => {
const transactionsToUpdate = data.transactions.filter((t) =>
selectedTransactions.has(t.id)
);
// Optimistic update
const updatedTransactions = data.transactions.map((t) => const updatedTransactions = data.transactions.map((t) =>
selectedTransactions.has(t.id) ? { ...t, isReconciled: reconciled } : t, selectedTransactions.has(t.id) ? { ...t, isReconciled: reconciled } : t,
); );
update({ ...data, transactions: updatedTransactions }); update({ ...data, transactions: updatedTransactions });
setSelectedTransactions(new Set()); setSelectedTransactions(new Set());
// Persist to database
try {
await Promise.all(
transactionsToUpdate.map((t) =>
fetch("/api/banking/transactions", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...t, isReconciled: reconciled }),
})
)
);
} catch (error) {
console.error("Failed to update transactions:", error);
refresh();
}
}; };
const bulkSetCategory = (categoryId: string | null) => { const bulkSetCategory = async (categoryId: string | null) => {
const transactionsToUpdate = data.transactions.filter((t) =>
selectedTransactions.has(t.id)
);
// Optimistic update
const updatedTransactions = data.transactions.map((t) => const updatedTransactions = data.transactions.map((t) =>
selectedTransactions.has(t.id) ? { ...t, categoryId } : t, selectedTransactions.has(t.id) ? { ...t, categoryId } : t,
); );
update({ ...data, transactions: updatedTransactions }); update({ ...data, transactions: updatedTransactions });
setSelectedTransactions(new Set()); setSelectedTransactions(new Set());
// Persist to database
try {
await Promise.all(
transactionsToUpdate.map((t) =>
fetch("/api/banking/transactions", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...t, categoryId }),
})
)
);
} catch (error) {
console.error("Failed to update transactions:", error);
refresh();
}
}; };
const toggleSelectAll = () => { const toggleSelectAll = () => {