iOS: "Ort zuordnen" auch ohne Stueck-QR (Einzelstueck aus Liste waehlen)

Bisher musste man im "Ort zuordnen"-Ablauf zuerst den QR des Einzelstuecks
scannen. Fuer Stuecke ohne eigenen Code (z.B. Kleidung) gibt es jetzt
"Einzelstueck aus Liste waehlen" (durchsuchbare Liste) als Alternative; danach
wie gehabt den Lagerort-QR scannen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-28 13:47:42 +02:00
parent 532695c2ee
commit 53d8f18497

View File

@@ -9,9 +9,10 @@ struct AssignScanView: View {
@State private var paused = false
@State private var torchOn = false
@State private var torchLocked = false
@State private var pending: Item? // gescanntes Stück, wartet auf Ort
@State private var pending: Item? // gescanntes/gewähltes Stück, wartet auf Ort
@State private var status: String?
@State private var error: String?
@State private var showPicker = false
var body: some View {
ScrollView {
@@ -34,8 +35,14 @@ struct AssignScanView: View {
.background(Color.accentColor.opacity(0.15))
.clipShape(RoundedRectangle(cornerRadius: 12)).padding(.horizontal)
} else {
Text("Schritt 1: Einzelstück-QR scannen")
.font(.caption).foregroundStyle(.secondary)
VStack(spacing: 8) {
Text("Schritt 1: Einzelstück-QR scannen oder ohne Code:")
.font(.caption).foregroundStyle(.secondary)
// Für Stücke ohne eigenen QR (z.B. Kleidung): aus der Liste wählen.
Button { showPicker = true } label: {
Label("Einzelstück aus Liste wählen", systemImage: "list.bullet")
}
}
}
if let status {
@@ -55,6 +62,9 @@ struct AssignScanView: View {
ToolbarItem(placement: .topBarLeading) { Button("Fertig") { dismiss() } }
ToolbarItem(placement: .topBarTrailing) { TorchButton(isOn: $torchOn, locked: $torchLocked) }
}
.sheet(isPresented: $showPicker) {
ItemPickerSheet { it in pending = it; status = nil; error = nil }
}
}
private func handle(_ code: String) async {
@@ -90,3 +100,49 @@ struct AssignScanView: View {
error = "Unbekannter Code bitte einen Einzelstück- oder Lagerort-QR scannen."
}
}
/// Einzelstück aus einer durchsuchbaren Liste wählen für Stücke ohne eigenen QR.
struct ItemPickerSheet: View {
var onPick: (Item) -> Void
@Environment(\.dismiss) private var dismiss
@State private var items: [Item] = []
@State private var locations: [StorageLocation] = []
@State private var query = ""
@State private var busy = true
private var gefiltert: [Item] {
let q = query.trimmingCharacters(in: .whitespaces).lowercased()
guard !q.isEmpty else { return items }
return items.filter {
[$0.productName, $0.uid, $0.productBrand, $0.note]
.compactMap { $0 }.joined(separator: " ").lowercased().contains(q)
}
}
var body: some View {
NavigationStack {
List {
if busy && items.isEmpty { ProgressView() }
ForEach(gefiltert) { it in
Button { onPick(it); dismiss() } label: {
ItemRow(item: it, locations: locations)
}
.buttonStyle(.plain)
}
if !busy && gefiltert.isEmpty {
Text("Nichts gefunden.").foregroundStyle(.secondary)
}
}
.searchable(text: $query, prompt: "Produkt, UID oder Notiz")
.navigationTitle("Einzelstück wählen")
.navigationBarTitleDisplayMode(.inline)
.toolbar { ToolbarItem(placement: .topBarLeading) { Button("Abbrechen") { dismiss() } } }
.task {
items = (try? await APIClient.shared.allItems()) ?? []
locations = (try? await APIClient.shared.locations()) ?? []
busy = false
}
}
}
}