iOS zeigt dieselben Dashboards und kann direkt buchen

Die Uebersicht in der App war fest verdrahtet: vier Kacheln, unabhaengig
davon, was am Rechner zusammengestellt wurde. Jetzt liest sie dieselben
Dashboards wie die Web-Oberflaeche und stellt sie nativ dar.

Das Raster laesst sich auf einem Telefon nicht sinnvoll nachbilden, deshalb
stehen die Karten untereinander - in der Lesereihenfolge des Rasters, erst
Zeile, dann Spalte. Zusammengestellt wird weiterhin am Rechner; gibt es
mehrere Dashboards, schaltet oben ein Menue um.

Neu ist die Buchungskarte: Artikel suchen, Menge, ein- oder auslagern, ohne
den Scan-Ablauf zu oeffnen. Nach dem Buchen zieht die Karte den Bestand nach
und laesst die uebrigen Karten neu laden - sonst stuende dort weiter die alte
Zahl.

Diagrammkarten bekommen bewusst keinen halbgaren Nachbau, sondern den
ehrlichen Hinweis, dass es sie in der Web-Oberflaeche gibt.

Geprueft mit der echten Antwort eines laufenden Servers: Sie decodiert in die
Modelle der App, samt zweier Karten derselben Art mit verschiedenen Artikeln.
OverviewView faellt weg, DashboardView tritt an ihre Stelle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-23 19:27:01 +02:00
parent 89598147ed
commit 2ad197df42
7 changed files with 633 additions and 128 deletions

View File

@@ -467,6 +467,55 @@ struct Movement: Codable, Identifiable, Hashable {
var isIncoming: Bool { type == "in" }
}
// MARK: - Dashboards
/// Eine Karte auf einem Dashboard.
///
/// `i` ist die Kennung **dieser** Karte, `type` ihre Art - erst dadurch kann
/// dieselbe Art mehrfach auf einem Dashboard liegen. `props` traegt, was nur
/// diese eine Karte angeht (etwa welcher Artikel gemeint ist).
struct DashboardCard: Codable, Identifiable, Hashable {
let i: String
let type: String
let x: Int
let y: Int
let w: Int
let h: Int
let tage: Int?
let props: CardProps?
var id: String { i }
/// Nur die Felder, die die App auswertet. Die Rasterangaben kommen aus der
/// Web-Oberflaeche; hier bestimmen sie allein die Reihenfolge.
struct CardProps: Codable, Hashable {
let productId: Int?
enum CodingKeys: String, CodingKey {
case productId = "product_id"
}
}
}
struct Dashboard: Codable, Identifiable, Hashable {
let id: Int
let name: String
let position: Int
let layout: [DashboardCard]
}
struct DashboardList: Codable {
let dashboards: [Dashboard]
let source: String
let enforced: Bool
let hasDefault: Bool
enum CodingKeys: String, CodingKey {
case dashboards, source, enforced
case hasDefault = "has_default"
}
}
// MARK: - Stammdaten
/// Gebinde (Packung, Glas, ...) mit Einzahl und Mehrzahl.