Click "Add Beneficiary" to start.
`;
} else {
calculatorState.beneficiaries.forEach((b, index) => {
const beneficiaryRow = document.createElement('div');
beneficiaryRow.className = 'grid grid-cols-12 gap-2 items-center';
beneficiaryRow.innerHTML = `
$0.00
`;
elements.beneficiaryList.appendChild(beneficiaryRow);
});
}
updateBeneficiaryDistribution();
};
/**
* Updates the summary table in Tab 4 based on the beneficiary list.
*/
const updateBeneficiarySummaryTable = () => {
elements.summaryBeneficiaryTable.innerHTML = '';
const estateAfterTax = Math.max(0, (calculateTotal(elements.assetInputs) - calculateTotal(elements.liabilityInputs)) - calculateEstateTax(Math.max(0, (calculateTotal(elements.assetInputs) - calculateTotal(elements.liabilityInputs) - getNumericValue(elements.deductionInputs.marital) - getNumericValue(elements.deductionInputs.charitable)) - getNumericValue(elements.deductionInputs.federalExemption))));
if (calculatorState.beneficiaries.length === 0 || estateAfterTax <= 0) {
elements.summaryBeneficiaryTable.innerHTML = `
| No beneficiaries or estate value to distribute. |
`;
return;
}
calculatorState.beneficiaries.forEach(b => {
const amount = estateAfterTax * (b.percentage / 100);
const row = document.createElement('tr');
row.className = 'border-b';
row.innerHTML = `
${b.name || 'Unnamed'} |
${b.percentage}% |
${formatCurrency(amount)} |
`;
elements.summaryBeneficiaryTable.appendChild(row);
});
};
// --- EVENT HANDLERS --- //
/**
* Handles tab switching logic.
* @param {number} tabNumber The number of the tab to display.
*/
const showTab = (tabNumber) => {
calculatorState.currentTab = tabNumber;
// Hide all panes, deactivate all buttons
elements.tabPanes.forEach(pane => pane.style.display = 'none');
elements.tabNavigation.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
// Show the correct pane and activate its button
const activePane = document.getElementById(`tab-${tabNumber}`);
const activeBtn = elements.tabNavigation.querySelector(`[data-tab='${tabNumber}']`);
if (activePane) activePane.style.display = 'block';
if (activeBtn) activeBtn.classList.add('active');
// Update navigation button visibility
elements.prevBtn.style.display = tabNumber > 1 ? 'inline-block' : 'none';
elements.nextBtn.textContent = tabNumber < 4 ? 'Next Step' : 'Finish';
elements.nextBtn.style.display = tabNumber < 4 ? 'inline-block' : 'none';
// Re-run calculations when switching, especially important for the summary tab.
runAllCalculations();
};
elements.tabNavigation.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
const tabNumber = parseInt(e.target.getAttribute('data-tab'), 10);
showTab(tabNumber);
}
});
elements.nextBtn.addEventListener('click', () => {
if (calculatorState.currentTab < 4) {
showTab(calculatorState.currentTab + 1);
}
});
elements.prevBtn.addEventListener('click', () => {
if (calculatorState.currentTab > 1) {
showTab(calculatorState.currentTab - 1);
}
});
// Add event listeners to all financial inputs to trigger calculations.
const allInputs = [...elements.assetInputs, ...elements.liabilityInputs, ...Object.values(elements.deductionInputs)];
allInputs.forEach(input => {
input.addEventListener('input', runAllCalculations);
});
// Event delegation for beneficiary list actions (update, delete).
elements.beneficiaryList.addEventListener('input', (e) => {
const target = e.target;
if (target.tagName === 'INPUT') {
const index = parseInt(target.getAttribute('data-index'), 10);
const field = target.getAttribute('data-field');
const value = field === 'name' ? target.value : Math.max(0, parseInt(target.value, 10) || 0);
if (index >= 0 && index < calculatorState.beneficiaries.length) {
calculatorState.beneficiaries[index][field] = value;
updateBeneficiaryDistribution();
}
}
});
elements.beneficiaryList.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
const index = parseInt(e.target.getAttribute('data-index'), 10);
if (index >= 0 && index < calculatorState.beneficiaries.length) {
calculatorState.beneficiaries.splice(index, 1);
renderBeneficiaries();
}
}
});
elements.addBeneficiaryBtn.addEventListener('click', () => {
calculatorState.beneficiaries.push({ name: '', percentage: 0 });
renderBeneficiaries();
});
/**
* Handles the PDF download process using html2canvas and jsPDF.
*/
elements.downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
const pdfContent = elements.pdfContent;
// Temporarily ensure the element is ready for capture
pdfContent.style.width = '800px';
html2canvas(pdfContent, {
scale: 2, // Improve resolution
useCORS: true,
}).then(canvas => {
pdfContent.style.width = ''; // Revert style
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'px',
format: 'a4'
});
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const ratio = canvasWidth / canvasHeight;
const widthInPdf = pdfWidth - 40; // with some margin
const heightInPdf = widthInPdf / ratio;
pdf.addImage(imgData, 'PNG', 20, 20, widthInPdf, heightInPdf);
pdf.save('Estate_Planning_Summary.pdf');
});
});
// --- INITIALIZATION --- //
runAllCalculations(); // Run once on load to initialize all values.
renderBeneficiaries(); // Initial render for beneficiary section.
});