Add CSV import to setup wizard

- New csv-import wizard step with file upload, auto column detection, column mapping UI, split-debit/credit support, and 5-row preview
- Imports transactions and auto-calculates account balance from CSV data
- Uses pendingImportedTransactions state (not side-channel) to reliably pass transactions through to saveUserData
- handleSetupComplete reloads from server so imported transactions appear in the UI immediately after wizard completes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-07-14 08:45:17 -04:00
1 parent 20ea25f4de
commit 8f9e9269ec
2 files changed
+347 -11

No files matched your search

+32 -8
View File
@@ -323,14 +323,38 @@ export default function BudgetDashboard() {
setLoading(false);
};
const handleSetupComplete = (accs: Account[], envs: Envelope[]) => {
const accsWithBase = accs.map(a => {
const base = normalizeBalanceByType(a.type, a.startingBalance ?? a.balance);
return { ...a, startingBalance: base, balance: base };
});
setAccounts(accsWithBase);
setEnvelopes(envs);
setTransactions([]);
const handleSetupComplete = async (accs: Account[], envs: Envelope[]) => {
// Re-load from server so imported CSV transactions are included
try {
const userData = await DataService.loadUserData();
if (userData) {
const accsWithBase = (userData.accounts ?? accs).map(a => {
const base = normalizeBalanceByType(a.type, a.startingBalance ?? a.balance);
return { ...a, startingBalance: base, balance: base };
});
setAccounts(accsWithBase);
setEnvelopes(userData.envelopes ?? envs);
setTransactions(userData.transactions ?? []);
setGoals(userData.goals ?? []);
setTransactionRules(userData.transactionRules ?? []);
} else {
const accsWithBase = accs.map(a => {
const base = normalizeBalanceByType(a.type, a.startingBalance ?? a.balance);
return { ...a, startingBalance: base, balance: base };
});
setAccounts(accsWithBase);
setEnvelopes(envs);
setTransactions([]);
}
} catch {
const accsWithBase = accs.map(a => {
const base = normalizeBalanceByType(a.type, a.startingBalance ?? a.balance);
return { ...a, startingBalance: base, balance: base };
});
setAccounts(accsWithBase);
setEnvelopes(envs);
setTransactions([]);
}
setSetupCompleted(true);
setShowSetupWizard(false);
};