feat(reports): DATEV-Monatsblatt-Button im Zeiterfassungs-Tab

Neuer Button "DATEV-Monatsblatt" neben CSV/Excel/PDF im time-Tab von
ReportsPage. Nutzt den bestehenden Mitarbeiter-Filter + den Monat aus
dateFrom, lädt GET /reports/datev-monthly/export als PDF herunter.
Manager müssen einen einzelnen Mitarbeiter wählen (kein Sammel-Export
möglich, da 1 Blatt = 1 Mitarbeiter/Monat).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CviFgc739S89xS97pvjszj
This commit is contained in:
2026-08-06 22:25:45 +02:00
co-authored by Claude Sonnet 5
parent 8a2f512112
commit 59a0305a75
+25
View File
@@ -200,6 +200,24 @@ export function ReportsPage() {
a.download = `${type}_${dateFrom}_${dateTo}.${format}`; a.click()
}
const downloadDatev = async () => {
if (isManager && !filterUser) { setError('DATEV-Monatsblatt: bitte oben einen einzelnen Mitarbeiter auswählen.'); return }
const uid = filterUser || user?.id
if (!uid) { setError('Bitte einen Mitarbeiter auswählen.'); return }
const d = new Date(dateFrom)
const year = d.getFullYear()
const month = d.getMonth() + 1
const token = localStorage.getItem('access_token')
const res = await fetch(
`/api/v1/reports/datev-monthly/export?user_id=${uid}&year=${year}&month=${month}`,
{ headers: { Authorization: `Bearer ${token}` } }
)
if (!res.ok) { setError('DATEV-Export fehlgeschlagen'); return }
const blob = await res.blob()
const a = document.createElement('a'); a.href = URL.createObjectURL(blob)
a.download = `datev_stundenaufzeichnung_${year}_${String(month).padStart(2, '0')}.pdf`; a.click()
}
const setQuick = (from: string, to: string) => { setDateFrom(from); setDateTo(to) }
const hasResult = !!(timeReport || absenceReport || overtimeReport || sickStats || payrollReport)
@@ -317,6 +335,13 @@ export function ReportsPage() {
<button onClick={() => download('xlsx')} className='text-xs px-3 py-1.5 bg-green-600 text-white rounded-lg hover:bg-green-700'>Excel</button>
<button onClick={() => download('pdf')} className='text-xs px-3 py-1.5 bg-red-600 text-white rounded-lg hover:bg-red-700'>PDF</button>
</>)}
{type === 'time' && (
<button onClick={downloadDatev}
title='Stundenaufzeichnung im DATEV-Blanko-Layout, ein Blatt pro Mitarbeiter/Monat'
className='text-xs px-3 py-1.5 bg-purple-600 text-white rounded-lg hover:bg-purple-700'>
DATEV-Monatsblatt
</button>
)}
</div>
</div>