From 55b9bc2587a3d2aec1950072a75d097cfd150518 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Sat, 22 Aug 2026 05:22:50 +0200 Subject: [PATCH] feat(frontend): Dashboard-Ansicht (Modul 13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /dashboard als Startseite nach Login mit Kennzahlen-Kacheln und Hinweisen (überfällige Aufgaben, auffällige Völker, Lagerartikel unter Mindestbestand). --- .../src/app/(app)/dashboard/page.tsx | 90 +++++++++++++++++++ ApiCore-Frontend/src/app/(app)/layout.tsx | 3 + .../src/app/(auth)/login/page.spec.tsx | 2 +- .../src/app/(auth)/login/page.tsx | 2 +- ApiCore-Frontend/src/lib/dashboard/api.ts | 10 +++ ApiCore-Frontend/src/lib/dashboard/types.ts | 17 ++++ TASKS.md | 2 +- 7 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 ApiCore-Frontend/src/app/(app)/dashboard/page.tsx create mode 100644 ApiCore-Frontend/src/lib/dashboard/api.ts create mode 100644 ApiCore-Frontend/src/lib/dashboard/types.ts diff --git a/ApiCore-Frontend/src/app/(app)/dashboard/page.tsx b/ApiCore-Frontend/src/app/(app)/dashboard/page.tsx new file mode 100644 index 0000000..a8085e8 --- /dev/null +++ b/ApiCore-Frontend/src/app/(app)/dashboard/page.tsx @@ -0,0 +1,90 @@ +"use client"; + +import Link from "next/link"; +import { useQuery } from "@tanstack/react-query"; +import { fetchDashboardAlerts, fetchDashboardSummary } from "@/lib/dashboard/api"; +import { DashboardAlert } from "@/lib/dashboard/types"; +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; + +function alertHref(alert: DashboardAlert): string | null { + if (alert.relatedType === "Colony") return `/colonies/${alert.relatedId}`; + if (alert.relatedType === "Task") return "/tasks"; + if (alert.relatedType === "StockItem") return "/storage"; + return null; +} + +export default function DashboardPage() { + const { data: summary, isLoading: summaryLoading } = useQuery({ + queryKey: ["dashboard", "summary"], + queryFn: fetchDashboardSummary, + }); + const { data: alerts, isLoading: alertsLoading } = useQuery({ + queryKey: ["dashboard", "alerts"], + queryFn: fetchDashboardAlerts, + }); + + const tiles = summary + ? [ + { label: "Aktive Bienenstände", value: summary.apiariesActive }, + { label: "Aktive Völker", value: summary.coloniesActive }, + { label: "Aktive Königinnen", value: summary.queensActive }, + { label: "Offene Aufgaben", value: summary.openTasks }, + { label: "Honigchargen", value: summary.honeyBatchesTotal }, + { label: "Artikel unter Mindestbestand", value: summary.stockItemsLowCount }, + ] + : []; + + return ( +
+

Dashboard

+ + {summaryLoading ?

Lädt…

: null} +
+ {tiles.map((tile) => ( + + + + {tile.label} + + + +

{tile.value}

+
+
+ ))} +
+ + + + Hinweise + + + {alertsLoading ?

Lädt…

: null} + {!alertsLoading && (!alerts || alerts.length === 0) ? ( +

Keine offenen Hinweise.

+ ) : null} + {alerts?.map((alert) => { + const href = alertHref(alert); + return ( +
+ {alert.message} +
+ {alert.type} + {href ? ( + + Ansehen + + ) : null} +
+
+ ); + })} +
+
+
+ ); +} diff --git a/ApiCore-Frontend/src/app/(app)/layout.tsx b/ApiCore-Frontend/src/app/(app)/layout.tsx index 829f3d3..f9b998c 100644 --- a/ApiCore-Frontend/src/app/(app)/layout.tsx +++ b/ApiCore-Frontend/src/app/(app)/layout.tsx @@ -25,6 +25,9 @@ export default function AppLayout({ children }: { children: ReactNode }) {