Lagerort-QR + Zuordnen per Scan
Web: druckbare QR-Etiketten fuer Lagerorte (Locations-Seite) und Route /l/<id> (zeigt den Ort im Browser). Geteilter QR-Helfer (web/src/qr.jsx). iOS: neuer Ablauf "Ort zuordnen" - erst Einzelstueck-QR (…/i/<UID>) scannen, dann Lagerort-QR (…/l/<ID>); das Stueck wird dem Ort zugewiesen, danach gleich das naechste. Plus die zuvor gebaute "Nachschlagen"-Kachel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
90
ios/Sources/AssignScanView.swift
Normal file
90
ios/Sources/AssignScanView.swift
Normal file
@@ -0,0 +1,90 @@
|
||||
import SwiftUI
|
||||
|
||||
/// Zuordnen per Scan: erst ein Einzelstück (…/i/<UID>) scannen, dann einen
|
||||
/// Lagerort (…/l/<ID>) – das Stück wird dem Ort zugewiesen. Danach gleich das
|
||||
/// nächste Stück, ohne Tippen.
|
||||
struct AssignScanView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@State private var paused = false
|
||||
@State private var torchOn = false
|
||||
@State private var pending: Item? // gescanntes Stück, wartet auf Ort
|
||||
@State private var status: String?
|
||||
@State private var error: String?
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(spacing: 14) {
|
||||
ScannerView(onCode: { code in Task { await handle(code) } },
|
||||
isPaused: $paused, torchOn: $torchOn)
|
||||
.aspectRatio(4.0 / 3.0, contentMode: .fit)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||||
.padding(.horizontal)
|
||||
|
||||
if let pending {
|
||||
VStack(spacing: 4) {
|
||||
Text("Einzelstück \(pending.uid)").font(.headline)
|
||||
Text("Jetzt den Lagerort-QR scannen")
|
||||
.font(.caption).foregroundStyle(.secondary)
|
||||
Button("Abbrechen") { self.pending = nil }
|
||||
.font(.caption).padding(.top, 2)
|
||||
}
|
||||
.padding().frame(maxWidth: .infinity)
|
||||
.background(Color.accentColor.opacity(0.15))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12)).padding(.horizontal)
|
||||
} else {
|
||||
Text("Schritt 1: Einzelstück-QR scannen")
|
||||
.font(.caption).foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
if let status {
|
||||
Text(status).font(.callout).foregroundStyle(.green)
|
||||
.frame(maxWidth: .infinity, alignment: .leading).padding(.horizontal)
|
||||
}
|
||||
if let error {
|
||||
Text(error).font(.callout).foregroundStyle(.red)
|
||||
.frame(maxWidth: .infinity, alignment: .leading).padding(.horizontal)
|
||||
}
|
||||
}
|
||||
.padding(.vertical)
|
||||
}
|
||||
.navigationTitle("Ort zuordnen")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) { Button("Fertig") { dismiss() } }
|
||||
ToolbarItem(placement: .topBarTrailing) { TorchButton(isOn: $torchOn) }
|
||||
}
|
||||
}
|
||||
|
||||
private func handle(_ code: String) async {
|
||||
// Lagerort-QR (…/l/<ID>)?
|
||||
if let r = code.range(of: "/l/") {
|
||||
let idStr = String(code[r.upperBound...])
|
||||
.trimmingCharacters(in: CharacterSet(charactersIn: "/ "))
|
||||
if let locId = Int(idStr) {
|
||||
guard let it = pending else {
|
||||
error = "Erst ein Einzelstück scannen."; status = nil; return
|
||||
}
|
||||
do {
|
||||
_ = try await APIClient.shared.updateItem(id: it.id, ItemUpdateRequest(
|
||||
locationId: locId, shopId: it.shopId,
|
||||
acquiredOn: it.acquiredOn, warrantyUntil: it.warrantyUntil, note: it.note))
|
||||
status = "\(it.uid) zugeordnet. Nächstes Stück scannen."
|
||||
error = nil
|
||||
pending = nil
|
||||
} catch { self.error = error.localizedDescription }
|
||||
return
|
||||
}
|
||||
}
|
||||
// Einzelstück-QR (…/i/<UID>)?
|
||||
if let r = code.range(of: "/i/") {
|
||||
let uid = String(code[r.upperBound...])
|
||||
.trimmingCharacters(in: CharacterSet(charactersIn: "/ ")).uppercased()
|
||||
if !uid.isEmpty, let it = try? await APIClient.shared.itemByUid(uid: uid) {
|
||||
pending = it; status = nil; error = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
error = "Unbekannter Code – bitte einen Einzelstück- oder Lagerort-QR scannen."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user