`;
}
if (slvpl_domElements.pdfDownloadBtn) {
slvpl_domElements.pdfDownloadBtn.classList.remove('slvpl-hidden');
}
}
function slvpl_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 slvpl_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 (!slvpl_validateTab1() || !slvpl_validateTab2() || !slvpl_validateTab3()) {
alert("Please ensure all inputs are correctly filled before generating PDF.");
if (!slvpl_validateTab1()) slvpl_navigateToTab('slvpl-tab1');
else if (!slvpl_validateTab2()) slvpl_navigateToTab('slvpl-tab2');
else if (!slvpl_validateTab3()) slvpl_navigateToTab('slvpl-tab3');
return;
}
slvpl_calculateAndDisplayComparison();
if (slvpl_domElements.resultsContainer && slvpl_domElements.resultsContainer.innerHTML.includes("slvpl-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 { loanAmount, loanTermYears, studentLoan, personalLoan } = slvpl_loanData;
doc.setFontSize(18);
const primaryColorRGB = slvpl_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--slvpl-primary-color').trim());
const secondaryColorRGB = slvpl_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--slvpl-secondary-color').trim());
if (primaryColorRGB) doc.setTextColor(primaryColorRGB.r, primaryColorRGB.g, primaryColorRGB.b); else doc.setTextColor(25,118,210);
doc.text("Student Loan vs. Personal Loan Comparison", 105, 20, null, null, "center");
doc.setFontSize(11);
doc.setTextColor(51,51,51);
let startY = 30;
doc.text(`Loan Amount: ${slvpl_formatCurrency(loanAmount)} | Loan Term: ${loanTermYears} years`, 14, startY);
startY += 10;
const tableHeadFillColor = secondaryColorRGB ? [secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b] : [13,71,161];
const studentLoanColorArr = slvpl_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--slvpl-student-loan-color').trim()) || {r:46,g:125,b:50};
const personalLoanColorArr = slvpl_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--slvpl-personal-loan-color').trim()) || {r:255,g:143,b:0};
const tableColumnStyles = {
0: { cellWidth: 60, fontStyle: 'bold' },
1: { cellWidth: 'auto', textColor: [studentLoanColorArr.r, studentLoanColorArr.g, studentLoanColorArr.b] },
2: { cellWidth: 'auto', textColor: [personalLoanColorArr.r, personalLoanColorArr.g, personalLoanColorArr.b] }
};
const tableBody = [
["Est. Annual Interest Rate", slvpl_formatPercent(studentLoan.rate), slvpl_formatPercent(personalLoan.rate)],
["Total Loan Fees", slvpl_formatCurrency(studentLoan.totalFees), slvpl_formatCurrency(personalLoan.totalFees)],
["Monthly Payment (EMI)", slvpl_formatCurrency(studentLoan.calculated.emi), slvpl_formatCurrency(personalLoan.calculated.emi)],
["Total Interest Paid", slvpl_formatCurrency(studentLoan.calculated.totalInterest), slvpl_formatCurrency(personalLoan.calculated.totalInterest)],
["Total Finance Charge (Interest + Fees)", slvpl_formatCurrency(studentLoan.calculated.totalFinanceCharge), slvpl_formatCurrency(personalLoan.calculated.totalFinanceCharge)],
[{content: "Total Amount Repaid", styles: {fontStyle: 'bold'}},
{content: slvpl_formatCurrency(studentLoan.calculated.totalRepayment), styles: {fontStyle: 'bold'}},
{content: slvpl_formatCurrency(personalLoan.calculated.totalRepayment), styles: {fontStyle: 'bold'}}]
];
doc.autoTable({
startY: startY,
head: [['Feature', 'Student Loan', 'Personal Loan']],
body: tableBody,
theme: 'grid',
headStyles: { fillColor: tableHeadFillColor, textColor: 255, fontSize:10, fontStyle:'bold' },
columnStyles: tableColumnStyles,
styles: { fontSize: 9, cellPadding: 2.5 },
margin: { left: 14, right: 14 }
});
startY = doc.autoTable.previous.finalY + 12;
doc.setFontSize(11);
doc.setTextColor(secondaryColorRGB ? secondaryColorRGB.r : 13, secondaryColorRGB ? secondaryColorRGB.g : 71, secondaryColorRGB ? secondaryColorRGB.b : 161);
doc.text("Key Differences to Consider:", 14, startY); startY += 7;
doc.setFontSize(9);
doc.setTextColor(51,51,51);
const keyDifferences = [
"- Tax Deductibility: Student loan interest is often tax-deductible; personal loan interest typically is not for education.",
"- Repayment Flexibility: Student loans usually offer more options (IDR, deferment, forbearance) than personal loans.",
"- Grace Period: Often available for student loans post-graduation; rare for personal loans (repayment starts sooner).",
"- Use of Funds: Student loans are for education expenses; personal loans can be used for any purpose.",
"- Interest Rates: Federal student loans often have fixed rates. Personal loan rates vary widely with credit."
];
keyDifferences.forEach(item => {
const splitItem = doc.splitTextToSize(item, doc.internal.pageSize.width - 28);
doc.text(splitItem, 14, startY);
startY += (splitItem.length * (doc.getLineHeight() / doc.internal.scaleFactor * 0.85)) + 1.5;
});
startY += 5;
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("Student_vs_Personal_Loan_Comparison.pdf");
}
window.slvpl_switchTab = slvpl_switchTab;
window.slvpl_navigateToTab = slvpl_navigateToTab;
window.slvpl_generatePdf = slvpl_generatePdf;
window.slvpl_updateTotalStudentLoanFeesDisplay = slvpl_updateTotalStudentLoanFeesDisplay; // Expose if needed, though listeners are internal
window.slvpl_updateTotalPersonalLoanFeesDisplay = slvpl_updateTotalPersonalLoanFeesDisplay;