Legal Expense Budgeting Tool

Legal Expense Budgeting Tool

Plan, track, and manage your legal spending with precision.

Expense Category / Matter Budgeted ($) Actual Spent ($) Variance ($) Actions

Overall Variance

$${formatCurrency(totalVariance)}

`; }; const renderBudgetTable = () => { budgetTableBody.innerHTML = ''; if (expenses.length === 0) { budgetTableBody.innerHTML = `No expense items found. Add one in the 'Manage Expenses' tab.`; return; } expenses.forEach(item => { const variance = item.budgeted - item.spent; let varianceColor = 'text-slate-700'; if (variance > 0) varianceColor = 'text-green-600 font-semibold'; if (variance < 0) varianceColor = 'text-red-600 font-semibold'; const row = document.createElement('tr'); row.className = 'border-b border-slate-200 hover:bg-slate-50'; row.innerHTML = ` ${item.category} $${formatCurrency(item.budgeted)} $${formatCurrency(item.spent)} $${formatCurrency(variance)} `; budgetTableBody.appendChild(row); }); }; // --- FORM & DATA LOGIC --- const clearForm = () => { form.reset(); expenseIdInput.value = ''; saveExpenseBtn.textContent = 'Save Item'; }; const saveExpense = () => { const expenseData = { category: expenseCategoryInput.value.trim(), budgeted: parseFloat(budgetedAmountInput.value) || 0, spent: parseFloat(actualAmountInput.value) || 0, }; if (!expenseData.category) { alert('Expense Category is required.'); return; } const id = expenseIdInput.value; if (id) { // Update const index = expenses.findIndex(e => e.id == id); expenses[index] = { ...expenses[index], ...expenseData }; } else { // Add new expenseData.id = nextExpenseId++; expenses.push(expenseData); } clearForm(); renderAll(); showTab(0); }; const editExpense = (id) => { const item = expenses.find(e => e.id == id); if (item) { expenseIdInput.value = item.id; expenseCategoryInput.value = item.category; budgetedAmountInput.value = item.budgeted; actualAmountInput.value = item.spent; saveExpenseBtn.textContent = 'Update Item'; showTab(1); } }; const deleteExpense = (id) => { if (confirm('Are you sure you want to delete this expense item?')) { const row = budgetTableBody.querySelector(`.delete-btn[data-id='${id}']`).closest('tr'); row.classList.add('deleting'); setTimeout(() => { expenses = expenses.filter(e => e.id != id); renderAll(); }, 300); } }; // --- UI & NAVIGATION LOGIC --- const showTab = (tabIndex) => { tabContents.forEach(c => c.classList.add('hidden')); tabButtons.forEach(b => b.classList.replace('active', 'inactive')); document.getElementById(`tab-content-${tabIndex}`).classList.remove('hidden'); document.querySelector(`.tab-button[data-tab='${tabIndex}']`).classList.replace('inactive', 'active'); updateNavButtons(); currentTab = tabIndex; }; const updateNavButtons = () => { prevBtn.style.visibility = currentTab === 0 ? 'hidden' : 'visible'; nextBtn.style.visibility = currentTab === totalTabs - 1 ? 'hidden' : 'visible'; }; const navigateTabs = (direction) => { const nextTabIndex = currentTab + direction; if (nextTabIndex >= 0 && nextTabIndex < totalTabs) showTab(nextTabIndex); }; // --- PDF GENERATION --- const downloadPDF = () => { const { jsPDF } = window.jspdf; const pdfContentArea = document.getElementById('pdf-content-area'); const totalBudgeted = expenses.reduce((sum, item) => sum + item.budgeted, 0); const totalSpent = expenses.reduce((sum, item) => sum + item.spent, 0); const totalVariance = totalBudgeted - totalSpent; let pdfHtml = `

Legal Expense Budget Report

${expenses.map(e => ` `).join('')}
Expense Category Budgeted ($) Actual Spent ($) Variance ($)
${e.category || ''} ${formatCurrency(e.budgeted)} ${formatCurrency(e.spent)} ${formatCurrency(e.budgeted - e.spent)}
Total $${formatCurrency(totalBudgeted)} $${formatCurrency(totalSpent)} $${formatCurrency(totalVariance)}
`; pdfContentArea.innerHTML = pdfHtml; pdfContentArea.classList.remove('hidden'); html2canvas(pdfContentArea, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgProps = pdf.getImageProperties(imgData); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight); pdf.save('Legal_Expense_Budget_Report.pdf'); pdfContentArea.innerHTML = ''; pdfContentArea.classList.add('hidden'); }); }; // --- EVENT LISTENERS --- prevBtn.addEventListener('click', () => navigateTabs(-1)); nextBtn.addEventListener('click', () => navigateTabs(1)); tabButtons.forEach(button => button.addEventListener('click', () => showTab(parseInt(button.dataset.tab)))); saveExpenseBtn.addEventListener('click', saveExpense); clearFormBtn.addEventListener('click', clearForm); downloadPdfBtn.addEventListener('click', downloadPDF); budgetTableBody.addEventListener('click', (e) => { const target = e.target; if (target.classList.contains('edit-btn')) { editExpense(target.dataset.id); } if (target.classList.contains('delete-btn')) { deleteExpense(target.dataset.id); } }); // --- INITIALIZATION --- renderAll(); showTab(0); });
Scroll to Top