Please complete all previous tabs to view the APR calculation and comparison.
Please correct errors in Tab 1: Loan Details.
';
blairc_domElements.pdfDownloadBtn.classList.add('blairc-hidden');
return;
}
if (!blairc_validateTab2AndCalcFees()) {
blairc_domElements.resultsContainer.innerHTML = '
Please correct errors in Tab 2: Loan Fees.
';
blairc_domElements.pdfDownloadBtn.classList.add('blairc-hidden');
return;
}
// Fees are assumed to be financed (added to the principal for payment calculation)
const effectiveLoanPrincipal = blairc_loanDetails.loanAmount + blairc_loanDetails.totalFees;
blairc_loanDetails.monthlyPayment = blairc_calculateMonthlyPayment(
effectiveLoanPrincipal,
blairc_loanDetails.nominalAnnualRate,
blairc_loanDetails.termYears
);
const aprMonthlyRate = blairc_solveAPRMonthlyRate(
blairc_loanDetails.loanAmount, // APR is solved against the actual amount borrowed
blairc_loanDetails.numberOfMonths,
blairc_loanDetails.monthlyPayment // Payment which includes cost of fees
);
blairc_loanDetails.aprAnnual = aprMonthlyRate * 12 * 100;
// Handle cases where APR solver might return non-sensical results for extreme inputs
if (isNaN(blairc_loanDetails.aprAnnual) || !isFinite(blairc_loanDetails.aprAnnual)) {
blairc_loanDetails.aprAnnual = 0; // Or some indicator of error
console.warn("APR calculation resulted in NaN or Infinity. Defaulting to 0 or error display might be needed.");
}
blairc_loanDetails.totalAmountPaid = blairc_loanDetails.monthlyPayment * blairc_loanDetails.numberOfMonths;
blairc_loanDetails.totalFinanceCharge = blairc_loanDetails.totalAmountPaid - blairc_loanDetails.loanAmount;
let aprDisplay = blairc_formatPercent(blairc_loanDetails.aprAnnual);
if (blairc_loanDetails.aprAnnual > 200) { // Arbitrary high APR warning
aprDisplay += " (APR is very high, please double-check inputs and loan terms)";
} else if (blairc_loanDetails.aprAnnual < blairc_loanDetails.nominalAnnualRate && blairc_loanDetails.totalFees > 0) {
// This shouldn't happen if fees > 0, indicates solver issue or edge case
// aprDisplay += " (Review: APR lower than nominal rate with fees)";
}
blairc_domElements.resultsContainer.innerHTML = `
The Nominal Interest Rate (${blairc_formatPercent(blairc_loanDetails.nominalAnnualRate)}) is the base interest charged on your loan principal.
The Annual Percentage Rate (APR) (${aprDisplay}) provides a more complete picture of your loan's cost. It includes the nominal interest rate PLUS all associated loan fees (${blairc_formatCurrency(blairc_loanDetails.totalFees)}), expressed as an annual rate. APR is generally higher than the nominal rate when fees are involved and is a better metric for comparing different loan offers.
`;
blairc_domElements.pdfDownloadBtn.classList.remove('blairc-hidden');
}
function blairc_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 blairc_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 (!blairc_validateTab1() || !blairc_validateTab2AndCalcFees()) {
alert("Please ensure all inputs are correctly filled before generating PDF.");
if (!blairc_validateTab1()) blairc_navigateToTab('blairc-tab1');
else if (!blairc_validateTab2AndCalcFees()) blairc_navigateToTab('blairc-tab2');
return;
}
blairc_calculateAndDisplayAPR(); // Ensure data is fresh
if (blairc_domElements.resultsContainer.innerHTML.includes("blairc-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, nominalAnnualRate, termYears, totalFees, monthlyPayment, totalAmountPaid, totalFinanceCharge, aprAnnual } = blairc_loanDetails;
doc.setFontSize(18);
const primaryColorRGB = blairc_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--blairc-primary-color').trim());
const secondaryColorRGB = blairc_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--blairc-secondary-color').trim());
if (primaryColorRGB) doc.setTextColor(primaryColorRGB.r, primaryColorRGB.g, primaryColorRGB.b); else doc.setTextColor(0,90,156);
doc.text("Business Loan APR vs. Interest Rate Comparison", 105, 20, null, null, "center");
doc.setFontSize(12);
doc.setTextColor(51, 51, 51);
let startY = 35;
const tableHeadFillColor = secondaryColorRGB ? [secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b] : [0,51,102];
doc.setFontSize(14);
if (secondaryColorRGB) doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b); else doc.setTextColor(0,51,102);
doc.text("Loan Terms Summary", 14, startY); startY += 7;
doc.autoTable({
startY: startY, theme: 'grid', headStyles: { fillColor: tableHeadFillColor },
body: [
["Loan Amount Requested:", blairc_formatCurrency(loanAmount)],
["Nominal Annual Interest Rate:", blairc_formatPercent(nominalAnnualRate)],
["Loan Term:", `${termYears} years`],
["Total Loan Fees (Financed):", blairc_formatCurrency(totalFees)],
], margin: { left: 14, right: 14 }
});
startY = doc.autoTable.previous.finalY + 10;
doc.setFontSize(14);
if (secondaryColorRGB) doc.setTextColor(secondaryColorRGB.r, secondaryColorRGB.g, secondaryColorRGB.b); else doc.setTextColor(0,51,102);
doc.text("Calculated Results", 14, startY); startY += 7;
doc.autoTable({
startY: startY, theme: 'grid', headStyles: { fillColor: tableHeadFillColor },
body: [
["Monthly Payment:", blairc_formatCurrency(monthlyPayment)],
["Total Amount Repaid Over Loan Life:", blairc_formatCurrency(totalAmountPaid)],
["Total Finance Charge (Interest + Fees):", blairc_formatCurrency(totalFinanceCharge)],
[{content: "Calculated Annual Percentage Rate (APR):", styles: {fontStyle: 'bold'}},
{content: blairc_formatPercent(aprAnnual), styles: {fontStyle: 'bold', fontSize: 12, textColor: blairc_hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--blairc-accent-color').trim()) || [255,193,7]}}],
], margin: { left: 14, right: 14 }
});
startY = doc.autoTable.previous.finalY + 15;
doc.setFontSize(12);
doc.setTextColor(51,51,51);
doc.text("Understanding Your Rates:", 14, startY); startY += 7;
doc.setFontSize(10);
const explanation1 = `The Nominal Interest Rate (${blairc_formatPercent(nominalAnnualRate)}) is the base interest charged on your loan principal.`;
const explanation2 = `The Annual Percentage Rate (APR) (${blairc_formatPercent(aprAnnual)}) provides a more complete picture of your loan's cost. It includes the nominal interest rate PLUS all associated loan fees (${blairc_formatCurrency(totalFees)}), expressed as an annual rate. APR is generally higher than the nominal rate when fees are involved and is a better metric for comparing different loan offers.`;
const splitExplanation1 = doc.splitTextToSize(explanation1, doc.internal.pageSize.width - 28);
doc.text(splitExplanation1, 14, startY);
startY += (splitExplanation1.length * (doc.getLineHeight() / doc.internal.scaleFactor)) + 4;
const splitExplanation2 = doc.splitTextToSize(explanation2, doc.internal.pageSize.width - 28);
doc.text(splitExplanation2, 14, startY);
doc.setFontSize(10);
doc.setTextColor(150);
doc.text(`Report generated on: ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`, 14, doc.internal.pageSize.height - 10);
doc.save("Loan_APR_Comparison.pdf");
}
window.blairc_switchTab = blairc_switchTab;
window.blairc_navigateToTab = blairc_navigateToTab;
window.blairc_generatePdf = blairc_generatePdf;