`).join('')}
`;
}
renderCalendar() {
this.dom.calendarGrid.innerHTML = '';
const year = this.state.year;
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
for (let month = 0; month < 12; month++) {
const monthContainer = document.createElement('div');
monthContainer.className = 'month-container';
const firstDay = new Date(year, month, 1);
const daysInMonth = new Date(year, month + 1, 0).getDate();
let startingDay = firstDay.getDay(); // 0 = Sunday
if (startingDay === 0) startingDay = 7; // Adjust to start week on Monday if desired, but 0=Sun is standard
let dayHtml = `Employee ${this.state.absenceTypes.map(t => `${t} `).join('')}Total `;
body.innerHTML = '';
this.state.employees.forEach(emp => {
let totalDays = 0;
const row = document.createElement('tr');
let rowHtml = `${emp.name} `;
this.state.absenceTypes.forEach(type => {
const daysForType = this.state.absences
.filter(ab => ab.employeeId === emp.id && ab.type === type)
.reduce((sum, ab) => sum + ab.days, 0);
rowHtml += `${daysForType} `;
totalDays += daysForType;
});
rowHtml += `${totalDays} `;
row.innerHTML = rowHtml;
body.appendChild(row);
});
}
// --- NAVIGATION & PDF ---
openTab(event, tabName) {
this.state.activeTab = tabName;
this.updateUI();
}
navigateTabs(direction) {
const currentIndex = this.TABS_ORDER.indexOf(this.state.activeTab);
let newIndex = currentIndex;
if (direction === 'next' && currentIndex < this.TABS_ORDER.length - 1) newIndex++;
if (direction === 'prev' && currentIndex > 0) newIndex--;
this.state.activeTab = this.TABS_ORDER[newIndex];
this.updateUI();
}
async generatePdf() {
const { jsPDF } = window.jspdf;
const pdfOutputElement = this.dom.pdfOutput;
this.dom.downloadPdfBtn.disabled = true;
this.dom.downloadPdfBtn.textContent = 'Generating...';
try {
const canvas = await html2canvas(pdfOutputElement, { scale: 2, useCORS: true, logging: false });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const canvasAspectRatio = canvas.width / canvas.height;
const margin = 40;
const imgWidth = pdfWidth - (margin * 2);
const imgHeight = imgWidth / canvasAspectRatio;
let heightLeft = imgHeight;
let position = margin;
pdf.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
heightLeft -= (pdfHeight - margin * 2);
while (heightLeft > 0) {
position = -heightLeft - margin;
pdf.addPage();
pdf.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
heightLeft -= pdfHeight;
}
const fileName = `Absence_Dashboard_${this.state.teamName.replace(/\s+/g, '_')}_${this.state.year}.pdf`;
pdf.save(fileName);
} catch (error) {
console.error("PDF Generation Error:", error);
alert("Sorry, an error occurred while creating the PDF.");
} finally {
this.dom.downloadPdfBtn.disabled = false;
this.dom.downloadPdfBtn.textContent = 'Download Dashboard as PDF';
}
}
}
const app = new AbsenceManager();
${monthNames[month]} ${year}
`;
dayHtml += '';
['S', 'M', 'T', 'W', 'T', 'F', 'S'].forEach(d => dayHtml += `
';
monthContainer.innerHTML = dayHtml;
this.dom.calendarGrid.appendChild(monthContainer);
}
}
renderEmployeeSummary() {
const head = this.dom.summaryTableHead;
const body = this.dom.summaryTableBody;
head.innerHTML = `${d}
`);
for (let i = 0; i < startingDay; i++) { dayHtml += ''; }
for (let day = 1; day <= daysInMonth; day++) {
const currentDate = new Date(year, month, day);
const dateStr = currentDate.toISOString().split('T')[0];
const todayStr = new Date().toISOString().split('T')[0];
let classes = 'calendar-day';
if(dateStr === todayStr) classes += ' today';
const absencesOnDay = this.state.absences.filter(ab => {
const start = new Date(ab.startDate);
const end = new Date(ab.endDate);
return currentDate >= start && currentDate <= end;
});
let markers = '';
if(absencesOnDay.length > 0) {
markers = `
${absencesOnDay.map(ab => ``).join('')}
`;
}
dayHtml += `${day}${markers}
`;
}
dayHtml += '