Files
trainingstagebuch/mobile-app/TODO.md
Torsten Schulz (local) 1e23171370
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 42s
feat(TournamentTab): add HTML escaping utility and improve player name rendering
- Introduced `escapeHtml` method to sanitize HTML content, enhancing security against XSS attacks.
- Refactored player name rendering in tournament results to utilize the new HTML escaping method, ensuring safe display of player names and table data.
2026-05-12 23:23:04 +02:00

13 KiB
Raw Blame History

Mobile App TODO Web-Parität (Android, KMP-Shared)

Dieses Dokument ist die Arbeitsliste, um die funktionale Abdeckung der Web-App (frontend/src/router.js, Views unter frontend/src/views/) in der nativen Android-App (Jetpack Compose, Shared Code unter mobile-app/shared) nachzubauen.

Wichtig: Ein „komplettes“ Umsetzen dieser Liste ist ein Mehrmonats-/Team-Projekt. Es wird iterativ abgearbeitet; unten sind nur die Punkte angehakt, die im Code tatsächlich vorhanden sind (Stand siehe Git). Alles andere bleibt offen.

Legende: [x] umgesetzt · [ ] offen · Die „Baseline“ am Ende beschreibt den älteren Grundstock.

Vorgehen: Pro Phase vertikale Schnitte (API im shared Modul → Manager/Use-Case → UI). Web-Referenz immer die gleichnamige *.vue-Datei und apiClient-Aufrufe darin.


Bereits umgesetzt (Baseline, Stand 2026-05)

  • Auth (authcode), Token-Persistenz, 401 → Login
  • Club-Auswahl, Permissions, Access-Request
  • Tabs inkl. Start-Hub (MainTab.Home), Unter-Screens (Tagebuch-Tag, Mitglied-Detail), Tab-/Rail ausblenden in Details
  • Tagebuch: Datenliste, Tag-Detail, Zeiten, Notizen, Tags (Tagesbezug), Freitext-Aktivitäten (/activities), Trainingsplan lesen & CRUD (Phase 3.2), Teilnehmer an/ab (einklappbare Liste, standard eingeklappt), Zuordnung zu Plan-Aktivitäten (3.4), Unfälle/Vorfälle (3.7), Löschen Tag
  • Mitglieder: Liste, Suche, statisches Detail
  • Trainings-Statistik: Basis-KPIs + Top-Liste
  • Einstellungen: Sprache, Session-Check, Logout, Backend-Anzeige
  • i18n-Generator + MobileStrings
  • Theming näher an Web (TtTagebuchTheme)

Phase 0 Architektur & Grundlagen für Vollausbau

  • Navigation: Zentraler Nav-Graph (z. B. Navigation Compose) mit Back-Stack pro Tab oder einheitlichem Stack; Tiefe: Club → Modul → Unterseiten
  • Feature-Paketierung: UI/API pro Bereich trennen (diary, members, schedule, …), Composables entschlacken
  • Use-Cases: Geschäftslogik aus Composables in testbare Funktionen/Klassen im shared
  • Fehlerbild (Basis): JSON-Fehlerbody (error / message) aus API-Antworten → [ApiException]-Text (ApiErrorMessage.kt, authed + public Client); bekannte Tokens (alreadyexists, …) → Deutsch; Retries bewusst noch offen
  • Echtzeit (optional): Socket-Events wie Web (socketService) oder dokumentiertes Polling nach Schreiboperationen
  • Medien: Entscheidung Bilder/PDF (Coil, Cache, Download, Intents)
  • Öffentlicher HTTP-Client ohne Auth-Header (PublicHttpClient, PublicAuthApi im shared)

Phase 1 Auth, Onboarding, öffentliche Seiten

Web-Routen: /login, /register, /activate/:code, /forgot-password, /reset-password/:token, /impressum, /datenschutz, / (Home öffentlich)

  • Registrierung (Register.vue) Android: RegisterScreen, POST /api/auth/register
  • Account aktivieren (Activate.vue) Android: ActivateAccountScreen, GET /api/auth/activate/:code
  • Passwort vergessen / E-Mail (ForgotPassword.vue) ForgotPasswordScreen, POST /api/auth/forgot-password
  • Passwort setzen mit Token (ResetPassword.vue) ResetPasswordScreen, POST /api/auth/reset-password
  • Home / Landing eingeloggt (Home.vue) Tab Start: Willkommen, Kacheln zu Tagebuch/Mitglieder/Statistik/Mehr, Vereinsinfos via GET /api/clubs/:id (HomeScreen, ClubsApi.getClub)
  • Impressum Einstellungen → öffnet BACKEND_BASE_URL/impressum im Browser
  • Datenschutz Einstellungen → öffnet BACKEND_BASE_URL/datenschutz im Browser
  • SEO-Marketingseiten (TableTennisClubSoftware, ClubMemberManagementPage, …): nur falls im Store gefordert; sonst [ ] optional / nicht mobil

Phase 2 Verein anlegen & Vereins-Ansicht

  • Verein erstellen (CreateClub.vue) + API POST /api/clubs, ClubSelectScreen + ClubManager.createClub
  • Vereins-Profil / Show Club (ClubView.vue) Basis: erweitertes Club-Modell + Karte auf Start (Begrüßung, Verbands-Nr., MyTischtennis-Kürzel); volle Parität (Links, Zahlen) offen

Phase 3 Tagebuch (DiaryView) Hauptblock

Web: DiaryView.vue (sehr groß). API-Cluster (Auszug in Web nach apiClient verifizieren):

3.1 Tages-Metadaten & Listen

  • Tagebuch-Daten vollständig laden beim Datumswechsel Plan, Trainingsgruppen und Teilnehmer parallel in einem LaunchedEffect (DiaryDetailScreen)
  • Aktivitäten-Liste /activities/:dateIdDiaryApi.listFreeformActivities / addFreeformActivity, Abschnitt „Weitere Tages-Aktivitäten“ im Tagebuch-Detail

3.2 Trainingsplan (CRUD)

  • Plan laden: GET /diary-date-activities/:clubId/:diaryDateIdDiaryApi / Tagebuch-Detail
  • Einträge anlegen: POST /diary-date-activities/:clubId, ggf. Gruppe POST /diary-date-activities/group — Android-Formulare + CreateDiaryPlanActivityRequest / AddDiaryPlanGroupActivityRequest
  • Einträge bearbeiten: PUT /diary-date-activities/:clubId/:id (Zuordnung groupId im Body wie Backend) — Dialog „Bearbeiten“; Unter-Einträge (GroupActivity): API updateNestedGroupActivity, mobil z.B. nur Löschen
  • Reihenfolge: PUT .../order — ↑/↓ je Trainingsgruppen-Scope
  • Löschen: DELETE ..., Gruppen-Aktivität DELETE .../group/...
  • Zeitblöcke (isTimeblock) inkl. UX wie Web — Checkbox beim Anlegen, Kennzeichnung in der Karte
  • Gruppen für Plan: GET/POST/DELETE /api/groupGroupApi + Liste mit Löschen; PUT Umbenennen (changeGroup) nur API, keine eigene UI

3.3 Teilnehmer & Status

  • Liste: GET /participants/:dateId

  • Hinzufügen/Entfernen: POST /participants/add, POST /participants/remove

  • Status entschuldigt/abgesagt: PUT /participants/:dateId/:memberId/status

  • Gruppenzuordnung Training: PUT /participants/:dateId/:memberId/groupParticipantsApi.updateParticipantGroup, Dropdown bei anwesenden Teilnehmern wenn Trainingsgruppen existieren

  • UX: Teilnehmerliste im Tagebuch-Detail aufklappbar, standard eingeklappt (DiaryDetailScreen)

  • GET /diary-member-activities/:clubId/:activityIdDiaryMemberActivitiesApi / „Wer macht mit?“ je Planzeile bzw. Gruppen-Aktivität

  • Zuweisen: POST ... mit participantIds — inkl. ensureParticipantRowId wenn noch keine Teilnehmer-Zeile

  • Entfernen: DELETE .../:participantId

3.5 Mitgliedsbezogene Notizen/Tags im Tagebuch

  • GET/POST .../diarymember/:clubId/note, DELETE .../note/:id (mit diaryDateId/memberId als Query) — DiaryMemberApi / Dialog „Notizen & Tags“ je Teilnehmer
  • GET/POST .../diarymember/:clubId/tag, POST .../tag/remove — bestehende Tags, neu anlegen (POST /tags + Verknüpfung)

3.6 Predefined Activities (Auswahl & Suche im Tagebuch)

  • GET /predefined-activities, GET ...?scope=standard, GET /search/query — Trainingsplan anlegen (global + Gruppe) und Eintrag bearbeiten (Suche / vordefinierte ID)
  • GET /predefined-activities/:idPredefinedActivitiesApi.getById / DiaryManager.getPredefinedActivity (für spätere Detail-UI)

3.7 Unfälle / Vorfälle

  • POST /accident, GET /accident/:clubId/:diaryDateIdAccidentApi / DiaryManager / Abschnitt im Tagebuch-Detail

3.8 Galerie & Bilder

  • Mitgliederbilder: memberProfileImagePath + AuthenticatedAsyncImage (Coil mit diaryAuthHeaders) in der Teilnehmerliste bei diary.read + members.read
  • Übungs-/Predefined-Bilder: DiaryImagePaths (mainActivityImagePath / nestedActivityImagePath) + ApiConfig.toAbsoluteUrl, Vollbild-Dialog im Tagebuch-Detail
  • Gruppenfotos: MemberGroupPhotosApi (GET/POST/DELETE /api/member-group-photos/:clubId), Galerie-Abschnitt + PickVisualMedia in DiaryDetailScreen

3.9 PDF / Export

  • Trainingsplan- und Tages-PDF (DiaryPdfExporter / writeTrainingPlanPdf, writeTrainingDaySummaryPdf), Teilen über FileProvider + sharePdfFile (DiaryPdfShare)

3.10 Sonstiges Diary-UX

  • Web-DiaryView → mobil (Kurzüberblick): Tages-Metadaten, Plan inkl. Zeitblöcke/Gruppen, Teilnehmer inkl. Status/Gruppe, „Wer macht mit?“, Freitext-Aktivitäten, Tags/Notizen, Unfälle, Mitglieds-Notizen/Tags-Dialog, Galerie, PDF-Exporte ohne die vielen Web-Tabs als 1:1-Spiegel; fehlende Parität steht in den Phasen 4+ / offenen Punkten.
  • Berechtigungen: ClubPermissionHelpers (canReadDiary, canWriteDiary, canReadMembers, canWriteMembers) Lese-Hinweis, Schreib-Aktionen und Gruppenfoto-Löschen in AppRoot.kt / DiaryDetailScreen entsprechend gekapselt

Phase 4 Mitglieder (MembersView) — erledigt

  • Mitglied-CRUD: POST /api/clubmembers/set/:clubIdMembersApi.setMember, MemberSetBody / Member.toSetBody, MembersManager.saveMember; neu + bearbeiten in MemberEditRoute (AppRoot.kt)
  • Felder / Formulare: Stammdaten, Adresse, mehrere Telefon- und E-Mail-Zeilen (Primär, Elternkontakt, Name) wie Web-contacts, Status (aktiv, Testmitglied, Formular, Freigaben, Bilder Internet), Geschlecht; TTR/QTTR nur Anzeige beim Bearbeiten
  • Profilbild: POST /api/clubmembers/image/... (Multipart) — MembersApi.uploadMemberPortrait, Galerie-Pick + UCrop in MemberDetailRoute / MemberPortraitCrop.kt
  • Aktivität / letzte Teilnahmen: GET /api/member-activities/:clubId/:memberId (Perioden-Query), .../last-participationsMemberActivitiesApi, Abschnitte im Profil
  • Trainingsgruppen: GET/POST/DELETE /api/training-groups/...TrainingGroupsApi, Zuweisen/Entfernen im Profil
  • Trainingszeiten (Verein): GET /api/training-times/:clubIdTrainingTimesApi, Anzeige je Gruppe im Profil
  • Bild zuschneiden: Yalantis UCrop nach PickVisualMedia — JitPack, UCropActivity im Manifest

Phase 5 Trainings-Statistik (Parität TrainingStatsView) — erledigt

  • DTO / API: TrainingStats.kt weekdayStats, monthlyTrend, memberDistribution, overview.bestTrainingDay, Mitglied mit birthDate, participationRate12Months, trainingGroups, trainingDetails, lastTrainingTs usw.
  • Ableitungen wie Web: TrainingStatsDerived.kt Filter (Wochentag, Trainingstag, Gruppe), filteredOverview, Monats-/Wochentags-Trends, Mitgliederstruktur, Gruppen-Performance, Altersklassen, Sortierung, CSV
  • UI: TrainingStatsScreen.kt Kennzahlen-Kacheln, Panels, kollabierbare Listen Trainingstage/Mitglieder, Detail-Dialog, CSV-Share (shareFileWithMime in DiaryPdfShare.kt)
  • i18n-Local: LanguageLocals.kt (LocalLanguageCode) aus AppRoot.kt ausgelagert
  • Hinweis: Web hat keinen CSV-Export für diese Statistik; mobil zusätzlich CSV exportieren (gefilterte/sortierte Mitgliederliste)

Phase 6 Terminplan (ScheduleView)

  • Kalender-/Listenansicht, CRUD oder Sync wie Web
  • API-Endpunkte aus ScheduleView.vue ins shared übernehmen

Phase 7 Turniere

  • TournamentsView.vue Vereinsturniere
  • OfficialTournaments.vue / offizielle Teilnahmen
  • TournamentTab.vue eingebettete Logik, soweit mobil relevant
  • API aus jeweiligen Views dokumentieren und abarbeiten

Phase 8 Freigaben & Verwaltung

  • Ausstehende Freigaben (PendingApprovalsView.vue)
  • Team-Management (TeamManagementView.vue)
  • Berechtigungen (PermissionsView.vue) rollenbasiert
  • Logs (LogsView.vue) eher Admin; nur wenn nötig mobil

Phase 9 Vereins- & Stammdaten-Einstellungen

  • ClubSettings (ClubSettings.vue) alle Unterbereiche
  • Predefined Activities Verwaltung (PredefinedActivities.vue) CRUD, Bilder/Zeichnungen falls API
  • Mitgliedstransfer-Einstellungen (MemberTransferSettingsView.vue)

Phase 10 Persönliche Konten & Integrationen

  • Persönliche Einstellungen vollständig (PersonalSettings.vue vs. aktuelles „Mehr“)
  • MyTischtennis-Konto (MyTischtennisAccount.vue)
  • ClickTT-Konto (ClickTtAccount.vue)
  • ClickTT-Ansicht (ClickTtView.vue)

Phase 11 Abrechnung & Bestellungen

  • Orders (OrdersView.vue)
  • Billing (BillingView.vue)
  • Rechtliches/UX: ggf. WebView oder Deep-Link, wenn Zahlungsflüsse web-only

Phase 12 Qualität, Tests, Release

  • Regression-Checkliste pro Phase (manuell)
  • Automatisierte Tests: shared (Serialisierung, Mapper), wo möglich UI-Tests kritische Flows
  • Barrierefreiheit: Talkback, Kontraste, Touch-Ziele
  • Performance: große Listen (Paging), Bildcache
  • Store-Texte, Datenverarbeitung (Play Policy) für Medien und Kontakte

Hinweise zur Pflege dieser Liste

  1. Beim Abhaken eines Punktes kurz vermerken (Commit-Message oder Unterpunkt), welche Datei/API neu ist.
  2. Wenn Web eine Funktion einstellt oder API ändert: TODO hier und DEVELOPMENT.md anpassen.
  3. DiaryView zuerst in Unterkapitel zerlegen (3.13.10), dann Issues/PRs pro Unterkapitel sonst bleibt der Block unendlich.

Referenz: Web-Routen (Router)

Siehe frontend/src/router.js jede path-Zeile sollte langfristig einem mobilen Eintrag (oder einer bewussten Ausnahme) zugeordnet sein.