`;
if (mbslp_domElements.pdfDownloadBtn) {
mbslp_domElements.pdfDownloadBtn.classList.remove('mbslp-hidden');
}
}
function mbslp_hexToRgb(hex) {
if (!hex || typeof hex !== 'string') return null;
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; });
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null;
}
function mbslp_generatePdf() {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined' || typeof window.jspdf.jsPDF.API === 'undefined' || typeof window.jspdf.jsPDF.API.autoTable === 'undefined') {
alert("PDF generation library is not loaded. Please try again later."); return;
}
if (!mbslp_validateTab1() || !mbslp_validateTab2() || !mbslp_validateTab3()) {
alert("Please ensure all inputs are correctly filled before generating PDF.");
if (!mbslp_validateTab1()) mbslp_navigateToTab('mbslp-tab1');
else if (!mbslp_validateTab2()) mbslp_navigateToTab('mbslp-tab2');
else if (!mbslp_validateTab3()) mbslp_navigateToTab('mbslp-tab3');
return;
}
mbslp_calculateAndDisplaySummary();
if (mbslp_domElements.resultsContainer && mbslp_domElements.resultsContainer.innerHTML.includes("mbslp-error-message")) {
alert("Cannot generate PDF due to errors in input or calculation. Please correct them."); return;
}
const ActualJsPDF = window.jspdf.jsPDF;
const doc = new ActualJsPDF();
const { income, expenses, studentLoanPayment, summary } = mbslp_budgetData;
doc.setFontSize(18);
const primaryColorRGB = mbslp_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--mbslp-primary-color').trim()) || {r:30,g:136,b:229};
const secondaryColorRGB = mbslp_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--mbslp-secondary-color').trim()) || {r:21,g:101,b:192};
doc.setTextColor(primaryColorRGB.r, primaryColorRGB.g, primaryColorRGB.b);
doc.text("Monthly Budget Summary", 105, 22, null, null, "center");
doc.setFontSize(12);
doc.setTextColor(38,50,56);
let startY = 35;
const tableHeadFillColor = [secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b];
// Income Section
doc.setFontSize(13);
doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b);
doc.text("Monthly Income", 14, startY); startY += 7;
doc.autoTable({
startY: startY, theme: 'grid', headStyles: {fillColor: tableHeadFillColor, textColor:255, fontSize:10},
body: [
["Primary Income:", mbslp_formatCurrency(income.primary)],
["Other Income:", mbslp_formatCurrency(income.other)],
[{content: "Total Monthly Income:", styles:{fontStyle:'bold'}}, {content: mbslp_formatCurrency(income.total), styles:{fontStyle:'bold'}}],
], margin: { left: 14, right: 14 }, styles: { fontSize: 9, cellPadding: 2.5 }, columnStyles: {0:{fontStyle:'bold'}}
});
startY = doc.autoTable.previous.finalY + 10;
// Expenses Section
doc.setFontSize(13);
doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b);
doc.text("Monthly Living Expenses", 14, startY); startY += 7;
doc.autoTable({
startY: startY, theme: 'grid', headStyles: {fillColor: tableHeadFillColor, textColor:255, fontSize:10},
body: [
["Housing:", mbslp_formatCurrency(expenses.housing)],
["Utilities:", mbslp_formatCurrency(expenses.utilities)],
["Food & Groceries:", mbslp_formatCurrency(expenses.food)],
["Transportation:", mbslp_formatCurrency(expenses.transportation)],
["Personal & Health:", mbslp_formatCurrency(expenses.personalHealth)],
["Savings & Investments (Planned):", mbslp_formatCurrency(expenses.savings)],
["Other Regular Expenses:", mbslp_formatCurrency(expenses.other)],
[{content: "Total Monthly Living Expenses:", styles:{fontStyle:'bold'}}, {content: mbslp_formatCurrency(expenses.total), styles:{fontStyle:'bold'}}],
], margin: { left: 14, right: 14 }, styles: { fontSize: 9, cellPadding: 2.5 }, columnStyles: {0:{fontStyle:'bold'}}
});
startY = doc.autoTable.previous.finalY + 10;
// Student Loan & Summary Section
doc.setFontSize(13);
doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b);
doc.text("Student Loan & Net Summary", 14, startY); startY += 7;
const netRemainingColor = summary.netRemaining >= 0 ? mbslp_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--mbslp-accent-color').trim()) || {r:67,g:160,b:71}
: mbslp_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--mbslp-danger-color').trim()) || {r:229,g:57,b:53};
doc.autoTable({
startY: startY, theme: 'grid', headStyles: {fillColor: tableHeadFillColor, textColor:255, fontSize:10},
body: [
["Total Monthly Student Loan Payment(s):", mbslp_formatCurrency(studentLoanPayment)],
["Income After Living Expenses:", mbslp_formatCurrency(summary.incomeAfterLivingExpenses)],
[{content: "Net Income / (Shortfall) After All Payments:", styles:{fontStyle:'bold'}},
{content: mbslp_formatCurrency(summary.netRemaining), styles:{fontStyle:'bold', textColor: [netRemainingColor.r, netRemainingColor.g, netRemainingColor.b]}}],
], margin: { left: 14, right: 14 }, styles: { fontSize: 9, cellPadding: 2.5 }, columnStyles: {0:{fontStyle:'bold'}}
});
startY = doc.autoTable.previous.finalY + 10;
if (income.total > 0) {
doc.setFontSize(13);
doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b);
doc.text("Expense Allocation (% of Total Income)", 14, startY); startY += 7;
doc.autoTable({
startY: startY, theme: 'grid', headStyles: {fillColor: tableHeadFillColor, textColor:255, fontSize:10},
body: [
["Living Expenses:", mbslp_formatPercent(expenses.total, income.total)],
["Student Loan Payments:", mbslp_formatPercent(studentLoanPayment, income.total)],
["Remaining/Discretionary:", mbslp_formatPercent(summary.netRemaining > 0 ? summary.netRemaining : 0, income.total)],
], margin: { left: 14, right: 14 }, styles: { fontSize: 9, cellPadding: 2.5 }, columnStyles: {0:{fontStyle:'bold'}}
});
startY = doc.autoTable.previous.finalY + 10;
}
doc.setFontSize(9);
doc.setTextColor(120);
doc.text(`Report generated on: ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`, 14, doc.internal.pageSize.height - 10);
doc.save("Monthly_Budget_Summary_StudentLoans.pdf");
}
window.mbslp_switchTab = mbslp_switchTab;
window.mbslp_navigateToTab = mbslp_navigateToTab;
window.mbslp_generatePdf = mbslp_generatePdf;
// Expose update functions if they were meant for direct calls, though listeners are better
window.mbslp_updateTotalIncomeDisplay = mbslp_updateTotalIncomeDisplay;
window.mbslp_updateTotalLivingExpensesDisplay = mbslp_updateTotalLivingExpensesDisplay;