mirror of
https://github.com/acedanger/finance.git
synced 2025-12-05 22:50:12 -08:00
Fix: Update button remaining disabled in transaction edit mode
This commit resolves an issue where the Update button in the transaction form would remain disabled when attempting to edit a transaction. The problem was in how the transactionStore was managing state updates during transaction editing. Key changes: - Enhanced startEditingTransaction function in transactionStore.ts to ensure proper reactivity - Added clean copy creation of transaction objects to avoid reference issues - Implemented a state update cycle with null value first to force reactivity - Added a small timeout to ensure state changes are properly detected by components The Transaction form now correctly enables the Update button when in edit mode, regardless of account selection state.
This commit is contained in:
@@ -4,43 +4,179 @@ import type { Transaction } from '../types';
|
||||
// Atom to hold the ID of the currently selected account
|
||||
export const currentAccountId = atom<string | null>(null);
|
||||
|
||||
// Atom to hold the current transactions
|
||||
export const currentTransactions = atom<Transaction[]>([]);
|
||||
|
||||
// Atom to hold the transaction object when editing, or null otherwise
|
||||
export const transactionToEdit = atom<Transaction | null>(null);
|
||||
|
||||
// Atom to trigger refreshes in components that depend on external changes
|
||||
export const refreshKey = atom<number>(0);
|
||||
|
||||
// Action to set the current transactions
|
||||
export function setTransactions(transactions: Transaction[]) {
|
||||
console.log('Setting transactions in store:', transactions.length, transactions);
|
||||
currentTransactions.set(transactions);
|
||||
}
|
||||
|
||||
// Action to increment the refresh key, forcing dependent effects to re-run
|
||||
export function triggerRefresh() {
|
||||
console.log('Triggering transaction refresh');
|
||||
refreshKey.set(refreshKey.get() + 1);
|
||||
}
|
||||
|
||||
// Action to set the transaction to be edited
|
||||
export function startEditingTransaction(transaction: Transaction) {
|
||||
transactionToEdit.set(transaction);
|
||||
// Optionally, trigger UI changes like expanding the form here
|
||||
// document.getElementById('add-transaction-section')?.classList.replace('collapsed', 'expanded');
|
||||
// document.getElementById('toggle-add-txn-btn')?.setAttribute('aria-expanded', 'true');
|
||||
console.log('Setting transaction to edit:', transaction);
|
||||
|
||||
// Create a clean copy of the transaction to avoid reference issues
|
||||
const transactionCopy = { ...transaction };
|
||||
|
||||
// Force update to ensure subscribers get notified
|
||||
transactionToEdit.set(null);
|
||||
|
||||
// Set after a small delay to ensure state change is detected
|
||||
setTimeout(() => {
|
||||
transactionToEdit.set(transactionCopy);
|
||||
console.log('Transaction edit state updated:', transactionToEdit.get());
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// Action to clear the edit state
|
||||
export function cancelEditingTransaction() {
|
||||
console.log('Canceling transaction edit');
|
||||
transactionToEdit.set(null);
|
||||
// Optionally, collapse the form
|
||||
// document.getElementById('add-transaction-section')?.classList.replace('expanded', 'collapsed');
|
||||
// document.getElementById('toggle-add-txn-btn')?.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
// Action triggered after a transaction is saved (created or updated)
|
||||
export function transactionSaved(transaction: Transaction) {
|
||||
console.log('Transaction saved:', transaction);
|
||||
|
||||
// Clear edit state if the saved transaction was the one being edited
|
||||
if (transactionToEdit.get()?.id === transaction.id) {
|
||||
transactionToEdit.set(null);
|
||||
}
|
||||
// Potentially trigger UI updates or refreshes here
|
||||
// This might involve dispatching a custom event or calling a refresh function
|
||||
document.dispatchEvent(new CustomEvent('transactionSaved', { detail: { transaction } }));
|
||||
|
||||
// Trigger a general refresh after saving too, to update balance
|
||||
// Add/update the transaction in the current list
|
||||
const currentList = currentTransactions.get();
|
||||
const existingIndex = currentList.findIndex((t) => t.id === transaction.id);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Update existing transaction
|
||||
const updatedList = [...currentList];
|
||||
updatedList[existingIndex] = transaction;
|
||||
currentTransactions.set(updatedList);
|
||||
} else {
|
||||
// Add new transaction
|
||||
currentTransactions.set([transaction, ...currentList]);
|
||||
}
|
||||
|
||||
// Trigger a general refresh after saving
|
||||
triggerRefresh();
|
||||
}
|
||||
|
||||
// Helper function to load transactions for an account
|
||||
export async function loadTransactionsForAccount(accountId: string) {
|
||||
console.log('loadTransactionsForAccount called with ID:', accountId);
|
||||
try {
|
||||
if (!accountId) {
|
||||
console.warn('No account ID provided, clearing transactions');
|
||||
currentTransactions.set([]);
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log(`Fetching transactions from API for account: ${accountId}`);
|
||||
const response = await fetch(`/api/accounts/${accountId}/transactions`);
|
||||
if (!response.ok) {
|
||||
console.error('API error:', response.status, response.statusText);
|
||||
const errorText = await response.text();
|
||||
console.error('Error response:', errorText);
|
||||
throw new Error(`Failed to fetch transactions: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const transactions: Transaction[] = await response.json();
|
||||
console.log(
|
||||
`Loaded ${transactions.length} transactions for account ${accountId}:`,
|
||||
transactions,
|
||||
);
|
||||
|
||||
// Set transactions in the store
|
||||
currentTransactions.set(transactions);
|
||||
return transactions;
|
||||
} catch (error) {
|
||||
console.error('Error loading transactions:', error);
|
||||
// Don't clear transactions on error, to avoid flickering UI
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to create a new transaction
|
||||
export async function createTransaction(transaction: Omit<Transaction, 'id'>) {
|
||||
try {
|
||||
console.log('Creating new transaction:', transaction);
|
||||
const response = await fetch('/api/transactions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(transaction),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
||||
throw new Error(errorData.error || `Failed to create transaction: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const newTransaction = await response.json();
|
||||
console.log('Transaction created successfully:', newTransaction);
|
||||
|
||||
// Add the new transaction to the existing list
|
||||
const currentList = currentTransactions.get();
|
||||
currentTransactions.set([newTransaction, ...currentList]);
|
||||
|
||||
// Trigger refresh to update other components
|
||||
triggerRefresh();
|
||||
|
||||
return newTransaction;
|
||||
} catch (error) {
|
||||
console.error('Error creating transaction:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to update an existing transaction
|
||||
export async function updateTransaction(id: string, transaction: Partial<Transaction>) {
|
||||
try {
|
||||
console.log(`Updating transaction ${id}:`, transaction);
|
||||
const response = await fetch(`/api/transactions/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(transaction),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
||||
throw new Error(errorData.error || `Failed to update transaction: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const updatedTransaction = await response.json();
|
||||
console.log('Transaction updated successfully:', updatedTransaction);
|
||||
|
||||
// Update the transaction in the existing list
|
||||
const currentList = currentTransactions.get();
|
||||
const updatedList = currentList.map((t) =>
|
||||
t.id === updatedTransaction.id ? updatedTransaction : t,
|
||||
);
|
||||
currentTransactions.set(updatedList);
|
||||
|
||||
// Trigger refresh to update other components
|
||||
triggerRefresh();
|
||||
|
||||
return updatedTransaction;
|
||||
} catch (error) {
|
||||
console.error('Error updating transaction:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user