iOS: eigene Kategorie-Felder schon beim Anlegen ausfuellen

Beim Neuanlegen eines Gegenstands (z.B. T-Shirt) werden jetzt die eigenen Felder
der gewaehlten Kategorie (Groesse, Farbe, ...) geladen und angezeigt - vorher
tauchten sie erst in der Detailansicht nach dem Anlegen auf. NewProductRequest
traegt die Werte via field_values mit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-28 10:56:37 +02:00
parent c67998d78b
commit 9ca7291c68
2 changed files with 40 additions and 1 deletions

View File

@@ -309,6 +309,8 @@ struct NewProductRequest: Codable {
var individual: Bool? = nil var individual: Bool? = nil
/// Verbrauchsgegenstand: Gegenstand wie ein Lebensmittel (Charge) geführt. /// Verbrauchsgegenstand: Gegenstand wie ein Lebensmittel (Charge) geführt.
var bulk: Bool? = nil var bulk: Bool? = nil
/// Selbst definierte Feldwerte der Kategorie: {feld_id (als Text): Wert}.
var fieldValues: [String: String?]? = nil
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case barcode, name, brand, individual, bulk case barcode, name, brand, individual, bulk
@@ -319,6 +321,7 @@ struct NewProductRequest: Codable {
case datePrecision = "date_precision" case datePrecision = "date_precision"
case groupId = "group_id" case groupId = "group_id"
case categoryId = "category_id" case categoryId = "category_id"
case fieldValues = "field_values"
} }
} }

View File

@@ -89,6 +89,9 @@ struct ProductFormView: View {
@State private var pendingImage: UIImage? @State private var pendingImage: UIImage?
@State private var showCamera = false @State private var showCamera = false
@State private var pickerItem: PhotosPickerItem? @State private var pickerItem: PhotosPickerItem?
// Eigene Felder der (Gegenstands-)Kategorie schon beim Anlegen ausfüllbar.
@State private var fieldDefs: [FieldDefinition] = []
@State private var fieldValues: [String: String] = [:]
private let baseUnits = [("piece", "Stück"), ("gram", "Gramm"), ("milliliter", "Milliliter")] private let baseUnits = [("piece", "Stück"), ("gram", "Gramm"), ("milliliter", "Milliliter")]
// Beschriftungen kommen sonst aus DisplaySettings.baseUnitLabel. // Beschriftungen kommen sonst aus DisplaySettings.baseUnitLabel.
@@ -179,6 +182,15 @@ struct ProductFormView: View {
} }
} }
} }
// Eigene Felder der Gegenstands-Kategorie (z.B. Größe, Farbe beim
// T-Shirt) schon beim Anlegen ausfüllbar, nicht erst danach.
if !fieldDefs.isEmpty {
Section("Eigene Felder") {
ForEach(fieldDefs) { def in
ObjectFieldRow(def: def, value: fieldBinding(def))
}
}
}
// Foto direkt beim Anlegen z.B. wenn Open Food/Products Facts keins // Foto direkt beim Anlegen z.B. wenn Open Food/Products Facts keins
// liefert. Wird nach dem Anlegen hochgeladen (dann gibt es eine ID). // liefert. Wird nach dem Anlegen hochgeladen (dann gibt es eine ID).
Section("Foto") { Section("Foto") {
@@ -222,6 +234,16 @@ struct ProductFormView: View {
pickerItem = nil pickerItem = nil
} }
} }
.onChange(of: selectedCategoryId) { cid in
// Bei einer Gegenstands-Kategorie deren (vererbte) Felder nachladen.
Task {
if let cid, categories.first(where: { $0.id == cid })?.isObject == true {
fieldDefs = (try? await APIClient.shared.categoryFields(categoryId: cid)) ?? []
} else {
fieldDefs = []
}
}
}
.onAppear(perform: prefill) .onAppear(perform: prefill)
.task { .task {
groups = (try? await APIClient.shared.groups()) ?? [] groups = (try? await APIClient.shared.groups()) ?? []
@@ -243,6 +265,19 @@ struct ProductFormView: View {
} }
} }
private func fieldBinding(_ def: FieldDefinition) -> Binding<String> {
let key = String(def.id)
return Binding(get: { fieldValues[key] ?? "" }, set: { fieldValues[key] = $0 })
}
/// Werte der geltenden eigenen Felder als {feld_id: Wert} nil, wenn keine.
private func eigeneFeldwerte() -> [String: String?]? {
guard !fieldDefs.isEmpty else { return nil }
var fv: [String: String?] = [:]
for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" }
return fv
}
private func prefill() { private func prefill() {
if let initialType { modus = initialType } if let initialType { modus = initialType }
barcode = suggestion?.barcode ?? prefillBarcode ?? "" barcode = suggestion?.barcode ?? prefillBarcode ?? ""
@@ -277,7 +312,8 @@ struct ProductFormView: View {
groupId: selectedGroupId, groupId: selectedGroupId,
categoryId: selectedCategoryId, categoryId: selectedCategoryId,
individual: modus == "object" ? (objMode == "individual") : nil, individual: modus == "object" ? (objMode == "individual") : nil,
bulk: modus == "object" ? (objMode == "bulk") : nil bulk: modus == "object" ? (objMode == "bulk") : nil,
fieldValues: eigeneFeldwerte()
) )
) )
// Vorgemerktes Foto hochladen ein Fehler darf das Anlegen nicht // Vorgemerktes Foto hochladen ein Fehler darf das Anlegen nicht