Full Leaderboard
| Rank | Affiliate | Clicks |
Conversions | CR% | Revenue |
Score |
${tableRows}
`;
document.getElementById('download-pdf-btn').addEventListener('click', handlePdfDownload);
lucide.createIcons();
}
async function handlePdfDownload() {
if (!lastResults) return;
const { jsPDF } = window.jspdf;
document.getElementById('pdf-generation-date').textContent = new Date().toLocaleDateString();
const rankIcons = ['🥇', '🥈', '🥉']; // Gold, Silver, Bronze emoji
document.getElementById('pdf-top-performers').innerHTML = lastResults.scoredData.slice(0, 3).map((aff, i) => `
${rankIcons[i]}
${aff.name}
Score: ${aff.score.toFixed(1)}
`).join('');
const tableHtml = `
| Rank | Affiliate |
Revenue | Score |
${lastResults.scoredData.map((aff, i) => `
| ${i + 1} | ${aff.name} |
$${aff.revenue.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})} | ${aff.score.toFixed(1)} |
`).join('')}
`;
document.getElementById('pdf-full-rankings-table').innerHTML = tableHtml;
try {
const canvas = await html2canvas(document.getElementById('pdf-content'), { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgProps = pdf.getImageProperties(imgData);
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
pdf.save('Affiliate_Performance_Scoreboard.pdf');
} catch (e) {
console.error("PDF generation failed:", e);
alert("An error occurred generating the PDF.");
}
}
// --- Event Listeners & Initialization ---
tabs.forEach((tab, index) => tab.btn.addEventListener('click', () => switchTab(index)));
prevBtn.addEventListener('click', () => switchTab(currentTab - 1));
nextBtn.addEventListener('click', () => switchTab(currentTab + 1));
generateBtn.addEventListener('click', handleGeneration);
addRowBtn.addEventListener('click', addRow);
affiliateTableBody.addEventListener('click', e => {
if (e.target.closest('.remove-row-btn')) removeRow(parseInt(e.target.closest('tr').dataset.id));
});
Object.values(weights).forEach(w => w.addEventListener('input', updateWeights));
switchTab(0);
updateNavButtons();
renderTable();
updateWeights();
lucide.createIcons();
});