feat: Implement Windows runner for Flutter desktop app
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 57s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 57s
- Added runner.exe.manifest for DPI awareness and compatibility settings. - Created utils.cpp and utils.h for console management and command line argument handling. - Developed win32_window.cpp and win32_window.h for high DPI-aware window management. - Established basic window creation, message handling, and theme updating. - Added documentation for Flutter desktop app implementation plan and MVP specifications.
This commit is contained in:
128
docs/FLUTTER_DESKTOP_APP_PLAN.md
Normal file
128
docs/FLUTTER_DESKTOP_APP_PLAN.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Flutter Desktop-App – Umsetzungsplan
|
||||
|
||||
## Ziel und Leitentscheidung
|
||||
|
||||
Eine eigenständige, plattformübergreifende **Flutter-/Dart-Desktop-App** für Windows, macOS und Linux. Sie rendert ihre Oberflächen selbst mit Flutter – **keine WebView und keine eingebettete Vue-Webseite**.
|
||||
|
||||
Die bestehende Express-/MySQL-Anwendung bleibt die gemeinsame Server- und API-Plattform. Web- und Desktop-App arbeiten deshalb mit denselben Vereinsdaten, Benutzern und Berechtigungen.
|
||||
|
||||
**Abgrenzung:** Das Vue-Frontend wird nicht portiert oder eingebettet. Es dient nur als fachliche Referenz für Abläufe und API-Nutzung.
|
||||
|
||||
## Zielarchitektur
|
||||
|
||||
```text
|
||||
Flutter Desktop-App (Dart)
|
||||
├── eigene native Flutter-Oberfläche
|
||||
├── REST-Client → https://tt-tagebuch.de/api
|
||||
├── sicherer Token-Speicher des Betriebssystems
|
||||
└── später: Socket.IO, Benachrichtigungen, Datei-/Druckfunktionen
|
||||
|
||||
Bestehendes Node/Express-Backend
|
||||
├── JWT-Authentifizierung und Berechtigungsprüfung
|
||||
├── MySQL-Datenbank
|
||||
└── bestehende REST- und Socket.IO-Schnittstellen
|
||||
```
|
||||
|
||||
### Technische Festlegungen
|
||||
|
||||
- Neues Projekt im Repository: `backend/desktop-app/`.
|
||||
- Flutter stable und Dart; Windows, macOS und Linux von Beginn an als Build-Ziele aktivieren.
|
||||
- `go_router` für Navigation, `flutter_riverpod` für App-Zustand und `Dio` für HTTP.
|
||||
- Datenmodelle, Repositorys und API-Client von Widgets trennen; DTOs nicht direkt in der UI verwenden.
|
||||
- API-URL ausschließlich per `--dart-define` bzw. Build-Konfiguration setzen, nie fest in Quellcode oder Installer einbauen.
|
||||
- JWT in `flutter_secure_storage` ablegen. Bei `401` Token entfernen und zur Anmeldung wechseln; Netzwerkfehler führen nicht zum Logout.
|
||||
- Requests senden den vom Backend unterstützten Header `Authorization: Bearer <token>`; kompatibel bleibt auch der Web-Header `authcode`.
|
||||
- Berechtigungen immer vom Backend erzwingen lassen. Die Flutter-Navigation blendet fehlende Rechte nur für eine bessere Bedienung aus.
|
||||
- Deutsch als erste Sprache; Übersetzungen von Beginn an über Flutter-Lokalisierung strukturieren.
|
||||
|
||||
## Phasen und To-dos
|
||||
|
||||
### Phase 0 – API und Produktumfang festziehen
|
||||
|
||||
- [x] Desktop-MVP verbindlich auf **Login, Vereinskontext, Kalender, Spielplan, Mitglieder und Trainingsübersicht** begrenzen.
|
||||
- [x] Rollen für das MVP festlegen: einfaches Mitglied, Trainer und Vereinsverwaltung; pro Rolle die sichtbaren Bereiche definieren.
|
||||
- [x] Die verwendeten Endpunkte und Payloads gegen `docs/api_contract.md` und die echten Routen prüfen.
|
||||
- [x] Fehlende oder uneinheitliche API-Antworten als eigene Backend-Tickets erfassen, statt sie in der App zu umgehen.
|
||||
- [x] Gemeinsame Fehlercodes und Lade-/Leerezustände für die App festlegen.
|
||||
- [x] Datenschutz- und Offline-Anforderungen entscheiden: zunächst online-first, lokale Daten nur als Cache.
|
||||
|
||||
### Phase 1 – Projektfundament
|
||||
|
||||
- [x] Flutter-Projekt in `backend/desktop-app/` erzeugen und eine nachvollziehbare README mit Voraussetzungen erstellen.
|
||||
- [x] Paketstruktur anlegen: `core/`, `features/`, `data/`, `domain/`, `presentation/`.
|
||||
- [x] Build-Konfigurationen `development`, `staging` und `production` mit `API_BASE_URL` per Dart-Define einrichten.
|
||||
- [x] App-Theme, Typografie, responsive Desktop-Layout und zentrale Design-Tokens anlegen.
|
||||
- [x] Navigation mit öffentlichem Bereich und geschütztem App-Bereich aufsetzen.
|
||||
- [x] Fehlerbehandlung, Logging ohne personenbezogene Daten und zentrale Ladeindikatoren implementieren.
|
||||
- [x] CI-Grundgerüst für Formatierung, Analyse und Tests anlegen.
|
||||
|
||||
### Phase 2 – Anmeldung, Sitzung und Vereinskontext
|
||||
|
||||
- [ ] Login gegen `POST /api/auth/login` implementieren, inklusive „angemeldet bleiben“.
|
||||
- [ ] Token sicher speichern, beim Start wiederherstellen und Sitzung mit `GET /api/session/status` prüfen.
|
||||
- [ ] Logout über `POST /api/auth/logout` implementieren und lokale Zugangsdaten zuverlässig löschen.
|
||||
- [ ] Passwort-vergessen- und Passwort-zurücksetzen-Flows als native Formulare ergänzen.
|
||||
- [ ] Vereinsliste über `GET /api/clubs` laden und aktiven Verein persistent auswählen.
|
||||
- [ ] Berechtigungen über `GET /api/permissions/:clubId` laden und die Navigation rollenabhängig aufbauen.
|
||||
- [ ] Unit- und Integrationstests für Login, Tokenablauf, 401 und Vereinswechsel schreiben.
|
||||
|
||||
### Phase 3 – Desktop-MVP: persönliche Organisation
|
||||
|
||||
- [ ] Startseite mit nächstem Training, nächstem Spiel, offenen Hinweisen und Schnellzugriffen erstellen.
|
||||
- [ ] Kalenderansicht für Trainings-, Vereins- und Spieltermine umsetzen.
|
||||
- [ ] Spielplan mit Saison- und Mannschaftsauswahl sowie korrekter Berliner Zeitzonenanzeige umsetzen.
|
||||
- [ ] Mitgliederliste mit Suche und einer datensparsamen Detailansicht implementieren.
|
||||
- [ ] Trainingsübersicht mit Gruppen, Zeiten und Trainingsstatistik für berechtigte Rollen implementieren.
|
||||
- [ ] Für einfaches Mitglied den Bereich „Mein Verein“ mit persönlichen Terminen und Informationen priorisieren.
|
||||
- [ ] Leere Zustände, fehlende Berechtigungen, langsame Verbindung und Serverfehler in allen MVP-Ansichten testen.
|
||||
|
||||
### Phase 4 – Vereins- und Trainerfunktionen
|
||||
|
||||
- [ ] Trainingstagebuch inklusive Anwesenheit, Aktivitäten und Gruppen als native Arbeitsansicht umsetzen.
|
||||
- [ ] Mitgliederverwaltung mit Bearbeiten, Bild-/Datei-Upload und Rechteprüfung erweitern.
|
||||
- [ ] Sammlungsbestellungen als gemeinsames Modul einplanen und implementieren: Wünsche, Artikelstatus, Rückfragen, Preise, Bestätigung und Zahlungsstatus.
|
||||
- [ ] Mannschaften, Spielberichte/Ergebnisse und Turniere in fachlich getrennten Features ergänzen.
|
||||
- [ ] Rechnungen, Kommunikation, Aufgaben und Archiv erst nach einem eigenen UX-Entwurf als weitere Feature-Wellen ergänzen.
|
||||
- [ ] Socket.IO für die Bereiche aktivieren, in denen aktuelle Daten tatsächlich einen Mehrwert bringen; REST bleibt die verlässliche Basis.
|
||||
|
||||
### Phase 5 – echte Desktop-Mehrwerte
|
||||
|
||||
- [ ] Systembenachrichtigungen für Terminänderungen, Rückfragen und neue Vereinsnachrichten einführen.
|
||||
- [ ] Tray-Icon mit „Heute“, Synchronisationsstatus und Schnellaktionen ergänzen.
|
||||
- [ ] Native Datei-Auswahl, Downloads, PDF-Export und Druckabläufe implementieren.
|
||||
- [ ] Fensterzustand, zuletzt gewählter Verein und bevorzugte Ansicht lokal speichern.
|
||||
- [ ] Offline-Cache für lesende Kernansichten konzipieren; Konfliktregeln vor schreibender Offline-Unterstützung festlegen.
|
||||
- [ ] Signierte Installer für Windows, macOS und Linux sowie eine sichere Update-Strategie vorbereiten.
|
||||
|
||||
### Phase 6 – Qualität, Release und Betrieb
|
||||
|
||||
- [ ] Widget-Tests für jede neue Ansicht und Repository-/API-Tests für kritische Datenflüsse ergänzen.
|
||||
- [ ] Integrationstests für Anmeldung, Vereinswechsel, Kalender und Spielplan aufsetzen.
|
||||
- [ ] Smoke-Tests auf Windows, macOS und Linux durchführen; dabei Skalierung, Tastaturnavigation und Zeitzonen prüfen.
|
||||
- [ ] Accessibility prüfen: Fokusführung, Kontraste, Screenreader-Beschriftungen und vollständig bedienbare Tastaturwege.
|
||||
- [ ] Release-Kanäle (intern/stabil), Versionsnummern, Fehlerberichte und Datenschutztexte definieren.
|
||||
- [ ] Pilot mit einem Verein durchführen und erst danach die nächste Paritätswelle freigeben.
|
||||
|
||||
## Reihenfolge nach dem MVP
|
||||
|
||||
1. Persönliche Funktionen: Mein Verein, Kalender, Spielplan und Benachrichtigungen.
|
||||
2. Trainer-Arbeitsabläufe: Trainingstagebuch, Anwesenheit, Gruppen und Trainingselemente.
|
||||
3. Vereinsverwaltung: Mitglieder, Kommunikation, Sammlungsbestellungen, Aufgaben und Dokumente.
|
||||
4. Komplexe Spezialfunktionen: Turniere, Rechnungen, Importe, externe myTischtennis-/click-TT-Abläufe und Offline-Schreiben.
|
||||
|
||||
## Kritische vorhandene Referenzen
|
||||
|
||||
- `backend/server.js` – zentrale API-Routen.
|
||||
- `backend/middleware/authMiddleware.js` und `backend/services/authService.js` – JWT- und Sitzungsverhalten.
|
||||
- `docs/api_contract.md` – aktueller API-Katalog.
|
||||
- `docs/socket_contract.md` – spätere Live-Updates.
|
||||
- `frontend/src/router.js` – fachliche Web-Bereiche und Berechtigungen als Referenz, nicht als UI-Vorlage.
|
||||
- `docs/simple-user-plan.md` und `docs/collective-orders-plan.md` – bereits geplante Nutzer- und Bestellabläufe.
|
||||
|
||||
## Abnahmekriterien für Release 1
|
||||
|
||||
- Die App ist eine eigenständige Flutter-Anwendung ohne WebView.
|
||||
- Login, sicherer Sitzungsspeicher und Logout funktionieren gegen die Produktions-API.
|
||||
- Ein Nutzer sieht ausschließlich die für seine Vereinsrolle erlaubten Bereiche.
|
||||
- Kalender, Spielplan, Mitglieder und Trainingsübersicht funktionieren auf allen drei Desktop-Plattformen.
|
||||
- `flutter analyze` und `flutter test` laufen fehlerfrei; je Plattform gibt es mindestens einen erfolgreichen manuellen Smoke-Test.
|
||||
101
docs/FLUTTER_DESKTOP_MVP_SPEC.md
Normal file
101
docs/FLUTTER_DESKTOP_MVP_SPEC.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Flutter Desktop-App – Phase 0: MVP- und API-Spezifikation
|
||||
|
||||
Stand: 30.07.2026
|
||||
Geltung: Release 1 der eigenständigen Flutter-Desktop-App für Windows, macOS und Linux.
|
||||
|
||||
## 1. Verbindlicher MVP-Umfang
|
||||
|
||||
Die erste Version ist eine **online-first Flutter-App ohne WebView**. Sie verwendet die Produktions-API, speichert keine fachlichen Daten dauerhaft offline und bildet ausschließlich die folgenden Bereiche ab:
|
||||
|
||||
| Bereich | Release-1-Umfang | Nicht Bestandteil von Release 1 |
|
||||
| --- | --- | --- |
|
||||
| Anmeldung | Login, Sitzung wiederherstellen, Logout, Passwort vergessen/zurücksetzen | Registrierung und Kontoaktivierung als eigener Folgeentscheid |
|
||||
| Vereinskontext | Verein wählen, Rechte laden, zuletzt gewählten Verein merken | Verein anlegen, Beitrittsfreigaben verwalten |
|
||||
| Startseite | Nächstes Training, nächstes Spiel, Anzahl ungelesener Hinweise, Schnellzugriffe | frei konfigurierbare Dashboards |
|
||||
| Kalender | Trainings-, Spiel- und Vereinsereignisse lesen; Monats-/Listenansicht | Ereignisse anlegen oder bearbeiten |
|
||||
| Spielplan | Saison, Mannschaft/Liga, Spiele und Ergebnisse lesen | CSV-Import, Tabellenabruf, Spielerzuordnung |
|
||||
| Mitglieder | Suche, Liste und datensparsame Detailansicht | Bearbeiten, Bildverwaltung, SEPA, Transfer |
|
||||
| Training | Trainingszeiten, Gruppen und Statistik lesen | Trainingstagebuch, Anwesenheit und Aktivitäten bearbeiten |
|
||||
| Mein Verein | Persönliche Übersicht, Inbox und eigene Terminantworten, sofern im Vereinskontext verfügbar | Profiländerung und Bestellabläufe als Folge-Release |
|
||||
|
||||
Der MVP liefert damit für alle Rollen eine verlässliche tägliche Übersicht. Schreibende Verwaltungs- und Trainerabläufe folgen erst, wenn die lesenden Kernansichten auf allen Zielplattformen stabil sind.
|
||||
|
||||
## 2. Rollen- und Sichtbarkeitsmatrix
|
||||
|
||||
Die Berechtigungen kommen ausschließlich vom Backend (`GET /api/permissions/:clubId`). Die folgende Matrix definiert nur die Desktop-Navigation; sie ersetzt niemals eine Serverprüfung.
|
||||
|
||||
| Bereich | Einfaches Mitglied | Trainer | Vereinsverwaltung |
|
||||
| --- | --- | --- | --- |
|
||||
| Startseite / Mein Verein | ja | ja | ja |
|
||||
| Kalender | wenn mindestens eine passende Leseberechtigung vorliegt | ja | ja |
|
||||
| Spielplan | mit `schedule.read` | mit `schedule.read` | mit `schedule.read` |
|
||||
| Mitglieder | nur eigene, persönliche Daten im MVP | mit `members.read` | mit `members.read` |
|
||||
| Training / Statistik | eigene bzw. freigegebene Ansicht | mit Trainings-/Statistikrecht | mit Trainings-/Statistikrecht |
|
||||
| Verwaltungsnavigation | nein | nur freigegebene Trainerbereiche | nur freigegebene Verwaltungsbereiche |
|
||||
|
||||
**Navigationsregel:** Fehlt eine Berechtigung, erscheint der Bereich nicht im Hauptmenü. Ein direkter Aufruf zeigt einen neutralen „Kein Zugriff“-Zustand. Ein `403` des Servers wird nie als Clientfehler behandelt.
|
||||
|
||||
## 3. Verifizierter API-Vertrag für Release 1
|
||||
|
||||
Basis: `backend/server.js`, die zugehörigen Route-Dateien sowie `docs/api_contract.md`.
|
||||
|
||||
### Authentifizierung und Kontext
|
||||
|
||||
| Vorgang | Endpunkt | MVP-Verwendung |
|
||||
| --- | --- | --- |
|
||||
| Anmeldung | `POST /api/auth/login` | Payload `{ email, password, rememberMe }`; Antwort enthält `token` und `expiresAt`. |
|
||||
| Sitzung prüfen | `GET /api/session/status` | beim App-Start nach Wiederherstellung des Tokens. |
|
||||
| Abmelden | `POST /api/auth/logout` | Token serverseitig invalidieren, danach lokal löschen. |
|
||||
| Vereine | `GET /api/clubs` und `GET /api/clubs/:clubId` | Vereinsauswahl und Überschrift. |
|
||||
| Rechte | `GET /api/permissions/:clubId` | Menü und Feature-Gates aktualisieren. |
|
||||
|
||||
### Fachliche Leseansichten
|
||||
|
||||
| Bereich | Endpunkt | Hinweise |
|
||||
| --- | --- | --- |
|
||||
| Persönliche Übersicht | `GET /api/clubmembers/dashboard/:clubId` | Für „Mein Verein“ und Startseite; Antwortschema vor Phase 3 als DTO festschreiben. |
|
||||
| Inbox | `GET /api/clubmembers/inbox/:clubId` | Ungelesene Hinweise und Nachrichten. |
|
||||
| Terminantwort | `PUT /api/clubmembers/dashboard/:clubId/events/:eventId/response` | einzige MVP-Schreibaktion für das Mitglied. |
|
||||
| Kalenderereignisse | `GET /api/calendar-events/:clubId?year=YYYY` | Vereinsereignisse. |
|
||||
| Kalender-/Feiertage | `GET /api/calendar/club/:clubId/holidays?year=YYYY` | ergänzende Kalenderdaten. |
|
||||
| Spielplan | `GET /api/matches/leagues/:clubId/matches?seasonid=:id` | nur bei `schedule.read`; Anzeige immer in `Europe/Berlin`. |
|
||||
| Ligen | `GET /api/matches/leagues/current/:clubId` | Auswahl für Spielplan. |
|
||||
| Teams | `GET /api/club-teams/club/:clubId?seasonid=:id` | Mannschaftsauswahl. |
|
||||
| Mitglieder | `GET /api/clubmembers/get/:clubId/:showAll` | nur bei `members.read`; Standardwert `showAll=false`. |
|
||||
| Trainingsgruppen | `GET /api/training-groups/:clubId` | nur bei verfügbarer Leseberechtigung. |
|
||||
| Trainingszeiten | `GET /api/training-times/:clubId` | nur bei verfügbarer Leseberechtigung. |
|
||||
| Trainingsstatistik | `GET /api/training-stats/:clubId` | nur bei `statistics.read`. |
|
||||
|
||||
### Verbindliche Request- und Fehlerregeln
|
||||
|
||||
- Jeder authentifizierte Request sendet `authcode: <JWT>`; optional zusätzlich `userid`, wenn es für einen bestehenden Endpunkt benötigt wird.
|
||||
- `Authorization: Bearer <JWT>` wird nicht als alleiniger Standard eingesetzt, bis alle Controller einheitlich auf den authentifizierten Request-Kontext zugreifen.
|
||||
- `401`: gespeicherten Token entfernen und zur Anmeldung wechseln.
|
||||
- `403`: Zugriff verweigert anzeigen, Token behalten und Navigation bei nächster Rechteaktualisierung korrigieren.
|
||||
- Netzwerkfehler, Timeout oder `5xx`: kein Logout, klare Wiederholen-Aktion und ggf. Anzeige gecachter Daten.
|
||||
- Kein Request und kein Log darf Passwort, JWT, E-Mail-Adresse oder vollständige Mitgliederdaten protokollieren.
|
||||
|
||||
## 4. Erfasste Backend-Tickets vor/parallel zu Phase 1
|
||||
|
||||
| Priorität | Ticket | Befund / Akzeptanzkriterium |
|
||||
| --- | --- | --- |
|
||||
| P0 | Auth-Header vereinheitlichen | `calendarController.js` und `calendarEventController.js` lesen aktuell nur `req.headers.authcode`, obwohl `authMiddleware.js` auch Bearer-Tokens akzeptiert. Einen zentralen Token-/User-Kontext verwenden; danach funktionieren beide Headerformen in allen geschützten Routen gleich. |
|
||||
| P0 | Dashboard-DTO dokumentieren | Antwort von `GET /api/clubmembers/dashboard/:clubId` mit stabilen Feldern für nächste Termine, Inbox-Zähler und persönliches Mitglied dokumentieren und per Test absichern. |
|
||||
| P1 | Kalender-Read-Contract absichern | Response-Modelle von Kalenderereignissen, Feiertagen und importierten Spielen mit Beispielpayloads dokumentieren; Datum/Zeit als ISO-Wert mit klarer Zeitzonenregel. |
|
||||
| P1 | Berechtigungen je MVP-Endpunkt prüfen | Für Trainingszeiten/-gruppen und das Member-Dashboard explizit serverseitige Vereins- und Rechteprüfungen testen; Navigation allein ist keine Sicherheit. |
|
||||
| P2 | Einheitliches Fehlerformat | Kalender- und ältere Controller schrittweise an das dokumentierte Fehlerformat `{ success, code, params, error, message }` angleichen. |
|
||||
|
||||
## 5. Datenschutz- und Offline-Entscheidung
|
||||
|
||||
- **Online-first:** Release 1 benötigt eine Verbindung zur API für alle Fachinformationen.
|
||||
- Lokal bleiben ausschließlich: verschlüsselter JWT, nicht sensible App-Einstellungen (Theme, Fensterzustand, letzter Verein) sowie ein kurzlebiger, löschbarer Lesecache.
|
||||
- Keine Passwörter, Zahlungsdaten, Mitgliedsfotos, SEPA-Daten oder vollständigen Mitgliederlisten offline speichern.
|
||||
- Bei fehlender Verbindung zeigt die App klar „Offline – Datenstand von …“ und deaktiviert Aktionen, die eine API-Anfrage benötigen.
|
||||
- Offline-Schreiben, Konfliktauflösung und Hintergrundsynchronisation gehören ausdrücklich nicht zu Release 1.
|
||||
|
||||
## 6. Definition of Ready für Phase 1
|
||||
|
||||
- MVP-Umfang und Rollenmatrix dieses Dokuments sind akzeptiert.
|
||||
- P0-Backend-Tickets sind umgesetzt oder der Flutter-Client verwendet vorübergehend den verbindlichen `authcode`-Header.
|
||||
- Eine Testumgebung mit HTTPS-API und einem Testkonto je MVP-Rolle steht bereit.
|
||||
- API-Base-URL für Entwicklung, Staging und Produktion ist festgelegt.
|
||||
Reference in New Issue
Block a user