Budget & Financial Management Dashboard
An overview of your income, expenses, and budget for the current month.
Total Income
$0
Total Expenses
$0
Net Savings
$0
Monthly Cash Flow
Expense Breakdown
Budget vs. Actuals
Recent Transactions
| Date | Description | Category | Amount |
|---|
Manage Budgets
| Category | Budget | Action |
|---|
Add Transaction
| Date | Description | Category | Amount | Action |
|---|
Error: A required library is missing.
'; return; } // --- DATA MANAGEMENT --- let budgets = JSON.parse(localStorage.getItem('bfm_budgets')) || []; let transactions = JSON.parse(localStorage.getItem('bfm_transactions')) || []; const getSampleData = () => { const sampleBudgets = [ { category: 'Housing', amount: 2200 }, { category: 'Transportation', amount: 500 }, { category: 'Food', amount: 800 }, { category: 'Utilities', amount: 300 }, { category: 'Entertainment', amount: 250 }, { category: 'Savings', amount: 1000 } ]; const sampleTransactions = []; const today = new Date(); const year = today.getFullYear(); const month = today.getMonth(); const createDate = (day) => new Date(year, month, day).toISOString().split('T')[0]; sampleTransactions.push( { id: 't1', date: createDate(1), desc: 'Paycheck', amount: 3500, type: 'Income', category: 'Salary' }, { id: 't2', date: createDate(1), desc: 'Rent', amount: 2200, type: 'Expense', category: 'Housing' }, { id: 't3', date: createDate(2), desc: 'Electricity Bill', amount: 120, type: 'Expense', category: 'Utilities' }, { id: 't4', date: createDate(3), desc: 'Groceries', amount: 180.50, type: 'Expense', category: 'Food' }, { id: 't5', date: createDate(5), desc: 'Gasoline', amount: 55.75, type: 'Expense', category: 'Transportation' }, { id: 't6', date: createDate(6), desc: 'Movie Night', amount: 45, type: 'Expense', category: 'Entertainment' }, { id: 't7', date: createDate(7), desc: 'Internet Bill', amount: 80, type: 'Expense', category: 'Utilities' }, { id: 't8', date: createDate(8), desc: 'Stock Dividend', amount: 150, type: 'Income', category: 'Investments' } ); budgets = sampleBudgets; transactions = sampleTransactions; }; if (budgets.length === 0 && transactions.length === 0) { getSampleData(); } const saveState = () => { localStorage.setItem('bfm_budgets', JSON.stringify(budgets)); localStorage.setItem('bfm_transactions', JSON.stringify(transactions)); }; // --- CHART INSTANCES --- let cashflowChart, expenseChart, budgetChart; // --- ELEMENT REFERENCES & UTILITIES --- const tabButtons = document.querySelectorAll('.bfm-tab-button'); const tabContents = document.querySelectorAll('.bfm-tab-content'); const nextBtn = document.getElementById('bfm-next-btn'); const prevBtn = document.getElementById('bfm-prev-btn'); const formatCurrency = (val) => val.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); const currentMonth = new Date().getMonth(); const currentYear = new Date().getFullYear(); // --- RENDER FUNCTIONS --- const renderAll = () => { try { const currentMonthTransactions = transactions.filter(t => { const d = new Date(t.date + 'T00:00:00'); return d.getMonth() === currentMonth && d.getFullYear() === currentYear; }); renderKPIs(currentMonthTransactions); renderCashflowChart(); renderExpenseChart(currentMonthTransactions); renderBudgetChart(currentMonthTransactions); renderTransactionTables(); updateNavButtons(); } catch(error) { console.error("Dashboard rendering failed:", error); } }; const renderKPIs = (data) => { const totalIncome = data.filter(t=>t.type==='Income').reduce((s,t)=>s+t.amount, 0); const totalExpense = data.filter(t=>t.type==='Expense').reduce((s,t)=>s+t.amount, 0); document.getElementById('bfm-income-kpi').textContent = formatCurrency(totalIncome); document.getElementById('bfm-expense-kpi').textContent = formatCurrency(totalExpense); const netEl = document.getElementById('bfm-net-kpi'); netEl.textContent = formatCurrency(totalIncome - totalExpense); netEl.className = (totalIncome - totalExpense) >= 0 ? 'net positive' : 'net negative'; }; const renderCashflowChart = () => { const monthlyData = transactions.reduce((acc, t) => { const month = t.date.substring(0, 7); if (!acc[month]) acc[month] = { income: 0, expense: 0 }; if (t.type === 'Income') acc[month].income += t.amount; else acc[month].expense += t.amount; return acc; }, {}); const sortedMonths = Object.keys(monthlyData).sort(); const options = { chart: { type: 'bar', height: 350, stacked: false }, series: [ { name: 'Income', data: sortedMonths.map(m => monthlyData[m].income) }, { name: 'Expense', data: sortedMonths.map(m => monthlyData[m].expense) } ], xaxis: { categories: sortedMonths }, yaxis: { labels: { formatter: val => formatCurrency(val) } }, colors: ['var(--bfm-success-color)', 'var(--bfm-danger-color)'], dataLabels: { enabled: false } }; if(cashflowChart) cashflowChart.destroy(); document.querySelector("#bfm-cashflow-chart").innerHTML = ''; cashflowChart = new ApexCharts(document.querySelector("#bfm-cashflow-chart"), options); cashflowChart.render(); }; const renderExpenseChart = (data) => { const expensesByCategory = data.filter(t=>t.type === 'Expense').reduce((acc, t) => { acc[t.category] = (acc[t.category] || 0) + t.amount; return acc; }, {}); const options = { chart: { type: 'donut', height: 350 }, series: Object.values(expensesByCategory), labels: Object.keys(expensesByCategory), legend: { position: 'bottom' } }; if(expenseChart) expenseChart.destroy(); document.querySelector("#bfm-expense-category-chart").innerHTML = ''; expenseChart = new ApexCharts(document.querySelector("#bfm-expense-category-chart"), options); expenseChart.render(); }; const renderBudgetChart = (data) => { const seriesData = []; const categories = []; budgets.forEach(b => { const actual = data.filter(t=>t.category === b.category && t.type === 'Expense').reduce((s,t)=>s+t.amount, 0); seriesData.push({ budget: b.amount, actual }); categories.push(b.category); }); const options = { chart: { type: 'bar', height: 350 }, series: [ { name: 'Actual Spending', data: seriesData.map(d=>d.actual) }, { name: 'Budgeted Amount', data: seriesData.map(d=>d.budget) } ], xaxis: { categories: categories }, yaxis: { labels: { formatter: val => formatCurrency(val) } }, plotOptions: { bar: { horizontal: true } }, colors: ['var(--bfm-secondary-color)', '#bdc3c7'], dataLabels: { enabled: false } }; if(budgetChart) budgetChart.destroy(); document.querySelector("#bfm-budget-chart").innerHTML = ''; budgetChart = new ApexCharts(document.querySelector("#bfm-budget-chart"), options); budgetChart.render(); }; const renderTransactionTables = () => { const recentTbody = document.getElementById('bfm-recent-transactions-tbody'); recentTbody.innerHTML = ''; transactions.sort((a,b) => new Date(b.date) - new Date(a.date)).slice(0,5).forEach(t => { const amountClass = t.type === 'Income' ? 'income' : 'expense'; recentTbody.innerHTML += `