Feste Fächer-Liste je Objekttyp (Vorlagen-Positionen: Dropdown + Sonstiges)
CI / backend-tests (push) Successful in 1m0s
CI / frontend-build (push) Successful in 5m56s

Nutzer-Vorgabe: Rucksack-Fächer sollen aus einer festen, je Objekttyp
gepflegten Liste gewählt werden können statt jedes Mal Freitext einzutippen.
Neue Tabelle fach (Migration 0004), CRUD-Endpoints /faecher, Admin-Tab
Struktur bekommt Fach-Verwaltung, Vorlagen-Editor nutzt Dropdown mit
"Sonstiges"-Freitext-Fallback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
This commit is contained in:
2026-09-04 10:24:15 +02:00
co-authored by Claude Sonnet 5
parent 2f11011ed1
commit a2877f5672
11 changed files with 493 additions and 17 deletions
+13 -2
View File
@@ -1,9 +1,10 @@
import { useEffect, useState } from "react";
import { apiRequest } from "../api/client";
import type { Benutzer, Bereich, Beladungsvorlage, Kategorie, Material, Objekt, Objekttyp, Standort } from "../api/types";
import type { Benutzer, Bereich, Beladungsvorlage, Fach, Kategorie, Material, Objekt, Objekttyp, Standort } from "../api/types";
import { BenutzerSection } from "./admin/BenutzerSection";
import { BereichSection } from "./admin/BereichSection";
import { FachSection } from "./admin/FachSection";
import { KategorieSection } from "./admin/KategorieSection";
import { MaterialSection } from "./admin/MaterialSection";
import { ObjektSection } from "./admin/ObjektSection";
@@ -40,12 +41,13 @@ export function AdminPage() {
const [objekte, setObjekte] = useState<Objekt[]>([]);
const [materialien, setMaterialien] = useState<Material[]>([]);
const [benutzer, setBenutzer] = useState<Benutzer[]>([]);
const [faecher, setFaecher] = useState<Fach[]>([]);
const [fehler, setFehler] = useState<string | null>(null);
const [laedt, setLaedt] = useState(true);
const [tab, setTab] = useState<Tab>("objekte");
async function ladeAlles() {
const [be, ka, ot, s, v, o, m, b] = await Promise.all([
const [be, ka, ot, s, v, o, m, b, f] = await Promise.all([
apiRequest<Bereich[]>("/bereiche"),
apiRequest<Kategorie[]>("/kategorien"),
apiRequest<Objekttyp[]>("/objekttypen"),
@@ -54,6 +56,7 @@ export function AdminPage() {
apiRequest<Objekt[]>("/objekte"),
apiRequest<Material[]>("/materialien"),
apiRequest<Benutzer[]>("/benutzer"),
apiRequest<Fach[]>("/faecher"),
]);
setBereiche(be);
setKategorien(ka);
@@ -63,6 +66,7 @@ export function AdminPage() {
setObjekte(o);
setMaterialien(m);
setBenutzer(b);
setFaecher(f);
}
useEffect(() => {
@@ -111,6 +115,7 @@ export function AdminPage() {
vorlagen={vorlagen}
objekttypen={objekttypen}
materialien={materialien}
faecher={faecher}
onGeaendert={ladeAlles}
onFehler={setFehler}
/>
@@ -134,6 +139,12 @@ export function AdminPage() {
onGeaendert={ladeAlles}
onFehler={setFehler}
/>
<FachSection
objekttypen={objekttypen}
faecher={faecher}
onGeaendert={ladeAlles}
onFehler={setFehler}
/>
</>
)}
{tab === "standorte" && (