iOS: 'Anlegen & fertig' fuers Einzelstueck + Speichern-Nachfrage beim Zurueck

1) Im Einzelstueck-Anlegen gibt es jetzt 'Anlegen & fertig' - das schliesst in einem Tap bis zur Produktliste zurueck (statt Sheet schliessen + nochmal zurueck). 'Anlegen' bleibt fuer mehrere Stuecke nacheinander. 2) Beim Zurueck aus der Produkt-Detailansicht wird bei ungespeicherten Stammdaten-Aenderungen nachgefragt (Speichern/Verwerfen); ohne Aenderung direkt zurueck. Fussnote stellt klar: Foto und Lagerort-Bedarf speichern sofort.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 19:42:43 +02:00
parent c52e88f856
commit 9551751732
2 changed files with 55 additions and 5 deletions

View File

@@ -5,8 +5,10 @@ struct ProductDetailView: View {
let product: Product
@EnvironmentObject private var display: DisplaySettings
@Environment(\.dismiss) private var dismiss
@State private var current: Product
@State private var showLeaveConfirm = false
@State private var lots: [Lot] = []
@State private var busy = false
@State private var error: String?
@@ -40,6 +42,29 @@ struct ProductDetailView: View {
_current = State(initialValue: product)
}
/// Ungespeicherte Änderungen an den Artikel-Stammdaten? (Foto und Lagerort-
/// Bedarf speichern sofort und zählen hier nicht.)
private var isDirty: Bool {
if name != current.name { return true }
if brand != (current.brand ?? "") { return true }
if categoryId != current.categoryId { return true }
if current.isObject {
if !current.isIndividual, shopId != current.shopId { return true }
if productUrl != (current.productUrl ?? "") { return true }
if fieldValues != Self.stringValues(current.fieldValues) { return true }
} else {
if packageSize != (current.packageSize.map { formatAmount($0) } ?? "") { return true }
if packageLabel != (current.packageLabel ?? "") { return true }
if datePrecision != (current.datePrecision == "month" ? "month" : "day") { return true }
if groupId != current.groupId { return true }
}
return false
}
private func attemptLeave() {
if isDirty { showLeaveConfirm = true } else { dismiss() }
}
var body: some View {
Form {
if let status {
@@ -52,7 +77,8 @@ struct ProductDetailView: View {
ProductPhotoSection(productId: current.id)
if current.isObject && current.isIndividual {
ProductItemsSection(product: current, onChanged: { await reload() })
ProductItemsSection(product: current, onChanged: { await reload() },
onFinish: { dismiss() })
} else if current.isObject {
ObjectStockSection(product: current, locations: locations, lots: lots,
onChanged: { await reload() })
@@ -193,6 +219,21 @@ struct ProductDetailView: View {
}
.navigationTitle(current.name)
.navigationBarTitleDisplayMode(.inline)
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button { attemptLeave() } label: { Label("Zurück", systemImage: "chevron.left") }
}
}
.confirmationDialog("Ungespeicherte Änderungen", isPresented: $showLeaveConfirm,
titleVisibility: .visible) {
Button("Speichern") { Task { await save(); dismiss() } }
Button("Verwerfen", role: .destructive) { dismiss() }
Button("Abbrechen", role: .cancel) {}
} message: {
Text("Änderungen an Name/Marke/Kategorie sind noch nicht gespeichert. "
+ "Foto und Lagerort-Bedarf werden sofort gespeichert.")
}
.sheet(item: $editLot) { lot in
NavigationStack {
LotEditView(lot: lot, product: current) {