diff --git a/ios/Sources/CategoryPicker.swift b/ios/Sources/CategoryPicker.swift index 49d5a64..219f31b 100644 --- a/ios/Sources/CategoryPicker.swift +++ b/ios/Sources/CategoryPicker.swift @@ -7,6 +7,8 @@ import SwiftUI struct CategoryPicker: View { let categories: [CategoryItem] @Binding var selection: Int? + /// Nur Kategorien dieses Typs zeigen ("food"/"object"); nil = alle. + var tracking: String? = nil var body: some View { Picker("Kategorie", selection: $selection) { @@ -18,17 +20,23 @@ struct CategoryPicker: View { } } + private var gefiltert: [CategoryItem] { + guard let tracking else { return categories } + return categories.filter { $0.tracking == tracking } + } + private func flattened() -> [(item: CategoryItem, depth: Int)] { - let ids = Set(categories.map(\.id)) + let quelle = gefiltert + let ids = Set(quelle.map(\.id)) var result: [(CategoryItem, Int)] = [] func walk(_ node: CategoryItem, _ depth: Int) { result.append((node, depth)) - for child in categories.filter({ $0.parentId == node.id }) { + for child in quelle.filter({ $0.parentId == node.id }) { walk(child, depth + 1) } } - for root in categories.filter({ $0.parentId == nil || !ids.contains($0.parentId!) }) { + for root in quelle.filter({ $0.parentId == nil || !ids.contains($0.parentId!) }) { walk(root, 0) } return result diff --git a/ios/Sources/ProductDetailView.swift b/ios/Sources/ProductDetailView.swift index 4be2943..a2ca129 100644 --- a/ios/Sources/ProductDetailView.swift +++ b/ios/Sources/ProductDetailView.swift @@ -84,11 +84,12 @@ struct ProductDetailView: View { } Section { - CategoryPicker(categories: categories, selection: $categoryId) + CategoryPicker(categories: categories, selection: $categoryId, + tracking: current.tracking) } footer: { Text(current.isObject - ? "Kategorie bestimmt die Verwaltungsart (Gegenstand) und die eigenen Felder." - : "Kategorie: nur für den Überblick in der Artikelliste.") + ? "Nur Gegenstands-Kategorien. Bestimmt die eigenen Felder." + : "Nur Lebensmittel-Kategorien.") } if current.isObject { diff --git a/ios/Sources/ProductViews.swift b/ios/Sources/ProductViews.swift index bbbe041..f2b4503 100644 --- a/ios/Sources/ProductViews.swift +++ b/ios/Sources/ProductViews.swift @@ -70,6 +70,8 @@ struct ProductFormView: View { @State private var datePrecision = "day" @State private var selectedGroupId: Int? @State private var selectedCategoryId: Int? + // Umschalter Lebensmittel/Gegenstand: filtert die Kategorieauswahl. + @State private var modus = "object" @State private var groups: [GroupItem] = [] @State private var categories: [CategoryItem] = [] @State private var units: [Unit] = [] @@ -89,43 +91,61 @@ struct ProductFormView: View { LabeledField(label: "Marke", text: $brand) } Section { - CategoryPicker(categories: categories, selection: $selectedCategoryId) + Picker("Typ", selection: $modus) { + Text("Lebensmittel").tag("food") + Text("Gegenstand").tag("object") + } + .pickerStyle(.segmented) + CategoryPicker(categories: categories, selection: $selectedCategoryId, tracking: modus) } footer: { - Text("Kategorie: nur für den Überblick in der Artikelliste.") + Text(modus == "object" + ? "Gegenstand: Menge je Lagerort und eigene Felder." + : "Lebensmittel: Chargen mit Mindesthaltbarkeit.") } - Section { - Picker("Gruppe", selection: $selectedGroupId) { - Text("– keine –").tag(Int?.none) - ForEach(groups) { gruppe in - Text(gruppe.name).tag(Int?.some(gruppe.id)) + .onChange(of: modus) { neu in + // Passt die gewählte Kategorie nicht mehr zum Typ, Auswahl leeren. + if let cid = selectedCategoryId, + categories.first(where: { $0.id == cid })?.tracking != neu { + selectedCategoryId = nil + } + } + // Lebensmittel-Felder (Gruppe, Einheit, MHD) nur im Lebensmittel-Modus. + // Fuer Gegenstaende irrelevant - sie zaehlen in Stueck je Lagerort. + if modus == "food" { + Section { + Picker("Gruppe", selection: $selectedGroupId) { + Text("– keine –").tag(Int?.none) + ForEach(groups) { gruppe in + Text(gruppe.name).tag(Int?.some(gruppe.id)) + } + } + if session.isAdmin { + Button { + newGroupShown = true + } label: { + Label("Neue Gruppe anlegen", systemImage: "plus") + } + } + } footer: { + Text("Gruppe: zählt Bestände mehrerer Marken zusammen. Der EAN-Code " + + "dieses Artikels erscheint danach automatisch bei der Gruppe.") + } + Section("Einheit") { + Picker("Basiseinheit", selection: $baseUnit) { + ForEach(baseUnits, id: \.0) { Text($0.1).tag($0.0) } + } + QuantityField(label: "Packungsgröße", text: $packageSize, + suffix: DisplaySettings.baseUnitLabel(baseUnit)) + Picker("Bezeichnung", selection: $packageLabel) { + ForEach(labels, id: \.self) { Text($0.isEmpty ? "Packung (Standard)" : $0).tag($0) } } } - if session.isAdmin { - Button { - newGroupShown = true - } label: { - Label("Neue Gruppe anlegen", systemImage: "plus") + Section("MHD") { + Picker("Angabe", selection: $datePrecision) { + Text("Tagesdatum").tag("day") + Text("nur Monat/Jahr").tag("month") } } - } footer: { - Text("Gruppe: zählt Bestände mehrerer Marken zusammen. Der EAN-Code " - + "dieses Artikels erscheint danach automatisch bei der Gruppe.") - } - Section("Einheit") { - Picker("Basiseinheit", selection: $baseUnit) { - ForEach(baseUnits, id: \.0) { Text($0.1).tag($0.0) } - } - QuantityField(label: "Packungsgröße", text: $packageSize, - suffix: DisplaySettings.baseUnitLabel(baseUnit)) - Picker("Bezeichnung", selection: $packageLabel) { - ForEach(labels, id: \.self) { Text($0.isEmpty ? "Packung (Standard)" : $0).tag($0) } - } - } - Section("MHD") { - Picker("Angabe", selection: $datePrecision) { - Text("Tagesdatum").tag("day") - Text("nur Monat/Jahr").tag("month") - } } if let error { Section { Text(error).foregroundStyle(.red).font(.callout) } @@ -142,6 +162,11 @@ struct ProductFormView: View { groups = (try? await APIClient.shared.groups()) ?? [] categories = (try? await APIClient.shared.categories()) ?? [] units = (try? await APIClient.shared.units()) ?? [] + // Kam eine Kategorie aus dem Barcode-Vorschlag, den Typ dazu setzen. + if let cid = selectedCategoryId, + let t = categories.first(where: { $0.id == cid })?.tracking { + modus = t + } } .sheet(isPresented: $newGroupShown) { NavigationStack {