From 8ebd324e77a815d4f2a9303fd0e49c95e78cccc0 Mon Sep 17 00:00:00 2001 From: olsch01 Date: Fri, 20 Feb 2026 08:53:04 -0500 Subject: [PATCH] Remove Investments tab, enhance fund tabs with full investment details and edit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed standalone Investments tab — investment accounts now show only under their respective Operating/Reserve tabs with full detail columns - Investment sub-tables now include: Principal, Current Value, Rate, Interest Earned, Maturity Value, Maturity Date, Days Remaining, plus summary cards (Total Principal, Total Current Value, Avg Rate) - Added investment edit capability via modal (name, institution, type, fund, principal, current value, rate, purchase/maturity dates, notes) - Fixed primary account star icon — now shows for all non-system accounts (was previously restricted to asset type only), allowing users to set default Operating and Reserve accounts regardless of account type - Fixed Adjust Balance icon to also show for all non-system accounts Co-Authored-By: Claude Opus 4.6 --- frontend/src/pages/accounts/AccountsPage.tsx | 311 +++++++++++-------- 1 file changed, 177 insertions(+), 134 deletions(-) diff --git a/frontend/src/pages/accounts/AccountsPage.tsx b/frontend/src/pages/accounts/AccountsPage.tsx index 5cc9d7c..54bec34 100644 --- a/frontend/src/pages/accounts/AccountsPage.tsx +++ b/frontend/src/pages/accounts/AccountsPage.tsx @@ -117,7 +117,9 @@ const fmt = (v: string | number) => export function AccountsPage() { const [opened, { open, close }] = useDisclosure(false); const [adjustOpened, { open: openAdjust, close: closeAdjust }] = useDisclosure(false); + const [invEditOpened, { open: openInvEdit, close: closeInvEdit }] = useDisclosure(false); const [editing, setEditing] = useState(null); + const [editingInvestment, setEditingInvestment] = useState(null); const [adjustingAccount, setAdjustingAccount] = useState(null); const [search, setSearch] = useState(''); const [filterType, setFilterType] = useState(null); @@ -277,7 +279,73 @@ export function AccountsPage() { }, }); + // ── Investment edit form ── + const invForm = useForm({ + initialValues: { + name: '', + institution: '', + accountNumberLast4: '', + investmentType: 'cd', + fundType: 'operating', + principal: 0, + interestRate: 0, + maturityDate: null as Date | null, + purchaseDate: null as Date | null, + currentValue: 0, + notes: '', + }, + validate: { + name: (v) => (v.length > 0 ? null : 'Required'), + principal: (v) => (v > 0 ? null : 'Required'), + }, + }); + + const updateInvestmentMutation = useMutation({ + mutationFn: (values: any) => + api.put(`/investment-accounts/${editingInvestment!.id}`, { + name: values.name, + institution: values.institution || null, + account_number_last4: values.accountNumberLast4 || null, + investment_type: values.investmentType, + fund_type: values.fundType, + principal: values.principal, + interest_rate: values.interestRate || 0, + maturity_date: values.maturityDate ? values.maturityDate.toISOString().split('T')[0] : null, + purchase_date: values.purchaseDate ? values.purchaseDate.toISOString().split('T')[0] : null, + current_value: values.currentValue || values.principal, + notes: values.notes || null, + }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['investments'] }); + notifications.show({ message: 'Investment updated', color: 'green' }); + closeInvEdit(); + setEditingInvestment(null); + invForm.reset(); + }, + onError: (err: any) => { + notifications.show({ message: err.response?.data?.message || 'Error updating investment', color: 'red' }); + }, + }); + // ── Handlers ── + const handleEditInvestment = (inv: Investment) => { + setEditingInvestment(inv); + invForm.setValues({ + name: inv.name, + institution: inv.institution || '', + accountNumberLast4: inv.account_number_last4 || '', + investmentType: inv.investment_type, + fundType: inv.fund_type, + principal: parseFloat(inv.principal || '0'), + interestRate: parseFloat(inv.interest_rate || '0'), + maturityDate: inv.maturity_date ? new Date(inv.maturity_date) : null, + purchaseDate: inv.purchase_date ? new Date(inv.purchase_date) : null, + currentValue: parseFloat(inv.current_value || inv.principal || '0'), + notes: '', + }); + openInvEdit(); + }; + const handleEdit = (account: Account) => { setEditing(account); form.setValues({ @@ -436,7 +504,6 @@ export function AccountsPage() { Reserve ({activeAccounts.filter(a => a.fund_type === 'reserve').length + reserveInvestments.length}) - Investments ({investments.filter(i => i.is_active).length}) {showArchived && archivedAccounts.length > 0 && ( Archived ({archivedAccounts.length}) @@ -465,7 +532,7 @@ export function AccountsPage() { {operatingInvestments.length > 0 && ( <> - + )} @@ -482,14 +549,11 @@ export function AccountsPage() { {reserveInvestments.length > 0 && ( <> - + )} - - - {showArchived && ( )} + + {/* Investment Edit Modal */} + + {editingInvestment && ( +
updateInvestmentMutation.mutate(values))}> + + + + + + + + + + + + + + + +