App: die selbst draufgesetzten Posten fehlten in der Einkaufsliste

Die Einkaufsliste besteht aus zwei Haelften: gerechnete Bedarfe (Artikel
und Gruppen unter ihrem Mindestbestand, Bedarfe je Lagerort) und das,
was jemand selbst draufgesetzt hat - eigene Eintraege und die aus einem
Rezept uebernommenen Zutaten.

Die App kannte nur die erste Haelfte. Sie fragte /shopping-list,
/shopping-list/groups und /shopping-list/by-location ab - drei Routen,
die ausschliesslich rechnen. Die gespeicherten Eintraege liegen in
/shopping-list/entries und kommen gebuendelt ueber /shopping-list/all;
danach hat die App nie gefragt. Ergebnis: Man setzt im Web etwas auf die
Liste, nimmt das Telefon mit in den Laden, und es ist nicht da.

Jetzt holt die App die gebuendelte Route - ein Aufruf statt drei - und
zeigt die eigenen Posten in einem eigenen Abschnitt "Selbst
draufgesetzt", mit Herkunft ("fuer Pfannkuchen") und Menge. Antippen
hakt ab: Der Posten verschwindet sofort, geht das Speichern schief,
kommt er zurueck - lieber ein Ruecksprung als ein falsches Haekchen.

Dieselbe Blindstelle hatte die Dashboard-Karte der App; sie meldete
"alle Mindestbestaende sind gedeckt", waehrend Posten auf der Liste
standen. Auch sie nimmt jetzt die gebuendelte Route.

Dazu ein Hinweis im Docstring von GET /shopping-list: Diese Route ist
ein Drittel der Liste, wer "die Liste" will, nimmt /all. Die Aufteilung
hat in zwei Tagen zweimal jemanden glauben lassen, es sei nichts da -
beim zweiten Mal war es die App selbst.

Gegen den laufenden Server geprueft: Mit einem Eintrag "Backpapier"
liefert /shopping-list weiterhin [] und /shopping-list/all den Eintrag
samt art, name, menge_text, source, recipe_name und done - genau die
Felder, die das neue Swift-Modell liest.

Nicht kompiliert: kein Xcode auf dieser Maschine. Geprueft sind
Klammer- und Anfuehrungsbalance, dass die drei alten Routen niemand mehr
aufruft, und dass die benutzten Hilfsfunktionen (makeRequest, jsonBody,
send) wirklich so heissen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-03 07:24:58 +02:00
co-authored by Claude Opus 5
parent 892c52e49a
commit f04d80a330
5 changed files with 148 additions and 7 deletions
+22 -3
View File
@@ -226,18 +226,33 @@ struct ShoppingCard: View {
let stand: Int
@State private var items: [ShoppingItem] = []
/// Selbst draufgesetzte Posten. Ohne sie meldete die Karte, alles sei
/// gedeckt, waehrend auf der Liste fuenf Dinge standen.
@State private var eintraege: [ShoppingEntry] = []
@State private var fehler: String?
private var offene: [ShoppingEntry] { eintraege.filter { !$0.done } }
var body: some View {
Group {
if let fehler {
Text(fehler).font(.caption).foregroundStyle(.red)
} else if items.isEmpty {
} else if items.isEmpty && offene.isEmpty {
Text("Alle Mindestbestände sind gedeckt.")
.font(.caption).foregroundStyle(.secondary)
} else {
VStack(alignment: .leading, spacing: 6) {
ForEach(items.prefix(5)) { item in
// Eigene Eintraege zuerst: Sie stehen da, weil jemand sie
// bewusst draufgesetzt hat.
ForEach(offene.prefix(5)) { eintrag in
HStack {
Text(eintrag.name).font(.callout)
Spacer()
Text(eintrag.mengeText.isEmpty ? "selbst notiert" : eintrag.mengeText)
.font(.caption).foregroundStyle(.orange)
}
}
ForEach(items.prefix(max(0, 5 - offene.count))) { item in
HStack {
Text(item.name).font(.callout)
Spacer()
@@ -252,7 +267,11 @@ struct ShoppingCard: View {
}
.task(id: stand) {
do {
items = try await APIClient.shared.shoppingList()
// Die gebuendelte Route: Nur sie bringt auch die selbst
// draufgesetzten Posten mit.
let alles = try await APIClient.shared.shoppingAll()
items = alles.products
eintraege = alles.entries
fehler = nil
} catch {
self.fehler = error.localizedDescription