feat(admin): Objekttyp-Presets beim Anlegen statt drei Einzel-Regler
CI / backend-tests (push) Successful in 3m39s
CI / frontend-build (push) Successful in 24s

Dropdown "Objekttyp-Art" (Verbrauchsmaterial/Gerät mit Wartungspflicht/
Fahrzeug/Benutzerdefiniert) setzt Zugfahrzeug/Ressourcenbuchung/Wartung/
Zählerstand mit sinnvollen Defaults vor - einzelne Felder bleiben danach
frei änderbar (kein Locking), manuelle Änderung schaltet automatisch auf
"Benutzerdefiniert" um. Reines Frontend, keine Schema-/API-Änderung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDMvneg6wKfXdXvTYNd3dN
This commit is contained in:
patrickandClaude Sonnet 5 committed 2026-09-14 11:56:16 +02:00
1 parent d661354d69
commit 20d4903d9c
3 files changed
+195 -4

No files matched your search

+63
View File
@@ -15788,3 +15788,66 @@ Keine Commits in dieser Session.
- frontend/src/pages/admin/ObjekttypSection.tsx | 45 +++++++++++++++++++++++++++++++-
---
## 2026-09-13 23:27 – 09:40 (10h 13m)
**Beschreibung:** Claude Code Session
**Projekt:** asb-material
### Commits
- d661354 fix(maintenance): MAINT-003 Wartung als Opt-in je Objekttyp
### Geänderte Dateien
- DEVLOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- arbeitskacheln/10_maintenance.md | 14 +++++++++++++
- backend/alembic/versions/0059_objekttyp_wartung_aktiv.py | 36 ++++++++++++++++++++++++++++++++++
- backend/app/models/stammdaten.py | 6 ++++++
- backend/app/schemas/akte.py | 1 +
- backend/app/schemas/stammdaten.py | 2 ++
- backend/app/services/akte.py | 1 +
- backend/tests/test_akte.py | 24 +++++++++++++++++++++++
- frontend/src/api/types.ts | 2 ++
- frontend/src/pages/AktePage.tsx | 8 +++++---
- frontend/src/pages/admin/ObjekttypSection.tsx | 19 ++++++++++++++++++
---
## 2026-09-14 09:45 – 09:45 (0m)
**Beschreibung:** Claude Code Session
**Projekt:** asb-material
### Commits
Keine Commits in dieser Session.
### Geänderte Dateien
- DEVLOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- arbeitskacheln/10_maintenance.md | 14 +++++++++++++
- backend/alembic/versions/0059_objekttyp_wartung_aktiv.py | 36 ++++++++++++++++++++++++++++++++++
- backend/app/models/stammdaten.py | 6 ++++++
- backend/app/schemas/akte.py | 1 +
- backend/app/schemas/stammdaten.py | 2 ++
- backend/app/services/akte.py | 1 +
- backend/tests/test_akte.py | 24 +++++++++++++++++++++++
- frontend/src/api/types.ts | 2 ++
- frontend/src/pages/AktePage.tsx | 8 +++++---
- frontend/src/pages/admin/ObjekttypSection.tsx | 19 ++++++++++++++++++
---
## 2026-09-14 10:02 – 10:06 (3m)
**Beschreibung:** Claude Code Session
**Projekt:** vsb-talk
### Commits
Keine Commits in dieser Session.
### Geänderte Dateien
- DEVLOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- arbeitskacheln/10_maintenance.md | 14 +++++++++++++
- backend/alembic/versions/0059_objekttyp_wartung_aktiv.py | 36 ++++++++++++++++++++++++++++++++++
- backend/app/models/stammdaten.py | 6 ++++++
- backend/app/schemas/akte.py | 1 +
- backend/app/schemas/stammdaten.py | 2 ++
- backend/app/services/akte.py | 1 +
- backend/tests/test_akte.py | 24 +++++++++++++++++++++++
- frontend/src/api/types.ts | 2 ++
- frontend/src/pages/AktePage.tsx | 8 +++++---
- frontend/src/pages/admin/ObjekttypSection.tsx | 19 ++++++++++++++++++
---
+42
View File
@@ -1306,3 +1306,45 @@ Keine Commits in dieser Session.
- frontend/src/pages/MangelListePage.tsx | 6 +-
---
## 2026-09-14 10:54 – 10:55 (1m)
**Beschreibung:** Claude Code Session
**Projekt:** asb-material
### Commits
Keine Commits in dieser Session.
### Geänderte Dateien
- DEVLOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- arbeitskacheln/10_maintenance.md | 14 +++++++++++++
- backend/alembic/versions/0059_objekttyp_wartung_aktiv.py | 36 ++++++++++++++++++++++++++++++++++
- backend/app/models/stammdaten.py | 6 ++++++
- backend/app/schemas/akte.py | 1 +
- backend/app/schemas/stammdaten.py | 2 ++
- backend/app/services/akte.py | 1 +
- backend/tests/test_akte.py | 24 +++++++++++++++++++++++
- frontend/src/api/types.ts | 2 ++
- frontend/src/pages/AktePage.tsx | 8 +++++---
- frontend/src/pages/admin/ObjekttypSection.tsx | 19 ++++++++++++++++++
---
## 2026-09-14 10:58 – 10:58 (0m)
**Beschreibung:** Claude Code Session
**Projekt:** frontend
### Commits
Keine Commits in dieser Session.
### Geänderte Dateien
- DEVLOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- arbeitskacheln/10_maintenance.md | 14 +++++++++++++
- backend/alembic/versions/0059_objekttyp_wartung_aktiv.py | 36 ++++++++++++++++++++++++++++++++++
- backend/app/models/stammdaten.py | 6 ++++++
- backend/app/schemas/akte.py | 1 +
- backend/app/schemas/stammdaten.py | 2 ++
- backend/app/services/akte.py | 1 +
- backend/tests/test_akte.py | 24 +++++++++++++++++++++++
- frontend/src/api/types.ts | 2 ++
- frontend/src/pages/AktePage.tsx | 8 +++++---
- frontend/src/pages/admin/ObjekttypSection.tsx | 19 ++++++++++++++++++
---
+90 -4
View File
@@ -11,6 +11,48 @@ const ZAEHLER_TYP_LABEL: Record<ZaehlerTyp, string> = {
beide: "Kilometerstand + Betriebsstunden",
};
type ObjekttypPreset = "verbrauchsmaterial" | "geraet_mit_wartung" | "fahrzeug" | "benutzerdefiniert";
interface PresetWerte {
istZugfahrzeug: boolean;
ressourcenbuchungAktiv: boolean;
wartungAktiv: boolean;
zaehlerTyp: ZaehlerTyp;
}
// Nutzer-Vorschlag 2026-09-14: drei Einzel-Regler (Zugfahrzeug/
// Ressourcenbuchung/Wartung/Zählerstand) beim Anlegen einzeln zu setzen ist
// für die zwei Hauptfälle (Verbrauchsmaterial, Fahrzeug) unnötig viele
// Klicks - Preset setzt sinnvolle Defaults, einzelne Felder bleiben danach
// trotzdem frei änderbar (kein Locking).
const OBJEKTTYP_PRESETS: Record<Exclude<ObjekttypPreset, "benutzerdefiniert">, PresetWerte> = {
verbrauchsmaterial: {
istZugfahrzeug: false,
ressourcenbuchungAktiv: false,
wartungAktiv: false,
zaehlerTyp: "keiner",
},
geraet_mit_wartung: {
istZugfahrzeug: false,
ressourcenbuchungAktiv: false,
wartungAktiv: true,
zaehlerTyp: "betriebsstunden",
},
fahrzeug: {
istZugfahrzeug: true,
ressourcenbuchungAktiv: true,
wartungAktiv: true,
zaehlerTyp: "beide",
},
};
const PRESET_LABEL: Record<ObjekttypPreset, string> = {
verbrauchsmaterial: "Verbrauchsmaterial / Rucksack",
geraet_mit_wartung: "Gerät mit Wartungspflicht",
fahrzeug: "Fahrzeug",
benutzerdefiniert: "Benutzerdefiniert",
};
interface Props {
bereiche: Bereich[];
kategorien: Kategorie[];
@@ -42,6 +84,17 @@ export function ObjekttypSection({
const [bearbeitungsZaehlerTyp, setBearbeitungsZaehlerTyp] = useState<ZaehlerTyp>("keiner");
const [wartungAktiv, setWartungAktiv] = useState(false);
const [bearbeitungsWartung, setBearbeitungsWartung] = useState(false);
const [preset, setPreset] = useState<ObjekttypPreset>("verbrauchsmaterial");
function presetAnwenden(gewaehlt: ObjekttypPreset) {
setPreset(gewaehlt);
if (gewaehlt === "benutzerdefiniert") return;
const werte = OBJEKTTYP_PRESETS[gewaehlt];
setIstZugfahrzeug(werte.istZugfahrzeug);
setRessourcenbuchungAktiv(werte.ressourcenbuchungAktiv);
setWartungAktiv(werte.wartungAktiv);
setZaehlerTyp(werte.zaehlerTyp);
}
const [schemaBearbeitenId, setSchemaBearbeitenId] = useState<number | null>(null);
const [schemaPraefix, setSchemaPraefix] = useState("");
const [schemaStellenzahl, setSchemaStellenzahl] = useState(5);
@@ -104,6 +157,7 @@ export function ObjekttypSection({
setRessourcenbuchungAktiv(false);
setZaehlerTyp("keiner");
setWartungAktiv(false);
setPreset("verbrauchsmaterial");
await onGeaendert();
} catch {
onFehler("Objekttyp konnte nicht angelegt werden.");
@@ -192,11 +246,30 @@ export function ObjekttypSection({
<input {...feldProps} className="input" value={name} onChange={(e) => setName(e.target.value)} />
)}
</FormField>
<FormField label="Objekttyp-Art">
{(feldProps) => (
<select
{...feldProps}
className="input"
value={preset}
onChange={(e) => presetAnwenden(e.target.value as ObjekttypPreset)}
>
{Object.entries(PRESET_LABEL).map(([wert, label]) => (
<option key={wert} value={wert}>
{label}
</option>
))}
</select>
)}
</FormField>
<label className="row" style={{ alignItems: "center", gap: "0.4rem", marginTop: "1.5rem" }}>
<input
type="checkbox"
checked={istZugfahrzeug}
onChange={(e) => setIstZugfahrzeug(e.target.checked)}
onChange={(e) => {
setIstZugfahrzeug(e.target.checked);
setPreset("benutzerdefiniert");
}}
/>
Zugfahrzeug (koppelbar)
</label>
@@ -204,12 +277,22 @@ export function ObjekttypSection({
<input
type="checkbox"
checked={ressourcenbuchungAktiv}
onChange={(e) => setRessourcenbuchungAktiv(e.target.checked)}
onChange={(e) => {
setRessourcenbuchungAktiv(e.target.checked);
setPreset("benutzerdefiniert");
}}
/>
Ressourcenbuchung in der Akte anzeigen
</label>
<label className="row" style={{ alignItems: "center", gap: "0.4rem", marginTop: "1.5rem" }}>
<input type="checkbox" checked={wartungAktiv} onChange={(e) => setWartungAktiv(e.target.checked)} />
<input
type="checkbox"
checked={wartungAktiv}
onChange={(e) => {
setWartungAktiv(e.target.checked);
setPreset("benutzerdefiniert");
}}
/>
Wartung in der Akte anzeigen
</label>
<FormField label="Zählerstand in der Akte">
@@ -218,7 +301,10 @@ export function ObjekttypSection({
{...feldProps}
className="input"
value={zaehlerTyp}
onChange={(e) => setZaehlerTyp(e.target.value as ZaehlerTyp)}
onChange={(e) => {
setZaehlerTyp(e.target.value as ZaehlerTyp);
setPreset("benutzerdefiniert");
}}
>
{Object.entries(ZAEHLER_TYP_LABEL).map(([wert, label]) => (
<option key={wert} value={wert}>