People Analytics Dashboard

People Analytics Dashboard

Analyze workforce composition, performance, and turnover.

Key Workforce Metrics

Headcount by Department

Performance Distribution

Employee Roster

Employee ID Department Performance Score Hire Date Status

Manage Employee Data

${totalHeadcount}

Gender Diversity

${diversityRatio}

Avg. Performance

${avgPerformance.toFixed(1)} / 5

Turnover Rate (YTD)

${turnoverRate.toFixed(1)}%

`; }; const renderDataTable = () => { dataTableBody.innerHTML = ''; const sortedEmployees = [...state.employees].sort((a, b) => new Date(b.hireDate) - new Date(a.hireDate)); sortedEmployees.forEach(e => { const status = e.termDate ? 'Inactive' : 'Active'; const row = ` ${e.id} ${e.department} ${e.performance} ${e.hireDate} ${status} `; dataTableBody.innerHTML += row; }); }; const renderCharts = () => { const activeEmployees = state.employees.filter(e => !e.termDate); // Headcount by Department const headcountByDept = activeEmployees.reduce((acc, e) => { acc[e.department] = (acc[e.department] || 0) + 1; return acc; }, {}); const deptLabels = Object.keys(headcountByDept); const deptData = deptLabels.map(label => headcountByDept[label]); if (departmentChart) departmentChart.destroy(); departmentChart = new Chart(departmentCanvas.getContext('2d'), { type: 'bar', data: { labels: deptLabels, datasets: [{ label: 'Headcount', data: deptData, backgroundColor: 'rgba(14, 165, 233, 0.7)' }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } } } }); // Performance Distribution const perfDist = activeEmployees.reduce((acc, e) => { if (e.performance <= 2) acc['Low']++; else if (e.performance <= 4) acc['Medium']++; else acc['High']++; return acc; }, { 'Low': 0, 'Medium': 0, 'High': 0 }); if (performanceChart) performanceChart.destroy(); performanceChart = new Chart(performanceCanvas.getContext('2d'), { type: 'doughnut', data: { labels: ['Low (1-2)', 'Medium (3-4)', 'High (5)'], datasets: [{ data: [perfDist['Low'], perfDist['Medium'], perfDist['High']], backgroundColor: ['#f87171', '#facc15', '#4ade80'] }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' } } } }); }; const renderConfigRows = () => { configRowsContainer.innerHTML = ''; const sortedEmployees = [...state.employees].sort((a,b) => b.id.localeCompare(a.id)); sortedEmployees.forEach(e => { configRowsContainer.innerHTML += `
`.replaceAll('class="config-input"', 'class="config-input w-full border-gray-300 rounded-md shadow-sm"'); }); addConfigEventListeners(); }; // --- EVENT HANDLERS --- const handleConfigChange = (e) => { const id = e.target.dataset.id; const field = e.target.dataset.field; const value = e.target.value; const employee = state.employees.find(emp => emp.id === id); if (employee) { if (field === 'performance') employee[field] = parseInt(value, 10); else if (field === 'termDate' && value === '') employee[field] = null; else employee[field] = value; } renderAll(); }; const handleAddEmployee = () => { const newId = 'E' + (Math.max(...state.employees.map(e => parseInt(e.id.substring(1)))) + 1); const today = new Date().toISOString().split('T')[0]; state.employees.push({ id: newId, department: "Unassigned", gender: "Male", performance: 3, hireDate: today, termDate: null }); renderAll(); }; const handleRemoveEmployee = (e) => { const id = e.target.dataset.id; state.employees = state.employees.filter(emp => emp.id !== id); renderAll(); }; const addConfigEventListeners = () => { document.querySelectorAll('.config-input').forEach(input => input.addEventListener('change', handleConfigChange)); document.querySelectorAll('.remove-btn').forEach(button => button.addEventListener('click', handleRemoveEmployee)); }; const handleDownloadPdf = () => { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-content'); document.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'hidden'); Chart.defaults.animation = false; html2canvas(pdfContent, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }).then(canvas => { document.querySelectorAll('.no-print').forEach(el => el.style.visibility = 'visible'); Chart.defaults.animation = true; const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pdfWidth - 20; const imgHeight = canvas.height * imgWidth / canvas.width; pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight); pdf.save('People-Analytics-Dashboard.pdf'); }); }; // --- TABBING LOGIC --- let currentTabIndex = 0; const updateTabButtons = () => { prevTabBtn.disabled = currentTabIndex === 0; nextTabBtn.disabled = currentTabIndex === tabContents.length - 1; }; const switchTab = (index) => { tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); tabButtons[index].classList.add('active'); tabContents[index].classList.add('active'); currentTabIndex = index; updateTabButtons(); }; tabButtons.forEach((button, index) => button.addEventListener('click', () => switchTab(index))); prevTabBtn.addEventListener('click', () => { if (currentTabIndex > 0) switchTab(currentTabIndex - 1); }); nextTabBtn.addEventListener('click', () => { if (currentTabIndex < tabContents.length - 1) switchTab(currentTabIndex + 1); }); // --- INITIALIZATION --- if (kpiContainer && addEmployeeBtn && downloadPdfBtn) { addEmployeeBtn.addEventListener('click', handleAddEmployee); downloadPdfBtn.addEventListener('click', handleDownloadPdf); renderAll(); updateTabButtons(); } else { console.error("Essential dashboard elements could not be found."); } });
Scroll to Top