Files
Vorrania/ios/README.md
T
ScarriffleandClaude Opus 5 aa72d8342a App: Einzelstuecke verleihen - alle Scan-Wege enden schon dort
Verleih-Abschnitt im Einzelstueck: an wen, seit wann, bis wann, dazu
Herausgeben bzw. Zuruecknehmen und der Verleih-Verlauf. Pflicht ist nur der
Name; Grund und Rueckgabedatum sind abschaltbar, weil "kurz mal
mitgenommen" nicht an einem Datum scheitern soll.

Der Abschnitt sitzt bewusst oben in ItemEditView, und zwar nicht nur der
Wichtigkeit wegen: QR ueber Nachschlagen, eingenaehtes NFC-Tag und ein
angetipptes Tag (vorrania://i/<UID>) landen alle in genau dieser Ansicht.
Damit ist "scannen und verleihen" ueberall moeglich, ohne einen eigenen
Weg dafuer zu bauen.

In der Einzelstueck-Liste steht der Verleih unter dem Stueck - ueberfaellig
in Rot - und das Filter-Menue kann auf Verliehen, Ueberfaellig oder Im Haus
eingrenzen. Wo etwas ist, war bisher immer der Lagerort; ist es verliehen,
ist der Entleiher die Antwort, und der Lagerort steht daneben.

days_overdue rechnet der Server (GET /loans, ItemOut.loan), damit App und
Web nicht getrennt rechnen und nicht auseinanderlaufen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 09:36:05 +02:00

140 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Vorrania – iOS-App
Native SwiftUI-App für Lebensmittel **und** Gegenstände. Sie spricht dieselbe
REST-API wie die Web-Oberfläche.
> **Stand:** Voll nutzbar. Login; Scannen von Barcode, MHD/Datum (per
> Texterkennung, auch nur Tag+Monat ohne Jahr), Lagerort-QR und Name/Marke;
> Ein-/Auslagern mit mehreren Chargen bzw. Menge je Lagerort; Einzelstücke mit
> UID/QR, Kaufdatum, Garantie und Beleg – auch **verleihen** und
> zurücknehmen; Verbrauchsgegenstände als Charge;
> Artikel anlegen (Open Food/Products Facts oder manuell, mit Foto); getrennte
> Listen für Lebensmittel/Gegenstände/Einzelstücke, Kategoriefilter, Sortierung;
> Einkaufsliste, Ablaufliste, Mindestbestände; Verlauf mit Sprung zum Produkt;
> lokale Dashboards und Push-Benachrichtigungen bei ablaufenden Produkten.
## Projekt in Xcode öffnen
### Variante A – mit XcodeGen (empfohlen)
```bash
brew install xcodegen
cd ios
xcodegen generate
open Vorrania.xcodeproj
```
`project.yml` beschreibt das Projekt vollständig (Bundle-ID, Info.plist,
Shortcuts, URL-Schema).
### Variante B – ohne XcodeGen
1. Xcode → *File ▸ New ▸ Project…* → **App**, Interface **SwiftUI**, Sprache **Swift**
2. Produktname `Vorrania`, Bundle-ID z. B. `com.scarriffle.vorrania`
3. Die von Xcode erzeugte `ContentView.swift` und `…App.swift` löschen
4. Den Ordner `Sources/` per Drag & Drop ins Projekt ziehen („Copy items if needed")
5. In den Target-Einstellungen die mitgelieferte `Sources/Info.plist` als Info.plist setzen
(*Build Settings ▸ Info.plist File*) und *Generate Info.plist File* auf **No** stellen
## Auf dem iPhone installieren
1. iPhone per Kabel verbinden, in Xcode als Ziel auswählen
2. *Signing & Capabilities* → dein Apple-Developer-Team wählen
3. ▶︎ Run. Beim ersten Start auf dem iPhone unter
*Einstellungen ▸ Allgemein ▸ VPN & Geräteverwaltung* dem Entwickler vertrauen
## Erste Schritte in der App
Beim Start nach der Server-Adresse fragen lassen, z. B. `http://192.168.1.50:8080`
(dieselbe Adresse wie im Browser), dann mit deinem Benutzer anmelden. Adresse und
Token bleiben gespeichert – das Token liegt im Keychain.
Hat der Server einen Anmeldedienst eingerichtet (Single Sign-on, siehe
[../README.md](../README.md#single-sign-on-optional)), erscheint darunter ein
Knopf „Mit … anmelden". Die Anmeldung läuft dann im System-Browser (AppAuth mit
PKCE, kein eingebettetes WebView); der Anmeldezustand samt Refresh-Token liegt
je Serverprofil getrennt im Keychain, und die App erneuert ein abgelaufenes
Token still im Hintergrund.
## Home-Screen-Shortcuts
Es gibt zwei Wege direkt in den Scan-Bildschirm:
**Schnellaktionen** – langer Druck auf das App-Symbol zeigt „Einlagern" und
„Auslagern" (funktioniert ohne weitere Einrichtung).
**Eigene Symbole auf dem Home-Bildschirm** – über die Apple-App *Kurzbefehle*:
1. Kurzbefehle ▸ **+** ▸ Aktion *URL öffnen*
2. URL `vorrania://checkin` (bzw. `vorrania://checkout`) eintragen
3. Kurzbefehl benennen, dann ▸ *Zum Home-Bildschirm hinzufügen*
Beide Wege öffnen die App **direkt in der Kamera**.
## Einzelstücke verleihen
In der Ansicht eines Einzelstücks steht **Verleih** ganz oben: verliehen an wen,
seit wann, bis wann – und der Knopf zum Herausgeben bzw. Zurücknehmen. Pflicht
ist nur der Name; Grund und Rückgabedatum sind optional, denn „kurz mal
mitgenommen" soll nicht an einem Datum scheitern.
Dass der Knopf genau dort sitzt, macht **scannen und verleihen** möglich, ohne
einen eigenen Weg dafür zu bauen: Alle Scan-Wege der App enden in dieser
Ansicht – der QR über *Nachschlagen*, ein eingenähtes NFC-Tag über *NFC-Tag
lesen* und ein angetipptes Tag über `vorrania://i/<UID>`.
Der Lagerort bleibt beim Verleihen stehen – dorthin gehört das Stück zurück. Als
verliehen zählt es aber nicht mehr zum Bestand, es ist ja nicht im Haus. In der
Einzelstück-Liste steht der Verleih unter dem Stück (überfällig in Rot) und lässt
sich über das Filter-Menü auf *Verliehen*, *Überfällig* oder *Im Haus* eingrenzen.
## NFC-Tags für Kleidung
Ein aufgeklebtes QR-Etikett übersteht keine Wäsche. Für Kleidungsstücke gibt es
deshalb eingenähte NFC-Tags: Einzelstück öffnen ▸ **NFC-Tag beschreiben** ▸ Tag
an die Oberseite des iPhones halten. Auf das Tag kommt derselbe Link, der auch im
QR steckt (`vorrania://i/<UID>`).
Gelesen wird es unter **Nachschlagen** oder **Ort zuordnen** über
*NFC-Tag lesen*. Das Antippen bei gesperrtem Handy startet die App bewusst
nicht: iOS macht das nur über Universal Links auf einer festen Domain, und die
gibt es bei einem selbst gehosteten Dienst nicht.
> Zum Bauen muss für die App-ID im Apple-Developer-Portal die Capability
> *Near Field Communication Tag Reading* aktiv sein, sonst schlägt das Signieren
> fehl. NFC gibt es nur auf dem iPhone – auf dem iPad sind die Knöpfe ausgeblendet.
## Aufbau der Quellen
| Datei | Inhalt |
|---|---|
| `VorraniaApp.swift` | App-Einstieg, Schnellaktionen, URL-Schema |
| `Session.swift` | Server-Adresse (UserDefaults) und Token (Keychain) |
| `APIClient.swift` | REST-Aufrufe gegen `/api/...` |
| `Models.swift` | Codable-Typen passend zu `backend/app/schemas.py` |
| `ScannerView.swift` | Kamera + Barcode-Erkennung (EAN-8/13, UPC-E, Code128, QR) |
| `RootView.swift` | Startbildschirm und Routing |
| `LoginView.swift` | Server + Anmeldung |
| `CheckInView.swift` / `CheckInFormView.swift` | Scan → Charge (MHD), Menge je Lagerort oder Einzelstück |
| `CheckOutView.swift` | Scan → Menge, Chargenauswahl oder FEFO |
| `ProductViews.swift` | Artikelsuche und Anlegen (mit OFF-Vorbefüllung, Foto, Text-Scan) |
| `ProductDetailView.swift` | Produkt bearbeiten, Verwaltungsart ändern, Chargen korrigieren |
| `ObjectStockView.swift` | Gegenstände: Menge je Lagerort (hinzufügen/umlagern/entfernen) |
| `ItemViews.swift` / `ItemListView.swift` | Einzelstücke anlegen, bearbeiten und auflisten |
| `AssignScanView.swift` | Einzelstück (Scan, NFC oder Liste) einem Lagerort-QR zuordnen |
| `NFCTag.swift` / `NFCViews.swift` | NFC-Tags lesen und beschreiben, Einzelstück-Code zerlegen |
| `ListViews.swift` | Produktlisten, Einkaufsliste, „bald ablaufend", Mindestbestände |
| `DashboardView.swift` / `DashboardCards.swift` / `ChartCards.swift` | Übersicht mit Karten und Diagrammen |
| `NotificationScheduler.swift` / `NotificationSettings*.swift` | Push-Benachrichtigungen bei Ablauf |
| `DateScanView.swift` / `BestBeforeText.swift` | MHD/Text per Texterkennung ablesen |
| `DisplaySettings.swift` | Datumsformat und Einheiten-Beschriftungen vom Server |
| `CategoryPicker.swift` | Kategorie-Auswahl und Gruppe anlegen |
## Gruppe und Kategorie – zwei verschiedene Dinge
**Gruppe** dient der *Bestandsrechnung*: Mehl von Rewe, Aldi und Migros zählen
zusammen, wichtig ist „ich habe 5 kg Mehl“. Eine Gruppe hat deshalb einen
gemeinsamen Mindestbestand mit Einheit und EAN-Codes. Ordnest du einen Artikel
einer Gruppe zu, erscheint sein EAN-Code automatisch dort; wechselt er die
Gruppe, wandert der Code mit.
**Kategorie** dient *allein dem Überblick* („Süßwaren“, „Molkereiprodukte“) und
ist verschachtelbar wie ein Lagerort (Süßwaren → Schokolade). Sie hat keinen
Bestand, keinen Mindestbestand und keine EAN-Codes. Filterst du auf eine
Oberkategorie, erscheinen die Artikel ihrer Unterkategorien mit. Beim Anlegen
schlägt der Server eine Kategorie aus der Open-Food-Facts-Einordnung vor.
## Weiteres
Push-Benachrichtigungen bei Ablauf und Lagerort je Charge beim Einlagern sind
umgesetzt. Weitere Ideen stehen in [../docs/ROADMAP.md](../docs/ROADMAP.md).