feat(frontend): Bienenstaende-Views (Modul 2)

/apiaries: Liste mit Status-Badge; /apiaries/new: Anlegen-Formular;
/apiaries/[id]: Bearbeiten (Name/Standort/Adresse/Notizen) + Deaktivieren.
Editierbares Formular liest den Ausgangszustand direkt aus der geladenen
Apiary (kein useEffect+setState-Sync, React-Key-Reset-Pattern statt
Effect - vermeidet kaskadierende Renders).

(app)/layout.tsx: einfache Nav-Leiste (Bienenstände fuer alle, Benutzer
nur fuer Admins) - Platzhalter bis zur echten Bottom-Nav/Sidebar aus
Modul 15. proxy.ts-Matcher um /apiaries/* erweitert.

Live im Browser gefunden+behoben: Base-UI-Button meldete fehlende
native Button-Semantik beim Rendern als Link (`nativeButton={false}`
noetig, wenn Button auf ein <a> zeigt).

8 Vitest-Tests, Lint, Typecheck und Build gruen. Kompletter Flow
(Anlegen, Liste, Bearbeiten, Deaktivieren, Navigation) live verifiziert.
This commit is contained in:
Nick Szaunig committed 2026-08-21 08:59:18 +02:00
1 parent 5c92c810e1
commit d59153a697
10 files changed
+428 -3

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
import { apiFetch } from "@/lib/auth/api-client";
import { Apiary, ApiaryInput } from "./types";
export function fetchApiaries(): Promise<Apiary[]> {
return apiFetch<Apiary[]>("/apiaries");
}
export function fetchApiary(id: string): Promise<Apiary> {
return apiFetch<Apiary>(`/apiaries/${id}`);
}
export function createApiary(input: ApiaryInput): Promise<Apiary> {
return apiFetch<Apiary>("/apiaries", {
method: "POST",
body: JSON.stringify(input),
});
}
export function updateApiary(id: string, input: Partial<ApiaryInput>): Promise<Apiary> {
return apiFetch<Apiary>(`/apiaries/${id}`, {
method: "PATCH",
body: JSON.stringify(input),
});
}
export function deactivateApiary(id: string): Promise<Apiary> {
return apiFetch<Apiary>(`/apiaries/${id}/deactivate`, { method: "POST" });
}
@@ -0,0 +1,24 @@
export type ApiaryStatus = "ACTIVE" | "INACTIVE";
export interface Apiary {
id: string;
name: string;
description: string | null;
location: string | null;
latitude: number | null;
longitude: number | null;
address: string | null;
status: ApiaryStatus;
notes: string | null;
createdAt: string;
updatedAt: string;
deactivatedAt: string | null;
}
export interface ApiaryInput {
name: string;
description?: string;
location?: string;
address?: string;
notes?: string;
}