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:
@@ -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")
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user