Affiliate Network Management Dashboard

Affiliate Network Management Dashboard

Oversee affiliate performance, manage commissions, and track payouts.

Affiliate Roster

Affiliate Status Sales ($) Comm. Rate (%) Comm. Owed ($) Actions

Top 5 Affiliates by Sales

Top 5 Affiliates by Commission Owed

$${totalOwed.toLocaleString('en-US', {minimumFractionDigits:2})}

`; }; const renderPayoutHistory = () => { payoutHistoryContainer.innerHTML = payoutHistory.length > 0 ? payoutHistory.map(p => `
Paid $${p.amount.toFixed(2)} to ${p.affiliateName} on ${p.date}
`).join('') : `

No recent payouts.

`; }; const renderCharts = () => { const sortedBySales = [...affiliates].sort((a,b) => b.sales - a.sales).slice(0, 5); const sortedByCommission = [...affiliates].map(a => ({...a, owed: (a.sales * a.rate/100) - a.paid})) .sort((a,b) => b.owed - a.owed).slice(0,5); if (salesChart) salesChart.destroy(); salesChart = new Chart(document.getElementById('sales-chart').getContext('2d'), { type: 'bar', data: { labels: sortedBySales.map(a => a.name), datasets: [{ label: 'Total Sales ($)', data: sortedBySales.map(a => a.sales), backgroundColor: 'rgba(59, 130, 246, 0.7)' }] }, options: { indexAxis: 'y', plugins: { legend: {display: false} } } }); if (commissionChart) commissionChart.destroy(); commissionChart = new Chart(document.getElementById('commission-chart').getContext('2d'), { type: 'bar', data: { labels: sortedByCommission.map(a => a.name), datasets: [{ label: 'Commission Owed ($)', data: sortedByCommission.map(a => a.owed), backgroundColor: 'rgba(239, 68, 68, 0.7)' }] }, options: { indexAxis: 'y', plugins: { legend: {display: false} } } }); }; const handleTableUpdate = e => { const target = e.target; if(target.dataset.id && target.dataset.field) { const id = parseInt(target.dataset.id); const field = target.dataset.field; const value = target.type === 'number' ? parseFloat(target.value) : target.value; const affiliate = affiliates.find(a => a.id === id); if(affiliate) { affiliate[field] = value; renderAll(); } } }; const handleLogPayout = e => { if(e.target.classList.contains('log-payout-btn')){ const id = parseInt(e.target.dataset.id); const affiliate = affiliates.find(a => a.id === id); if (affiliate) { const owed = (affiliate.sales * affiliate.rate / 100) - affiliate.paid; if (owed > 0) { affiliate.paid += owed; payoutHistory.unshift({ affiliateName: affiliate.name, amount: owed, date: new Date().toISOString().split('T')[0] }); renderAll(); } } } }; const handleAddAffiliate = () => { const nameInput = document.getElementById('new-affiliate-name'); const rateInput = document.getElementById('new-commission-rate'); const name = nameInput.value.trim(); const rate = parseFloat(rateInput.value) || 10; if (name) { const newAffiliate = { id: affiliates.length > 0 ? Math.max(...affiliates.map(a => a.id)) + 1 : 1, name: name, status: 'Pending', sales: 0, rate: rate, paid: 0 }; affiliates.push(newAffiliate); nameInput.value = ''; rateInput.value = '10'; renderAll(); showTab('dashboard'); // Switch to dashboard to see the new entry } else { alert("Please enter an affiliate name."); } }; const generatePDF = () => { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-content'); const pdfBtnContainer = document.getElementById('pdf-button-container'); if (!pdfContent || !pdfBtnContainer) return; pdfContent.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'hidden'); pdfBtnContainer.style.display = 'none'; html2canvas(pdfContent, { scale: 2, useCORS: true }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'l', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pdfWidth - 20; const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.setFontSize(22); pdf.setFont('helvetica', 'bold'); pdf.text('Affiliate Network Dashboard Report', pdfWidth / 2, 15, { align: 'center' }); pdf.addImage(imgData, 'PNG', 10, 25, imgWidth, imgHeight); pdf.save('affiliate-dashboard-report.pdf'); pdfContent.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'visible'); pdfBtnContainer.style.display = 'block'; }).catch(err => { console.error("Error generating PDF:", err); pdfContent.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'visible'); pdfBtnContainer.style.display = 'block'; }); }; // --- Event Listeners --- tabBtnDashboard.addEventListener('click', () => showTab('dashboard')); tabBtnConfig.addEventListener('click', () => showTab('config')); prevBtn.addEventListener('click', () => showTab('dashboard')); nextBtn.addEventListener('click', () => showTab('config')); affiliatesTableBody.addEventListener('change', handleTableUpdate); affiliatesTableBody.addEventListener('click', handleLogPayout); addAffiliateBtn.addEventListener('click', handleAddAffiliate); downloadPdfBtn.addEventListener('click', generatePDF); // --- Initial Setup --- renderAll(); showTab('dashboard'); });
Scroll to Top