/* ═══ CYPHER-HR Reports Module ═══ */ const Reports = { async adminView() { try { const employees = await App.api('/api/employees'); return `

${icon('report', 20)} Generate Report

${dateInput('reportStart')}
${dateInput('reportEnd')}
`; } catch (err) { return `
${err.message}
`; } }, async employeeView() { return `

${icon('report', 20)} My Reports

${dateInput('reportStart')}
${dateInput('reportEnd')}
`; }, lastData: [], async generate() { const type = document.getElementById('reportType').value; const container = document.getElementById('reportResults'); container.innerHTML = '

Loading...

'; try { if (type === 'detailed') { const params = new URLSearchParams(); const empEl = document.getElementById('reportEmployee'); if (empEl && empEl.value) params.set('user_id', empEl.value); const start = parseDateInput('reportStart'); const end = parseDateInput('reportEnd'); const status = document.getElementById('reportStatus')?.value; if (start) params.set('start_date', start); if (end) params.set('end_date', end); if (status) params.set('status', status); const data = await App.api(`/api/reports/detailed?${params}`); this.lastData = data; container.innerHTML = `

Detailed Report (${data.length} records)

${data.length === 0 ? '

No records found

' : ` ${data.map(r => ``).join('')}
EmployeeTypeStartEndReasonStatusDepartment
${r.first_name} ${r.last_name} ${r.leave_type} ${App.formatDate(r.start_date)} ${App.formatDate(r.end_date)} ${r.reason || '—'} ${App.statusBadge(r.status)} ${r.department || '—'}
`}
`; } else { const params = new URLSearchParams(); const empEl = document.getElementById('reportEmployee'); if (empEl && empEl.value) params.set('user_id', empEl.value); params.set('year', document.getElementById('reportYear')?.value || new Date().getFullYear()); const data = await App.api(`/api/reports/summary?${params}`); this.lastData = data; const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; const grouped = {}; data.forEach(r => { const key = `${r.first_name} ${r.last_name}`; if (!grouped[key]) grouped[key] = {}; const m = months[parseInt(r.month) - 1]; if (!grouped[key][m]) grouped[key][m] = {}; grouped[key][m][r.status] = (grouped[key][m][r.status] || 0) + parseInt(r.count); }); container.innerHTML = `

Summary Report — ${document.getElementById('reportYear')?.value || new Date().getFullYear()}

${data.length === 0 ? '

No records found

' : Object.entries(grouped).map(([name, monthData]) => `

${name}

${Object.entries(monthData).map(([m, statuses]) => { const a = statuses.approved || 0; const r2 = statuses.rejected || 0; const p = statuses.pending || 0; return ``; }).join('')}
MonthApprovedRejectedPendingTotal
${m}${a}${r2}${p}${a+r2+p}
`).join('')}
`; } } catch (err) { container.innerHTML = `
${err.message}
`; } }, exportCSV() { if (!this.lastData || this.lastData.length === 0) { App.toast('Generate a report first', 'error'); return; } const type = document.getElementById('reportType').value; let csv, filename; if (type === 'detailed') { csv = 'Employee,Type,Start Date,End Date,Reason,Status,Department\n'; csv += this.lastData.map(r => `"${r.first_name} ${r.last_name}","${r.leave_type}","${App.formatDate(r.start_date)}","${App.formatDate(r.end_date)}","${(r.reason||'').replace(/"/g,'""')}","${r.status}","${r.department||''}"` ).join('\n'); filename = 'detailed_report.csv'; } else { csv = 'Employee,Month,Status,Count\n'; csv += this.lastData.map(r => `"${r.first_name} ${r.last_name}","${r.month}","${r.status}","${r.count}"` ).join('\n'); filename = 'summary_report.csv'; } const blob = new Blob([csv], { type: 'text/csv' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; a.click(); App.toast('Report exported'); } };