`;
}
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]) => `
`).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();
});
${status} (${names.length})
- ${names.map(n => `
- ${n} `).join('') || '
- - '}
