feat(frontend): Suche und Filter (Modul 14)

/search-Seite über Bienenstände, Völker, Königinnen, Aufgaben und
Honigchargen. Filterleisten (Status/Standort) in den Listen-Views
für Bienenstände, Völker, Königinnen und Honigchargen.
This commit is contained in:
Nick Szaunig committed 2026-08-22 05:39:59 +02:00
1 parent 146b56d683
commit 166979ff3c
21 files changed
+314 -28

No files matched your search

@@ -47,7 +47,7 @@ function MoveDialog({ colony }: { colony: Colony }) {
const queryClient = useQueryClient();
const [open, setOpen] = useState(false);
const [apiaryId, setApiaryId] = useState("");
const { data: apiaries } = useQuery({ queryKey: ["apiaries"], queryFn: fetchApiaries });
const { data: apiaries } = useQuery({ queryKey: ["apiaries"], queryFn: () => fetchApiaries() });
const mutation = useMutation({
mutationFn: () => moveColony(colony.id, { apiaryId }),
@@ -182,7 +182,7 @@ function MergeDialog({ colony }: { colony: Colony }) {
const queryClient = useQueryClient();
const [open, setOpen] = useState(false);
const [mergedColonyId, setMergedColonyId] = useState("");
const { data: colonies } = useQuery({ queryKey: ["colonies"], queryFn: fetchColonies });
const { data: colonies } = useQuery({ queryKey: ["colonies"], queryFn: () => fetchColonies() });
const mutation = useMutation({
mutationFn: () => mergeColony(colony.id, { mergedColonyIds: [mergedColonyId] }),
@@ -35,7 +35,7 @@ const COLONY_TYPES: ColonyType[] = [
export default function NewColonyPage() {
const router = useRouter();
const queryClient = useQueryClient();
const { data: apiaries } = useQuery({ queryKey: ["apiaries"], queryFn: fetchApiaries });
const { data: apiaries } = useQuery({ queryKey: ["apiaries"], queryFn: () => fetchApiaries() });
const [code, setCode] = useState("");
const [apiaryId, setApiaryId] = useState("");
@@ -1,10 +1,19 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query";
import { fetchColonies } from "@/lib/colonies/api";
import { ColonyStatus } from "@/lib/colonies/types";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
@@ -14,10 +23,23 @@ import {
TableRow,
} from "@/components/ui/table";
const STATUS_OPTIONS: ColonyStatus[] = [
"ACTIVE",
"WEAK",
"CONSPICUOUS",
"QUEENLESS",
"DISSOLVED",
"SOLD",
"DECEASED",
"MERGED",
];
export default function ColoniesPage() {
const [status, setStatus] = useState<ColonyStatus | "">("");
const { data: colonies, isLoading, isError } = useQuery({
queryKey: ["colonies"],
queryFn: fetchColonies,
queryKey: ["colonies", status],
queryFn: () => fetchColonies({ status: status || undefined }),
});
return (
@@ -29,6 +51,23 @@ export default function ColoniesPage() {
</Button>
</div>
<Select
value={status || "ALL"}
onValueChange={(value) => setStatus(value === "ALL" ? "" : ((value ?? "") as ColonyStatus))}
>
<SelectTrigger className="w-40">
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="ALL">Alle Status</SelectItem>
{STATUS_OPTIONS.map((option) => (
<SelectItem key={option} value={option}>
{option}
</SelectItem>
))}
</SelectContent>
</Select>
{isLoading ? <p className="text-sm text-muted-foreground">Lädt…</p> : null}
{isError ? (
<p role="alert" className="text-sm text-red-600">