`;
}
renderAgingChart(agingData) {
const maxAmount = Math.max(...Object.values(agingData));
this.dom.agingChart.innerHTML = Object.entries(agingData).map(([bucket, amount]) => `
`).join('');
}
renderStatusChart(statusData) {
const total = Object.values(statusData).reduce((sum, v) => sum + v, 0);
const colors = { 'Open': '#1e88e5', 'Paid': '#43a047', 'Promise to Pay': '#fdd835', 'Disputed': '#fb8c00' };
let gradientString = 'conic-gradient(';
let currentPercentage = 0;
this.dom.statusLegend.innerHTML = '';
Object.entries(statusData).forEach(([status, count]) => {
const percentage = total > 0 ? (count / total) * 100 : 0;
const color = colors[status];
if (percentage > 0) {
gradientString += `${color} ${currentPercentage}% ${currentPercentage + percentage}%, `;
currentPercentage += percentage;
}
this.dom.statusLegend.innerHTML += `${status} (${count}) `;
});
gradientString = gradientString.slice(0, -2) + ')';
this.dom.statusChart.style.background = gradientString;
}
renderTopOverdueTable(overdueAccounts) {
this.dom.topOverdueBody.innerHTML = overdueAccounts
.sort((a,b) => b.daysOverdue - a.daysOverdue)
.slice(0, 5) // Top 5
.map(acc => `
${acc.name}
$${acc.amount.toLocaleString()}
${acc.daysOverdue}
${acc.status}
`).join('');
if(overdueAccounts.length === 0) {
this.dom.topOverdueBody.innerHTML = 'No overdue accounts. Well done! ';
}
}
// --- PDF & Navigation ---
openTab(event, tabName) { this.state.activeTab = tabName; this.updateUI(); }
navigateTabs(dir) {
const i = this.TABS_ORDER.indexOf(this.state.activeTab);
let n = i;
if (dir === 'next' && i < this.TABS_ORDER.length - 1) n++;
if (dir === 'prev' && i > 0) n--;
this.openTab(null, this.TABS_ORDER[n]);
}
async generatePdf() {
if(this.state.activeTab !== 'dashboard') {
this.openTab(null, 'dashboard');
await new Promise(res => setTimeout(res, 50));
}
this.dom.downloadPdfBtn.disabled = true; this.dom.downloadPdfBtn.textContent = 'Generating...';
this.dom.container.classList.add('pdf-export-mode');
try {
const { jsPDF } = window.jspdf;
const canvas = await html2canvas(this.dom.pdfOutput, { scale: 2, useCORS: true, backgroundColor: '#ffffff' });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
const margin = 40;
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgWidth = pdfWidth - margin * 2;
const imgHeight = canvas.height * imgWidth / canvas.width;
pdf.addImage(imgData, 'PNG', margin, margin, imgWidth, imgHeight);
pdf.save(`Collections_Performance_Dashboard.pdf`);
} catch(e) {
console.error(e); alert('Error generating PDF.');
} finally {
this.dom.container.classList.remove('pdf-export-mode');
this.dom.downloadPdfBtn.disabled = false; this.dom.downloadPdfBtn.textContent = 'Download Dashboard as PDF';
}
}
}
const app = new CollectionsDashboard();
