feat(frontend): Inventar (Modul 24)

/equipment, /equipment/new, /equipment/:id mit Zustandsaenderung.
statusTone()-Helper um Equipment-Zustaende (NEW/GOOD/WORN/DEFECTIVE)
erweitert, Nav-Dropdown um Inventar ergaenzt.
This commit is contained in:
Nick Szaunig committed 2026-08-22 22:30:46 +02:00
1 parent 3f20133d02
commit 8b42a86115
8 files changed
+362 -3

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import { apiFetch } from "@/lib/auth/api-client";
import {
CreateEquipmentInput,
Equipment,
EquipmentFilter,
UpdateEquipmentInput,
} from "./types";
export function fetchEquipmentList(filter: EquipmentFilter = {}): Promise<Equipment[]> {
const params = new URLSearchParams();
if (filter.condition) params.set("condition", filter.condition);
const query = params.toString();
return apiFetch<Equipment[]>(`/equipment${query ? `?${query}` : ""}`);
}
export function fetchEquipment(id: string): Promise<Equipment> {
return apiFetch<Equipment>(`/equipment/${id}`);
}
export function createEquipment(input: CreateEquipmentInput): Promise<Equipment> {
return apiFetch<Equipment>("/equipment", {
method: "POST",
body: JSON.stringify(input),
});
}
export function updateEquipment(
id: string,
input: UpdateEquipmentInput,
): Promise<Equipment> {
return apiFetch<Equipment>(`/equipment/${id}`, {
method: "PATCH",
body: JSON.stringify(input),
});
}
@@ -0,0 +1,31 @@
export type EquipmentCondition = "NEW" | "GOOD" | "WORN" | "DEFECTIVE";
export interface Equipment {
id: string;
inventoryNumber: string;
name: string;
manufacturer: string | null;
purchaseDate: string | null;
condition: EquipmentCondition;
location: string | null;
maintenanceDate: string | null;
createdAt: string;
updatedAt: string;
}
export interface CreateEquipmentInput {
inventoryNumber: string;
name: string;
manufacturer?: string;
purchaseDate?: string;
location?: string;
maintenanceDate?: string;
}
export interface UpdateEquipmentInput extends Partial<CreateEquipmentInput> {
condition?: EquipmentCondition;
}
export interface EquipmentFilter {
condition?: EquipmentCondition;
}
+5 -2
View File
@@ -5,16 +5,19 @@ const WARNING_STATUSES = new Set([
"CONSPICUOUS",
"QUEENLESS",
"LOW_STOCK",
"WORN",
]);
const DESTRUCTIVE_STATUSES = new Set(["DISSOLVED", "DECEASED", "SOLD"]);
const DESTRUCTIVE_STATUSES = new Set(["DISSOLVED", "DECEASED", "SOLD", "DEFECTIVE"]);
const NEUTRAL_STATUSES = new Set(["MERGED", "CONSUMED"]);
const POSITIVE_STATUSES = new Set(["ACTIVE", "NEW", "GOOD"]);
export function statusTone(status: string): StatusTone {
if (WARNING_STATUSES.has(status)) return "warning";
if (DESTRUCTIVE_STATUSES.has(status)) return "destructive";
if (NEUTRAL_STATUSES.has(status)) return "outline";
if (status === "ACTIVE") return "default";
if (POSITIVE_STATUSES.has(status)) return "default";
return "secondary";
}