Attendance Dashboard

Attendance Rate

${attendanceRate.toFixed(1)}%

`; } function renderStatusLists(data) { const statuses = { Present: [], Late: [], 'On Leave': [], Absent: [] }; data.forEach(r => { if(statuses[r.status]) statuses[r.status].push(r.employee_name); }); elements.statusListsContainer.innerHTML = Object.entries(statuses).map(([status, names]) => `

${status} (${names.length})

    ${names.map(n => `
  • ${n}
  • `).join('') || '
  • -
  • '}
`).join(''); } const renderChart = (id, type, data, options) => { if(charts[id]) charts[id].destroy(); charts[id] = new Chart(document.getElementById(id), { type, data, options }); }; function renderDepartmentChart(data) { const depts = [...new Set(employeeList.map(e => e.department))]; const statusByDept = depts.map(dept => { const deptData = data.filter(r => r.department === dept); return { Present: deptData.filter(r => r.status === 'Present' || r.status === 'Late').length, Absent: deptData.filter(r => r.status === 'Absent').length, 'On Leave': deptData.filter(r => r.status === 'On Leave').length }; }); renderChart('att-dept-chart', 'bar', { labels: depts, datasets: [ { label: 'Present', data: statusByDept.map(d => d.Present), backgroundColor: '#22c55e' }, { label: 'Absent', data: statusByDept.map(d => d.Absent), backgroundColor: '#ef4444' }, { label: 'On Leave', data: statusByDept.map(d => d['On Leave']), backgroundColor: '#3b82f6' } ] }, { responsive: true, maintainAspectRatio: false, scales: { x: { stacked: true }, y: { stacked: true, beginAtZero: true, ticks: {stepSize: 1} } } }); } function renderHistoricalTrendChart(today) { const trendData = []; for (let i = 29; i >= 0; i--) { const date = new Date(today); date.setDate(today.getDate() - i); const dateStr = date.toISOString().split('T')[0]; const dailyData = fullData.filter(r => r.date === dateStr); const onLeave = dailyData.filter(r => r.status === 'On Leave').length; const present = dailyData.filter(r => r.status === 'Present' || r.status === 'Late').length; const expected = employeeList.length - onLeave; trendData.push({ x: dateStr, y: expected > 0 ? (present / expected) * 100 : 0 }); } renderChart('att-trend-chart', 'line', { datasets: [{ label: 'Attendance %', data: trendData, borderColor: '#0ea5e9', tension: 0.1, fill: true, backgroundColor: 'rgba(14, 165, 233, 0.1)' }] }, { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: 'day' } }, y: { min: 0, max: 100, ticks: { callback: v => v + '%' } } } }); } window.attDownloadPDF = () => { html2canvas(document.getElementById('att-pdf-content'), { scale: 2 }).then(canvas => { const pdf = new jspdf.jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 40, 40, pdf.internal.pageSize.getWidth() - 80, 0); pdf.save(`Attendance_Report_${document.getElementById('att-selected-date').textContent}.pdf`); }); }; loadSampleData(); });
Scroll to Top