import { useState } from 'react'; import { api } from '../api/client'; import styles from './AdminPage.module.css'; interface ActionResult { message: string; success: boolean; timestamp: Date; } export default function AdminPage() { const [syncResult, setSyncResult] = useState(null); const [evalResult, setEvalResult] = useState(null); const [refreshResult, setRefreshResult] = useState(null); const [syncing, setSyncing] = useState(false); const [evaluating, setEvaluating] = useState(false); const [refreshing, setRefreshing] = useState(false); const handleSync = async () => { setSyncing(true); setSyncResult(null); try { const res = await api.syncMatches(); setSyncResult({ success: true, timestamp: new Date(), message: `${res.total} Spiele geladen — ${res.created} neu, ${res.updated} aktualisiert` }); } catch (e) { setSyncResult({ success: false, timestamp: new Date(), message: (e as Error).message }); } finally { setSyncing(false); } }; const handleEvaluate = async () => { setEvaluating(true); setEvalResult(null); try { const res = await api.evaluateTips(); setEvalResult({ success: true, timestamp: new Date(), message: `${res.matchesEvaluated} Spiele ausgewertet — ${res.tipsUpdated} Tipps bewertet` }); } catch (e) { setEvalResult({ success: false, timestamp: new Date(), message: (e as Error).message }); } finally { setEvaluating(false); } }; const handleRefreshLeaderboard = async () => { setRefreshing(true); setRefreshResult(null); try { await fetch('/api/admin/refresh-leaderboard', { method: 'POST' }); setRefreshResult({ success: true, timestamp: new Date(), message: 'Materialized View aktualisiert' }); } catch (e) { setRefreshResult({ success: false, timestamp: new Date(), message: (e as Error).message }); } finally { setRefreshing(false); } }; function formatTime(d: Date) { return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); } return (
{/* Header */}

Administration

Editor

Nur für Editoren sichtbar. Nach Staffbase-Freischaltung wird diese Seite durch Rollenprüfung geschützt.

{/* Action Cards */}
{/* Sync */} {/* Evaluate */} {/* Refresh Leaderboard */}
); } /* ── Sub-component ── */ function ActionCard({ icon, title, desc, result, loading, loadingLabel, actionLabel, onAction, formatTime, }: { icon: string; title: string; desc: string; result: ActionResult | null; loading: boolean; loadingLabel: string; actionLabel: string; onAction: () => void; formatTime: (d: Date) => string; }) { return (
{icon}
{title}
{desc}
{result && (
{result.message} {formatTime(result.timestamp)}
)}
); }