feat: manueller Backup-Button für Admin
POST /api/backup (nur Admin) löst triggerBackup() aus. Button im Header zeigt ⏳/✓/✗ Feedback, verschwindet nach 4s. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+31
-6
@@ -21,6 +21,7 @@ export default function MainClient({ kuerzel, beoId, beoName, role }: Props) {
|
|||||||
const [activeTab, setActiveTab] = useState<'eingabe' | 'liste' | 'statistik' | 'fahrkosten'>('eingabe');
|
const [activeTab, setActiveTab] = useState<'eingabe' | 'liste' | 'statistik' | 'fahrkosten'>('eingabe');
|
||||||
const [refreshKey, setRefreshKey] = useState(0);
|
const [refreshKey, setRefreshKey] = useState(0);
|
||||||
const [editEntry, setEditEntry] = useState<LogbuchEintrag | null>(null);
|
const [editEntry, setEditEntry] = useState<LogbuchEintrag | null>(null);
|
||||||
|
const [backupState, setBackupState] = useState<'idle' | 'running' | 'ok' | 'error'>('idle');
|
||||||
|
|
||||||
const grafikSrc = '/api/statistik/grafik';
|
const grafikSrc = '/api/statistik/grafik';
|
||||||
|
|
||||||
@@ -47,6 +48,17 @@ export default function MainClient({ kuerzel, beoId, beoName, role }: Props) {
|
|||||||
window.location.href = '/login';
|
window.location.href = '/login';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleBackup() {
|
||||||
|
setBackupState('running');
|
||||||
|
try {
|
||||||
|
const r = await fetch('/api/backup', { method: 'POST' });
|
||||||
|
setBackupState(r.ok ? 'ok' : 'error');
|
||||||
|
} catch {
|
||||||
|
setBackupState('error');
|
||||||
|
}
|
||||||
|
setTimeout(() => setBackupState('idle'), 4000);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-white py-1 px-2 sm:py-2 sm:px-4 print:p-0">
|
<div className="min-h-screen bg-white py-1 px-2 sm:py-2 sm:px-4 print:p-0">
|
||||||
<main className="max-w-6xl mx-auto border-2 border-black rounded-lg p-3 sm:p-4 bg-[#EEF4FF] print:max-w-none print:border-0 print:p-0 print:bg-white">
|
<main className="max-w-6xl mx-auto border-2 border-black rounded-lg p-3 sm:p-4 bg-[#EEF4FF] print:max-w-none print:border-0 print:p-0 print:bg-white">
|
||||||
@@ -59,12 +71,25 @@ export default function MainClient({ kuerzel, beoId, beoName, role }: Props) {
|
|||||||
</h1>
|
</h1>
|
||||||
<div className="flex items-center gap-2 shrink-0">
|
<div className="flex items-center gap-2 shrink-0">
|
||||||
{role?.includes('admin') && (
|
{role?.includes('admin') && (
|
||||||
<a
|
<>
|
||||||
href="/admin"
|
<button
|
||||||
className="text-xs sm:text-sm px-2 sm:px-3 py-1.5 bg-gray-200 hover:bg-gray-300 rounded-lg text-gray-700"
|
onClick={handleBackup}
|
||||||
>
|
disabled={backupState === 'running'}
|
||||||
Admin
|
className={`text-xs sm:text-sm px-2 sm:px-3 py-1.5 rounded-lg text-gray-900 disabled:opacity-50 ${
|
||||||
</a>
|
backupState === 'ok' ? 'bg-green-200' :
|
||||||
|
backupState === 'error' ? 'bg-red-200' :
|
||||||
|
'bg-gray-200 hover:bg-gray-300'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{backupState === 'running' ? '⏳ Backup…' : backupState === 'ok' ? '✓ Backup OK' : backupState === 'error' ? '✗ Fehler' : '💾 Backup'}
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
href="/admin"
|
||||||
|
className="text-xs sm:text-sm px-2 sm:px-3 py-1.5 bg-gray-200 hover:bg-gray-300 rounded-lg text-gray-700"
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={handleLogout}
|
onClick={handleLogout}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { getSession } from '@/lib/session';
|
||||||
|
import { triggerBackup } from '@/lib/backup';
|
||||||
|
|
||||||
|
export async function POST() {
|
||||||
|
const session = await getSession();
|
||||||
|
if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 });
|
||||||
|
if (!session.role?.includes('admin')) return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 });
|
||||||
|
|
||||||
|
triggerBackup();
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user