Verwendungsstatus: in der App umstellen, filtern und nachsehen

Im Einzelstueck steht jetzt ueber dem Verleih ein Abschnitt "Verwendung"
mit vier Symbolen: verfuegbar, in Verwendung, in Reinigung, in Reparatur.
Ein Tipp bucht sofort, ohne "Speichern" - wie beim Verleih, denn alle
Scan-Wege (QR, NFC, vorrania://i/<UID>) landen genau in dieser Ansicht.
Vier Woerter waeren auf einem iPhone zu breit, vier Symbole passen immer;
darunter steht der Name im Klartext samt "seit wann".

Dazu der Verwendungs-Verlauf mit Zeitstempeln und Konto, und in der
Einzelstueck-Liste ein Filter ueber alle vier Zustaende plus die Zeile
unter dem Namen, solange etwas laeuft. Stuecke ohne Verwendungsstatus
fallen aus dem Filter "Verfuegbar" heraus - ein Schraubenzieher ist nicht
verfuegbar, er fuehrt den Zustand gar nicht.

Der Haken je Kategorie sitzt im Kategorie-Editor und gilt beim Bearbeiten
auch fuer die Unterkategorien.

Zwei Dinge, die beim Pruefen am Simulator auffielen: Die Leiste haette
beim Oeffnen jedes Mal einmal ins Leere gebucht, weil onChange auch beim
Laden feuert - dagegen der Abgleich mit dem zuletzt gemeldeten Stand. Und
SQLite liefert Zeitstempel ohne Zeitzone, woran ISO8601DateFormatter
scheitert; in der App stand deshalb der rohe ISO-Text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-20 22:07:27 +02:00
co-authored by Claude Opus 5
parent b9d097fe96
commit 290ff9341a
5 changed files with 343 additions and 4 deletions
+47 -1
View File
@@ -11,6 +11,28 @@ struct ItemListView: View {
@State private var locationFilter: String? // Lagerort-ID
@State private var categoryFilter: Int? // Kategorie-ID (Unterkategorien zählen mit)
@State private var verleihFilter: VerleihFilter = .alle
@State private var verwendungFilter: VerwendungFilter = .alle
/// Blickwinkel auf den Verwendungszustand – „was liegt gerade in der
/// Wäsche?" ist die Frage dahinter. „Verfügbar" ist dabei das Fehlen eines
/// laufenden Zeitraums, kein eigener Serverwert.
enum VerwendungFilter: Hashable, CaseIterable {
case alle
case verfuegbar
case status(VerwendungStatus)
static var allCases: [VerwendungFilter] {
[.alle, .verfuegbar] + VerwendungStatus.allCases.map { .status($0) }
}
var label: String {
switch self {
case .alle: return "Alle"
case .verfuegbar: return "Verfügbar"
case let .status(s): return s.label
}
}
}
/// Blickwinkel auf den Verleihzustand – „was ist gerade draußen?" ist die
/// Frage, die man im Alltag an diese Liste stellt.
@@ -97,6 +119,16 @@ struct ItemListView: View {
case .ueberfaellig: if !(it.loan?.istUeberfaellig ?? false) { return false }
case .imHaus: if it.loan != nil { return false }
}
switch verwendungFilter {
case .alle: break
// Stuecke ohne Verwendungsstatus fallen hier bewusst raus: Ein
// Schraubenzieher ist nicht „verfuegbar", er fuehrt den Zustand gar
// nicht.
case .verfuegbar:
if !it.zeigtVerwendung || it.verwendungStatus != nil { return false }
case let .status(gesucht):
if it.verwendungStatus != gesucht { return false }
}
if !q.isEmpty {
let heu = [it.productName, it.uid, it.note, it.productBrand]
.compactMap { $0 }.joined(separator: " ").lowercased()
@@ -108,6 +140,7 @@ struct ItemListView: View {
private var hatFilter: Bool {
locationFilter != nil || categoryFilter != nil || verleihFilter != .alle
|| verwendungFilter != .alle
}
var body: some View {
@@ -193,6 +226,11 @@ struct ItemListView: View {
check(f.label, verleihFilter == f) { verleihFilter = f }
}
}
Menu("Verwendung") {
ForEach(VerwendungFilter.allCases, id: \.self) { f in
check(f.label, verwendungFilter == f) { verwendungFilter = f }
}
}
if !filterKategorien.isEmpty {
Menu("Kategorie") {
check("Alle", categoryFilter == nil) { categoryFilter = nil }
@@ -204,7 +242,8 @@ struct ItemListView: View {
if hatFilter {
Divider()
Button(role: .destructive) {
locationFilter = nil; categoryFilter = nil; verleihFilter = .alle
locationFilter = nil; categoryFilter = nil
verleihFilter = .alle; verwendungFilter = .alle
} label: {
Label("Filter zurücksetzen", systemImage: "xmark.circle")
}
@@ -263,6 +302,13 @@ struct ItemRow: View {
.foregroundStyle(loan.istUeberfaellig ? Color.red : .secondary)
.lineLimit(2)
}
// Nur, wenn etwas laeuft: „Verfuegbar" unter jeder zweiten
// Zeile waere Rauschen.
if let status = item.verwendungStatus {
Label(status.label, systemImage: status.symbol)
.font(.caption)
.foregroundStyle(.secondary)
}
}
Spacer()
}