${formatCurrency(s.revenue)}
`;
resultsContainer.appendChild(resultDiv);
});
// Update recommendation
if (bestScenario.name === 'Baseline' || bestScenario.uplift <= 0) {
recommendationText.textContent = 'Based on the current inputs, neither strategy provides a significant revenue lift. Consider adjusting prices or expected take rates.';
} else {
recommendationText.textContent = `The ${bestScenario.name} shows the highest potential, with a projected revenue uplift of ${formatCurrency(bestScenario.uplift)}.`;
}
recommendationBox.classList.remove('hidden');
};
const formatCurrency = (value) => {
return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
};
const showNotification = (message) => {
const banner = document.getElementById('notification-banner');
const messageEl = document.getElementById('notification-message');
messageEl.textContent = message;
banner.classList.remove('hidden', 'translate-y-10', 'opacity-0');
setTimeout(() => {
banner.classList.add('translate-y-10', 'opacity-0');
setTimeout(() => banner.classList.add('hidden'), 300);
}, 3000);
};
async function downloadPDF() {
if (!resultsContainer.innerHTML.includes('div')) {
showNotification("Please calculate results before downloading.");
return;
}
// --- Populate PDF Data ---
document.getElementById('pdf-date').textContent = new Date().toLocaleDateString('en-US');
// Inputs Table
const inputsTable = document.getElementById('pdf-inputs-table');
inputsTable.innerHTML = `
| Main Product Price | ${formatCurrency(parseFloat(inputs.mainPrice.value))} |
| # of Customers | ${parseInt(inputs.customers.value).toLocaleString()} |
| Upsell Price | ${formatCurrency(parseFloat(inputs.upsellPrice.value))} |
| Upsell Take Rate | ${inputs.upsellRate.value}% |
| Cross-Sell Price | ${formatCurrency(parseFloat(inputs.crossSellProductPrice.value))} |
| Cross-Sell Take Rate | ${inputs.crossSellRate.value}% |
`;
// Results Table (re-calculate for data consistency)
const mainPrice = parseFloat(inputs.mainPrice.value) || 0;
const customers = parseInt(inputs.customers.value) || 0;
const upsellPrice = parseFloat(inputs.upsellPrice.value) || 0;
const upsellRate = parseFloat(inputs.upsellRate.value) / 100 || 0;
const crossSellPrice = parseFloat(inputs.crossSellProductPrice.value) || 0;
const crossSellRate = parseFloat(inputs.crossSellRate.value) / 100 || 0;
const baselineRevenue = mainPrice * customers;
const upsoldCustomers = customers * upsellRate;
const nonUpsoldCustomers = customers - upsoldCustomers;
const upsellRevenue = (upsoldCustomers * upsellPrice) + (nonUpsoldCustomers * mainPrice);
const crossSoldCustomers = customers * crossSellRate;
const crossSellRevenue = baselineRevenue + (crossSoldCustomers * crossSellPrice);
const scenarios = [
{ name: 'Baseline', revenue: baselineRevenue, uplift: 0 },
{ name: 'Upsell Strategy', revenue: upsellRevenue, uplift: upsellRevenue - baselineRevenue },
{ name: 'Cross-Sell Strategy', revenue: crossSellRevenue, uplift: crossSellRevenue - baselineRevenue },
];
const bestScenario = scenarios.reduce((max, current) => current.revenue > max.revenue ? current : max, scenarios[0]);
const resultsTableBody = document.querySelector('#pdf-results-table tbody');
resultsTableBody.innerHTML = '';
scenarios.forEach(s => {
const tr = document.createElement('tr');
if(s.name === bestScenario.name) tr.className = 'highlight';
tr.innerHTML = `
${s.name} |
${formatCurrency(s.revenue)} |
${formatCurrency(s.uplift)} |
`;
resultsTableBody.appendChild(tr);
});
// Recommendation
document.getElementById('pdf-recommendation-text').textContent = recommendationText.textContent;
// --- Generate PDF ---
const pdfContentWrapper = document.getElementById('pdf-content-wrapper');
pdfContentWrapper.classList.remove('hidden');
try {
const { jsPDF } = window.jspdf;
const canvas = await html2canvas(pdfContentWrapper, { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF('p', 'mm', 'a4');
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgProps = pdf.getImageProperties(imgData);
const imgHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, imgHeight);
pdf.save('Pricing_Strategy_Analysis.pdf');
} catch(error) {
console.error("Failed to generate PDF:", error);
showNotification("An error occurred generating the PDF.");
} finally {
pdfContentWrapper.classList.add('hidden');
}
}
// --- Event Listeners & Initial Setup ---
Object.values(inputs).forEach(input => {
input.addEventListener('input', calculate);
});
pdfBtn.addEventListener('click', downloadPDF);
// Initial calculation
calculate();
});