Average Filing Rate
${avgFilingRate.toFixed(2)}%
`;
}
const renderChart = (id, type, data, options) => {
const ctx = document.getElementById(id)?.getContext('2d');
if(!ctx) return;
if(charts[id]) charts[id].destroy();
charts[id] = new Chart(ctx, { type, data, options });
};
function renderCharts(data) {
const totalFilings = data.reduce((sum, r) => sum + r.eviction_filings, 0);
const totalEvictions = data.reduce((sum, r) => sum + r.actual_evictions, 0);
renderChart('eviction-funnel-chart', 'bar', {
labels: ['Filings', 'Actual Evictions'],
datasets: [{ label: 'Count', data: [totalFilings, totalEvictions], backgroundColor: ['#6366f1', '#a78bfa'] }]
}, { responsive: true, maintainAspectRatio: false, indexAxis: 'y', plugins: { legend: { display: false } } });
const filingsByRace = {
White: data.reduce((s, r) => s + r.filings_by_race_white, 0),
Black: data.reduce((s, r) => s + r.filings_by_race_black, 0),
Hispanic: data.reduce((s, r) => s + r.filings_by_race_hispanic, 0),
Asian: data.reduce((s, r) => s + r.filings_by_race_asian, 0),
};
renderChart('eviction-race-chart', 'doughnut', {
labels: Object.keys(filingsByRace),
datasets: [{ data: Object.values(filingsByRace) }]
}, { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } } });
}
function renderLocationTable(data) {
data.sort((a,b) => b.filing_rate - a.filing_rate);
elements.locationTbody.innerHTML = data.map(row => `
| ${row.location} |
${row.renter_households.toLocaleString()} |
${row.eviction_filings.toLocaleString()} |
${row.actual_evictions.toLocaleString()} |
${row.filing_rate.toFixed(2)}% |
${row.eviction_rate.toFixed(2)}% |
`).join('');
}
window.evictionDownloadPDF = () => {
html2canvas(document.getElementById('eviction-pdf-content'), { scale: 2 }).then(canvas => {
const pdf = new jspdf.jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 40, 40, pdf.internal.pageSize.getWidth() - 80, 0);
pdf.save('Eviction_Rates_Dashboard.pdf');
});
};
loadSampleData();
});