'use client'; interface Account { id: string; name: string; type: 'checking' | 'savings' | 'credit_card' | 'mortgage' | 'investment' | 'loan'; balance: number; color: string; } interface Envelope { id: string; name: string; allocated: number; spent: number; color: string; } interface Transaction { id: string; amount: number; date: Date; envelopeId?: string; } interface DashboardChartsProps { accounts: Account[]; envelopes: Envelope[]; transactions: Transaction[]; visibleCharts?: { incomeExpenses: boolean; budgetAlerts: boolean; assetsDebt: boolean; envelopeSpending: boolean; accountBalances: boolean; dailySpending: boolean; }; } const assetTypes: Account['type'][] = ['checking', 'savings', 'investment']; const debtTypes: Account['type'][] = ['credit_card', 'mortgage', 'loan']; export default function DashboardCharts({ accounts, envelopes, transactions, visibleCharts = { incomeExpenses: true, budgetAlerts: true, assetsDebt: true, envelopeSpending: true, accountBalances: true, dailySpending: true, } }: DashboardChartsProps) { // Separate accounts into assets and debt const assetAccounts = accounts.filter(acc => assetTypes.includes(acc.type)); const debtAccounts = accounts.filter(acc => debtTypes.includes(acc.type)); const totalAssets = assetAccounts.reduce((sum, acc) => sum + acc.balance, 0); const totalDebt = Math.abs(debtAccounts.reduce((sum, acc) => sum + acc.balance, 0)); // Calculate spending by envelope const envelopeSpending = envelopes.map(env => ({ name: env.name, spent: Math.abs(env.spent), allocated: env.allocated, color: env.color, percentage: env.allocated > 0 ? (Math.abs(env.spent) / env.allocated) * 100 : 0 })).sort((a, b) => b.spent - a.spent); // Find envelopes with alerts (overspent or near limit >80%) const envelopeAlerts = envelopes.filter(env => { const percentage = env.allocated > 0 ? (Math.abs(env.spent) / env.allocated) * 100 : 0; return percentage >= 80; }).sort((a, b) => { const aPerc = a.allocated > 0 ? (Math.abs(a.spent) / a.allocated) * 100 : 0; const bPerc = b.allocated > 0 ? (Math.abs(b.spent) / b.allocated) * 100 : 0; return bPerc - aPerc; }); // Calculate total balance across accounts const totalBalance = accounts.reduce((sum, acc) => sum + acc.balance, 0); const accountBalances = accounts.map(acc => ({ name: acc.name, balance: acc.balance, color: acc.color, percentage: totalBalance > 0 ? (acc.balance / totalBalance) * 100 : 0 })); // Calculate income vs expenses (this month) const now = new Date(); const monthStart = new Date(now.getFullYear(), now.getMonth(), 1); const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0); const monthTransactions = transactions.filter(t => { const txDate = t.date instanceof Date ? t.date : new Date(t.date); return txDate >= monthStart && txDate <= monthEnd; }); const totalIncome = monthTransactions .filter(t => t.amount > 0 && !t.envelopeId) .reduce((sum, t) => sum + t.amount, 0); const totalExpenses = monthTransactions .filter(t => t.amount < 0) .reduce((sum, t) => sum + Math.abs(t.amount), 0); const netIncome = totalIncome - totalExpenses; // Calculate spending over time (last 30 days) const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); const recentTransactions = transactions.filter(t => { const txDate = t.date instanceof Date ? t.date : new Date(t.date); return txDate >= thirtyDaysAgo; }); const dailySpending: { [key: string]: number } = {}; recentTransactions.forEach(t => { const txDate = t.date instanceof Date ? t.date : new Date(t.date); const dateKey = txDate.toISOString().split('T')[0]; if (t.amount < 0) { dailySpending[dateKey] = (dailySpending[dateKey] || 0) + Math.abs(t.amount); } }); const spendingData = Object.entries(dailySpending) .sort((a, b) => a[0].localeCompare(b[0])) .slice(-7); // Last 7 days const maxDailySpending = Math.max(...spendingData.map(([_, amount]) => amount), 1); return (
{env.name}
{isOverspent ? `Over budget by $${(Math.abs(env.spent) - env.allocated).toFixed(2)}` : `${percentage.toFixed(0)}% of budget used`}
✓ All envelopes are within budget
)}Over budget by ${(env.spent - env.allocated).toFixed(2)}
)}No envelope spending data yet.
)}No account data yet.
)}No data yet. Add transactions to see history.
; })()}No spending data for the last 7 days.
)}