Integrate Ktor HTTP clients and repositories for Veranstalter and Turnier features:

- Add `ApiRoutes` for central backend routing configuration.
- Implement `DefaultVeranstalterRepository` and `DefaultTurnierRepository` with Ktor clients.
- Add domain models (`Turnier`, `Bewerb`, `Abteilung`, `Veranstalter`) and respective repository interfaces.
- Replace fake VeranstalterRepository with real implementation.
- Update DI with `veranstalterModule` and HTTP client injection.
- Simplify TokenProvider and update HttpClient setup (timeouts, retries, logging).
- Mark roadmap tasks B-2 as partially complete.
This commit is contained in:
2026-04-03 01:09:30 +02:00
parent a5c1fb5bae
commit f82dbd64a5
17 changed files with 314 additions and 67 deletions
+61 -10
View File
@@ -1,6 +1,6 @@
# 🎨 [Frontend Expert] — Schritt-für-Schritt Roadmap
> **Stand:** 2. April 2026
> **Stand:** 3. April 2026
> **Rolle:** KMP, Compose Desktop, State-Management, MVVM/UDF, Backend-Anbindung
---
@@ -20,7 +20,7 @@
Referenzen:
- docs/06_Frontend/MVVM_UDF_Pattern.md (Regeln, Vorlage, Referenz-Code)
- frontend/features/veranstalter-feature/src/commonMain/.../VeranstalterViewModel.kt
- frontend/features/veranstalter-feature/src/jvmMain/.../DefaultVeranstalterRepository.kt
- frontend/features/veranstalter-feature/src/jvmMain/kotlin/at/mocode/frontend/features/veranstalter/data/remote/DefaultVeranstalterRepository.kt
- frontend/features/veranstalter-feature/src/jvmMain/.../VeranstalterAuswahlScreen.kt (nutzt ViewModel/Intents)
- [x] **A-2** | Abteilungs-Logik im Bewerb-Dialog berücksichtigen
@@ -60,14 +60,65 @@
- [x] `FunktionaerViewModel`
- [x] `AbteilungViewModel` (Startliste, Ergebnisse)
- [ ] **B-2** | Ktor-Clients und Repositories für Backend-Anbindung vorbereiten
- [ ] Ktor-HTTP-Client konfigurieren (BaseURL, Auth-Header, Timeout)
- [ ] Repository-Interface je Entität definieren (ermöglicht späteres Austauschen von Mock → Real)
- [ ] `VeranstalterRepository` mit echtem Backend-Client implementieren
- [ ] `TurnierRepository` implementieren
- [ ] `BewerbRepository` implementieren
- [ ] `AbteilungRepository` implementieren
- [ ] `StoreV2` schrittweise durch echte Repositories ersetzen
- [ ] **B-2** | Ktor-Clients und Repositories für Backend-Anbindung vorbereiten (V3-ready)
- [x] KMP-Ktor-Client zentral konfigurieren (BaseURL, Auth, Timeout, JSON, Logging)
- [x] BaseURL per `PlatformConfig.resolveApiBaseUrl()` (SSoT; JS: `globalThis.API_BASE_URL`/`window.location.origin`, JVM: `.env`/Systemprop) → frontend/core/network
- [x] Auth: Bearer Token über Interceptor; Token-Quelle: core/auth (`AuthApiClient`) bzw. Session-Store → Header `Authorization: Bearer <token>`
- [x] Timeouts: connect = 5s, request = 15s, socket = 30s (prod); dev je 2× höher; Retry-Policy max 2 Versuche bei 5xx/Network
- [x] JSON: `kotlinx.serialization` mit `ignoreUnknownKeys=true`, `explicitNulls=false`, `coerceInputValues=true`
- [x] Logging: `LogLevel.HEADERS` in dev, `LogLevel.NONE` in prod; PII nie loggen
- [x] Engines: JVM=CIO, JS=fetch (ktor-client-js), WASM=js (vorbereitet)
- [ ] Repository-Schnittstellen je Domäne definieren (Mock ↔ Real austauschbar)
- [ ] Pakete/Orte (commonMain):
- [x] `at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository`
- [x] `at.mocode.turnier.feature.domain.TurnierRepository`
- [ ] `at.mocode.turnier.feature.domain.BewerbRepository`
- [ ] `at.mocode.turnier.feature.domain.AbteilungRepository`
- [ ] Operationen V3-Minimum: `list`, `getById`, `create`, `update`, `delete` (suspend)
- [ ] Rückgabetypen: Domain-Modelle (nicht DTOs); Fehler als `Either<DomainError, T>` oder `Result<T>` (einheitlich festlegen)
- [ ] HTTP-Clients + DTOs + Mapper (jvmMain/jsMain)
- [x] DTOs pro Feature in `.../data/remote/dto` mit `@Serializable` (Veranstalter)
- [x] Mapper: `Dto ↔ Domain` in `.../data/mapper` (reine Funktionen) (Veranstalter)
- [x] Client-Implementierungen in `.../data/remote/Default*Repository` mit Ktor (Veranstalter)
- [x] Fehlerbehandlung: Mapping HTTP 401→`AuthError.Expired`, 403→`AuthError.Forbidden`, 404→`NotFound`, 409→`Conflict`, 5xx→`ServerError`
- [ ] Koin-DI-Module
- [x] `core/network`: `HttpClient`-Factory als `single { provideHttpClient(env) }`
- [ ] Feature-Module binden `Repository`-Interfaces auf Default-Impl
- [ ] `AuthApiClient` (core/auth) integrieren, Token-Provider injizierbar (z. B. `() -> String?`)
- [ ] Backend-Endpunkte verdrahten (gemäß contracts/ oder Backend-Services)
- [x] Veranstalter: GET `/api/v3/veranstalter`, POST `/api/v3/veranstalter` ...
- [ ] Turniere: GET `/api/v3/turniere`, ...
- [ ] Bewerbe: GET `/api/v3/turniere/{id}/bewerbe`, ...
- [ ] Abteilungen: GET `/api/v3/bewerbe/{id}/abteilungen`, ...
- [ ] Versionierung: Präfix `/api/v3` zentral in `ApiRoutes`
- [ ] Migration: `StoreV2` schrittweise ablösen
- [ ] ViewModels von `StoreV2` auf Repositories umschalten (Feature für Feature)
- [ ] Parallelbetrieb per Toggle: `useRealBackend=true/false` (Konfig/DI)
- [ ] Entfernen von `StoreV2`, sobald Feature vollständig migriert und stabil
- [ ] Qualität & DX
- [ ] Akzeptanztests per Fake-Server (Mock Engine) gegen Repos (happy + error paths)
- [ ] Network-Error-UX: Einheitliche Fehlermeldungen/Retry in ViewModels (UDF)
- [ ] Dokumentation in `docs/06_Frontend/Networking.md` (Beispiele, Guidelines)
Referenzen (bestehend):
- frontend/core/network/src/commonMain/.../PlatformConfig.kt (expect) und js/jvm actuals
- frontend/core/auth/src/commonMain/.../AuthApiClient.kt (Keycloak/PKCE, Token-Erhalt)
- frontend/core/network/build.gradle.kts (Ktor- und Engine-Dependencies)
- frontend/core/network/src/commonMain/.../NetworkModule.kt (HttpClient-Setup, Retry/Timeout, Token-Inject)
- frontend/features/veranstalter-feature/src/jvmMain/kotlin/at/mocode/frontend/features/veranstalter/data/remote/DefaultVeranstalterRepository.kt
Akzeptanzkriterien (B-2 abgeschlossen):
- [x] `HttpClient`-Factory vorhanden, konfiguriert und via Koin injizierbar
- [x] Repository-Interfaces existieren in commonMain, mit Domain-Typen und suspend-APIs (Veranstalter, Turnier vorbereitet)
- [x] Mindestens `VeranstalterRepository` nutzt echten Backend-Client und liefert Daten
- [x] Fehler werden einheitlich modelliert und bis ins ViewModel propagiert
- [x] Ein Feature-ViewModel (z. B. Veranstalter) läuft ohne `StoreV2`
- [ ] **B-3** | Validierungs-Live-Feedback in Edit-Dialogen
- [ ] Spezifikation von 📜 Rulebook Expert (Sprint A-5) als Basis nutzen