Files
muh/frontend/src/pages/AdminDashboardPage.tsx

193 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { apiGet } from "../lib/api";
import type { DashboardOverview } from "../lib/types";
interface AdminStats {
totalSamples: number;
openSamples: number;
completedToday: number;
nextSampleNumber: number;
}
export default function AdminDashboardPage() {
const navigate = useNavigate();
const [stats, setStats] = useState<AdminStats | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadStats() {
try {
const dashboard = await apiGet<DashboardOverview>("/dashboard");
setStats({
totalSamples: dashboard.nextSampleNumber - 1,
openSamples: dashboard.openSamples,
completedToday: dashboard.completedToday,
nextSampleNumber: dashboard.nextSampleNumber,
});
} finally {
setLoading(false);
}
}
void loadStats();
}, []);
const adminModules = [
{
title: "Landwirte",
description: "Verwaltung der Landwirte und Betriebe",
icon: "👨‍🌾",
route: "/admin/landwirte",
color: "#4a7c59",
},
{
title: "Benutzer",
description: "Benutzerverwaltung und Berechtigungen",
icon: "👥",
route: "/admin/benutzer",
color: "#5b7ba8",
},
{
title: "Medikamente",
description: "Verwaltung der Medikamentenkataloge",
icon: "💊",
route: "/admin/medikamente",
color: "#8b5a7c",
},
{
title: "Erreger",
description: "Verwaltung der Erreger und Kürzel",
icon: "🦠",
route: "/admin/erreger",
color: "#7c5a5a",
},
{
title: "Antibiogramm",
description: "Verwaltung der Antibiotika-Kataloge",
icon: "📊",
route: "/admin/antibiogramm",
color: "#5a7c7c",
},
{
title: "Berichtsvorlage",
description: "Gestaltung der PDF-Berichtsvorlagen",
icon: "📄",
route: "/report-template",
color: "#7c7c5a",
},
];
return (
<div className="page-stack">
{/* Header Bereich */}
<section className="hero-card admin-hero">
<div>
<p className="eyebrow">Administration</p>
<h3>Administrator Dashboard</h3>
<p className="muted-text">
Verwalten Sie Landwirte, Benutzer, Medikamente, Erreger und Systemeinstellungen.
</p>
</div>
</section>
{/* Statistik-Karten */}
<section className="metrics-grid admin-metrics">
<article className="metric-card metric-card--primary">
<span className="metric-card__label">Nächste Probennummer</span>
<strong className="metric-card__value--large">
{loading ? "..." : stats?.nextSampleNumber}
</strong>
</article>
<article className="metric-card">
<span className="metric-card__label">Offene Proben</span>
<strong>{loading ? "..." : stats?.openSamples}</strong>
</article>
<article className="metric-card">
<span className="metric-card__label">Heute abgeschlossen</span>
<strong>{loading ? "..." : stats?.completedToday}</strong>
</article>
<article className="metric-card">
<span className="metric-card__label">Gesamtproben</span>
<strong>{loading ? "..." : stats?.totalSamples}</strong>
</article>
</section>
{/* Admin Module Grid */}
<section className="admin-modules-section">
<div className="section-card__header">
<div>
<p className="eyebrow">Verwaltung</p>
<h3>Verwaltungsmodule</h3>
</div>
</div>
<div className="admin-modules-grid">
{adminModules.map((module) => (
<button
key={module.route}
type="button"
className="admin-module-card"
onClick={() => navigate(module.route)}
style={{ "--module-color": module.color } as React.CSSProperties}
>
<span className="admin-module-card__icon">{module.icon}</span>
<div className="admin-module-card__content">
<strong>{module.title}</strong>
<span className="muted-text">{module.description}</span>
</div>
<span className="admin-module-card__arrow"></span>
</button>
))}
</div>
</section>
{/* Schnellzugriffe */}
<section className="quick-actions-section">
<div className="section-card">
<div className="section-card__header">
<div>
<p className="eyebrow">Schnellzugriff</p>
<h3>Häufige Aktionen</h3>
</div>
</div>
<div className="quick-actions-grid">
<button
type="button"
className="quick-action-button"
onClick={() => navigate("/samples/new")}
>
<span></span>
<span>Neue Probe anlegen</span>
</button>
<button
type="button"
className="quick-action-button"
onClick={() => navigate("/search/probe")}
>
<span>🔍</span>
<span>Probe suchen</span>
</button>
<button
type="button"
className="quick-action-button"
onClick={() => navigate("/portal")}
>
<span>📧</span>
<span>Portal & Berichte</span>
</button>
<button
type="button"
className="quick-action-button"
onClick={() => navigate("/search/landwirt")}
>
<span>👤</span>
<span>Landwirt suchen</span>
</button>
</div>
</div>
</section>
</div>
);
}