Attrition Analysis Dashboard

${all.length}

Total Attrition

${exited.length}

Attrition Rate

${attritionRate.toFixed(1)}%

Avg. Tenure of Exited

${avgTenureExited.toFixed(1)} mo

`; } const renderChart = (id, type, data, options) => { if(charts[id]) charts[id].destroy(); charts[id] = new Chart(document.getElementById(id), { type, data, options }); }; function renderAttritionByDeptChart(exited) { const byDept = exited.reduce((acc, e) => { acc[e.department] = (acc[e.department] || 0) + 1; return acc; }, {}); renderChart('attr-dept-chart', 'bar', { labels: Object.keys(byDept), datasets: [{ label: 'Number of Exited Employees', data: Object.values(byDept), backgroundColor: 'rgba(59, 130, 246, 0.7)' }] }, { responsive: true, maintainAspectRatio: false, indexAxis: 'y', plugins:{legend:{display:false}} } ); } function renderAttritionByTenureChart(exited) { const tenureBins = { "0-6 mo": 0, "7-12 mo": 0, "1-2 yr": 0, "2-5 yr": 0, "5+ yr": 0 }; exited.forEach(e => { if (e.tenure_months <= 6) tenureBins["0-6 mo"]++; else if (e.tenure_months <= 12) tenureBins["7-12 mo"]++; else if (e.tenure_months <= 24) tenureBins["1-2 yr"]++; else if (e.tenure_months <= 60) tenureBins["2-5 yr"]++; else tenureBins["5+ yr"]++; }); renderChart('attr-tenure-chart', 'bar', { labels: Object.keys(tenureBins), datasets: [{ label: 'Number of Exited Employees', data: Object.values(tenureBins), backgroundColor: 'rgba(22, 163, 74, 0.7)' }] }, { responsive: true, maintainAspectRatio: false, plugins:{legend:{display:false}} } ); } function renderReasonChart(exited) { const byReason = exited.filter(e => e.reason_for_leaving).reduce((acc, e) => { acc[e.reason_for_leaving] = (acc[e.reason_for_leaving] || 0) + 1; return acc; }, {}); renderChart('attr-reason-chart', 'doughnut', { labels: Object.keys(byReason), datasets: [{ data: Object.values(byReason) }] }, { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } } } ); } function renderSalaryChart(all) { const depts = [...new Set(all.map(e => e.department))]; const avgSalaries = { Active: depts.map(dept => { const deptEmps = all.filter(e => e.department === dept && e.attrition_status === 'Active'); return deptEmps.length > 0 ? deptEmps.reduce((sum, e) => sum + e.salary_usd, 0) / deptEmps.length : 0; }), Exited: depts.map(dept => { const deptEmps = all.filter(e => e.department === dept && e.attrition_status === 'Exited'); return deptEmps.length > 0 ? deptEmps.reduce((sum, e) => sum + e.salary_usd, 0) / deptEmps.length : 0; }) }; renderChart('attr-salary-chart', 'bar', { labels: depts, datasets: [ { label: 'Active', data: avgSalaries.Active, backgroundColor: 'rgba(34, 211, 238, 0.7)' }, { label: 'Exited', data: avgSalaries.Exited, backgroundColor: 'rgba(249, 115, 22, 0.7)' } ]}, { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } }, scales: { y: { ticks: { callback: v => '$' + (v/1000) + 'k' } } } } ); } window.attrDownloadPDF = () => { html2canvas(document.getElementById('attr-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('Attrition_Analysis_Dashboard.pdf'); }); }; loadSampleData(); });
Scroll to Top