Personal Finance Dashboard
Financial Snapshot
Net Worth
$0.00
Total Assets
$0.00
Total Liabilities
$0.00
Budget Period
N/A
Total Budgeted
$0.00
Total Spent
$0.00
Budget Difference
$0.00
Savings Goals Overview
No active savings goals.
Net Worth Calculation
Total Assets
$0.00
Total Liabilities
$0.00
Calculated Net Worth
$0.00
Assets
No assets added yet.
Liabilities
No liabilities added yet.
Budget & Actual Expenses
Budget Categories
No budget categories defined yet.
Expense Breakdown Chart
No expense data to display chart.
Savings Goals
No savings goals added yet.
No assets added yet.
'; return; } const table = document.createElement('table'); table.className = 'pfd-table'; table.innerHTML = `No liabilities added yet.
'; return; } const table = document.createElement('table'); table.className = 'pfd-table'; table.innerHTML = `No budget categories defined yet.
'; return; } const table = document.createElement('table'); table.className = 'pfd-table pfd-budget-table'; table.innerHTML = `No savings goals added yet.
'); } console.log('No savings goals, showing no-data message'); return; } savingsGoals.sort((a, b) => a.name.localeCompare(b.name)); savingsGoals.forEach(goal => { const progress = goal.target > 0 ? Math.min((goal.current / goal.target) * 100, 100) : 0; const li = document.createElement('li'); li.setAttribute('data-id', goal.id); li.innerHTML = `${escapeHtml(goal.name)}
No active savings goals.
'; console.log('No savings goals in overview'); return; } const goalsGrid = document.createElement('div'); goalsGrid.className = 'pfd-grid'; savingsGoals.slice(0, 4).forEach(goal => { const progress = goal.target > 0 ? Math.min((goal.current / goal.target) * 100, 100) : 0; const card = document.createElement('div'); card.className = 'pfd-summary-card'; card.innerHTML = `${escapeHtml(goal.name)}
${progress.toFixed(1)}%
${formatCurrency(goal.current)} / ${formatCurrency(goal.target)}
`; goalsGrid.appendChild(card); }); overviewGoalsSummary.appendChild(goalsGrid); if (savingsGoals.length > 4) { overviewGoalsSummary.innerHTML += ``; overviewGoalsSummary.querySelector('.pfd-switch-tab-link').addEventListener('click', (e) => { e.preventDefault(); console.log('Goals link clicked'); const targetTab = e.target.getAttribute('data-tab-target'); tabs.forEach(t => t.classList.remove('active')); tabContents.forEach(c => c.classList.remove('active')); const targetButton = dashboardContainer.querySelector(`.pfd-tab-button[data-tab="${targetTab}"]`); const targetContent = document.getElementById(`tab-${targetTab}`); if (targetButton && targetContent) { targetButton.classList.add('active'); targetContent.classList.add('active'); console.log(`Switched to goals tab via link`); } else { console.error(`Failed to switch to goals tab: button or content not found`); } }); } } console.log('Overview updated successfully'); } catch (e) { console.error('Error in updateOverview:', e); } } // PDF Export function handleDownloadPdf() { console.log('Handling PDF download'); try { if (!window.jspdf) { console.error('jsPDF not loaded, cannot generate PDF'); alert('PDF generation is unavailable due to a loading issue.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); const styles = getComputedStyle(document.documentElement); const primaryColor = styles.getPropertyValue('--pfd-primary-color').trim() || '#2a9d8f'; const infoColor = styles.getPropertyValue('--pfd-info-color').trim() || '#457b9d'; const textColor = styles.getPropertyValue('--pfd-text-color').trim() || '#343a40'; const whiteColor = styles.getPropertyValue('--pfd-white-color').trim() || '#fff'; const successColor = styles.getPropertyValue('--pfd-success-color').trim() || '#2a9d8f'; const dangerColor = styles.getPropertyValue('--pfd-danger-color').trim() || '#e76f51'; let currentY = 20; const leftMargin = 15; const rightMargin = doc.internal.pageSize.width - 15; const centerPage = doc.internal.pageSize.width / 2; doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text('Personal Finance Summary', centerPage, currentY, { align: 'center' }); currentY += 15; doc.setFontSize(14); doc.setTextColor(infoColor); doc.text('Net Worth Summary', leftMargin, currentY); currentY += 8; doc.setDrawColor(styles.getPropertyValue('--pfd-border-color').trim()); doc.line(leftMargin, currentY - 2, rightMargin, currentY - 2); currentY += 8; const { totalAssets, totalLiabilities, netWorth } = calculateNetWorth(); doc.setFontSize(11); doc.setTextColor(textColor); doc.text(`Total Assets: ${formatCurrency(totalAssets)}`, leftMargin, currentY); currentY += 7; doc.text(`Total Liabilities: ${formatCurrency(totalLiabilities)}`, leftMargin, currentY); currentY += 7; doc.setFont('helvetica', 'bold'); doc.setTextColor(netWorth >= 0 ? successColor : dangerColor); doc.text(`Net Worth: ${formatCurrency(netWorth)}`, leftMargin, currentY); doc.setFont('helvetica', 'normal'); currentY += 15; doc.setFontSize(14); doc.setTextColor(infoColor); doc.text(`Budget Summary (${budget.period || 'N/A'})`, leftMargin, currentY); currentY += 8; doc.line(leftMargin, currentY - 2, rightMargin, currentY - 2); currentY += 8; const { totalBudgeted, totalActual, difference } = calculateBudgetTotals(); doc.setFontSize(11); doc.setTextColor(textColor); doc.text(`Total Budgeted: ${formatCurrency(totalBudgeted)}`, leftMargin, currentY); currentY += 7; doc.text(`Total Spent: ${formatCurrency(totalActual)}`, leftMargin, currentY); currentY += 7; doc.setFont('helvetica', 'bold'); doc.setTextColor(difference >= 0 ? successColor : dangerColor); doc.text(`Difference: ${formatCurrency(difference)}`, leftMargin, currentY); doc.setFont('helvetica', 'normal'); currentY += 10; if (budget.categories.length > 0) { const budgetTableData = budget.categories.map(cat => [ cat.name, formatCurrency(cat.budgeted), formatCurrency(cat.actual), formatCurrency(cat.budgeted - cat.actual) ]); budgetTableData.push([ { content: 'Total', styles: { fontStyle: 'bold' } }, { content: formatCurrency(totalBudgeted), styles: { fontStyle: 'bold', halign: 'right' } }, { content: formatCurrency(totalActual), styles: { fontStyle: 'bold', halign: 'right' } }, { content: formatCurrency(difference), styles: { fontStyle: 'bold', halign: 'right', textColor: difference >= 0 ? successColor : dangerColor } } ]); doc.autoTable({ head: [['Category', 'Budgeted', 'Actual', 'Difference']], body: budgetTableData, startY: currentY, theme: 'grid', headStyles: { fillColor: infoColor, textColor: whiteColor, fontStyle: 'bold' }, styles: { fontSize: 9, cellPadding: 2, textColor: textColor }, columnStyles: { 1: { halign: 'right' }, 2: { halign: 'right' }, 3: { halign: 'right' } }, didParseCell: function (data) { if (data.section === 'body' && data.column.index === 3) { const rawValue = budget.categories[data.row.index]?.budgeted - budget.categories[data.row.index]?.actual; if (rawValue !== undefined && rawValue < 0) { data.cell.styles.textColor = dangerColor; } else if (rawValue !== undefined && rawValue >= 0) { data.cell.styles.textColor = successColor; } } } }); currentY = doc.lastAutoTable.finalY + 10; } if (expenseChartInstance && budget.categories.filter(cat => cat.actual > 0).length > 0) { try { const chartImage = expenseChartCanvas.toDataURL('image/png', 1.0); const chartHeight = 80; const chartWidth = 100; if (currentY + chartHeight > doc.internal.pageSize.height - 20) { doc.addPage(); currentY = 20; } doc.setFontSize(14); doc.setTextColor(infoColor); doc.text('Expense Breakdown Chart', leftMargin, currentY); currentY += 8; doc.line(leftMargin, currentY - 2, rightMargin, currentY - 2); currentY += 5; const imgX = centerPage - chartWidth / 2; doc.addImage(chartImage, 'PNG', imgX, currentY, chartWidth, chartHeight); currentY += chartHeight + 10; } catch (error) { console.error("Error adding chart to PDF:", error); doc.setTextColor(dangerColor); doc.text('Error rendering chart image.', leftMargin, currentY); currentY += 10; } } if (savingsGoals.length > 0) { if (currentY + 20 > doc.internal.pageSize.height - 20) { doc.addPage(); currentY = 20; } doc.setFontSize(14); doc.setTextColor(infoColor); doc.text('Savings Goals Progress', leftMargin, currentY); currentY += 8; doc.line(leftMargin, currentY - 2, rightMargin, currentY - 2); currentY += 8; const goalTableData = savingsGoals.map(goal => { const progress = goal.target > 0 ? Math.min((goal.current / goal.target) * 100, 100) : 0; return [ goal.name, formatCurrency(goal.target), formatCurrency(goal.current), `${progress.toFixed(1)}%` ]; }); doc.autoTable({ head: [['Goal Name', 'Target ($)', 'Current ($)', 'Progress']], body: goalTableData, startY: currentY, theme: 'grid', headStyles: { fillColor: infoColor, textColor: whiteColor, fontStyle: 'bold' }, styles: { fontSize: 9, cellPadding: 2, textColor: textColor }, columnStyles: { 1: { halign: 'right' }, 2: { halign: 'right' }, 3: { halign: 'right' } } }); } doc.save('personal-finance-summary.pdf'); console.log('PDF generated successfully'); } catch (e) { console.error('Error in handleDownloadPdf:', e); } } // Event Listeners Setup function setupEventListeners() { console.log('Setting up event listeners'); try { if (addAssetForm) addAssetForm.addEventListener('submit', handleAddAsset); if (assetsTableContainer) assetsTableContainer.addEventListener('click', handleRemoveAsset); if (addLiabilityForm) addLiabilityForm.addEventListener('submit', handleAddLiability); if (liabilitiesTableContainer) liabilitiesTableContainer.addEventListener('click', handleRemoveLiability); if (budgetPeriodInput) budgetPeriodInput.addEventListener('change', handleBudgetPeriodChange); if (addBudgetCategoryForm) addBudgetCategoryForm.addEventListener('submit', handleAddBudgetCategory); if (budgetTableContainer) { budgetTableContainer.addEventListener('click', handleRemoveBudgetCategory); budgetTableContainer.addEventListener('change', handleActualBudgetChange); } if (addGoalForm) addGoalForm.addEventListener('submit', handleAddGoal); if (goalsListUl) { goalsListUl.addEventListener('click', handleRemoveGoal); goalsListUl.addEventListener('click', handleGoalCurrentChange); } if (downloadPdfButton) downloadPdfButton.addEventListener('click', handleDownloadPdf); console.log('Event listeners attached successfully'); } catch (e) { console.error('Error in setupEventListeners:', e); } } // Initialization function init() { console.log('init called'); try { console.log('Loading assets'); assets = loadData('pfd_assets', []); console.log('Loading liabilities'); liabilities = loadData('pfd_liabilities', []); console.log('Loading budget'); budget = loadData('pfd_budget', { period: "", categories: [] }); console.log('Loading savings goals'); savingsGoals = loadData('pfd_savingsGoals', []); console.log('Rendering net worth'); renderNetWorth(); console.log('Rendering budget'); renderBudget(); console.log('Rendering savings goals'); renderSavingsGoals(); console.log('Updating overview'); updateOverview(); console.log('Setting up event listeners'); setupEventListeners(); console.log('Setting budget period input'); if (budgetPeriodInput) { budgetPeriodInput.value = budget.period; } else { console.error('budgetPeriodInput not found'); } console.log('Initialization completed'); } catch (e) { console.error('Error during initialization:', e.message, e.stack); throw e; // Rethrow to catch in outer try-catch } } // Start the application try { console.log('Starting initialization'); setupTabs(); // Call setupTabs first to ensure tabs work init(); } catch (e) { console.error('Failed to initialize dashboard:', e.message, e.stack); } });Take control of your financial future with WorkToolz.com’s intuitive Personal Finance Dashboard. Designed for everyday users, this powerful tool simplifies the complexities of managing your money, helping you achieve your financial goals with ease. Forget about confusing jargon and complicated spreadsheets; our dashboard presents your financial snapshot in a clear, natural, and easy-to-understand format.
The Personal Finance Dashboard provides a comprehensive overview of your financial health, allowing you to track your net worth, total assets, and total liabilities at a glance. Understand exactly where your money is going with our detailed budget and expenses section. You can set up budget periods, monitor your total budgeted amounts against your actual spending, and quickly identify any budget differences. This clear visualization empowers you to make informed decisions about your expenditures and adjust your habits to align with your financial objectives.
Beyond tracking, our dashboard helps you plan for the future by enabling you to set and monitor savings goals. Whether you’re saving for a down payment on a house, a dream vacation, or simply building an emergency fund, the Personal Finance Dashboard keeps your goals in sight and motivates you to stay on track. The tool is designed to be user-friendly, ensuring that even those new to financial management can navigate its features effortlessly. We believe that managing your money should be straightforward and stress-free, and our dashboard is built to reflect that philosophy.
Your financial data is stored locally in your browser, providing you with peace of mind regarding your privacy. There’s no need to worry about sensitive information being stored on external servers. However, remember that clearing your browser data will remove your saved information, so always keep that in mind when managing your financial records. The Personal Finance Dashboard is your personal guide to financial clarity, helping you understand your current situation, plan for what’s ahead, and ultimately achieve financial freedom. Start your journey towards better money management today with WorkToolz.com.
