- Added logic in MatchService to filter matches based on the user's own teams, ensuring only relevant matches are displayed. - Updated the mobile app's TODO list to reflect progress on ClubSettings and Predefined Activities features. - Enhanced the AppRoot and ClubStammdatenScreens to support new settings and permissions for club management. - Introduced new API methods for creating and updating training groups and times, improving the training management capabilities. - Refactored MembersManager to include methods for managing training groups and times, streamlining the member management process.
15 KiB
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,PublicAuthApiimshared)
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 viaGET /api/clubs/:id(HomeScreen,ClubsApi.getClub) - Impressum – Einstellungen → öffnet
BACKEND_BASE_URL/impressumim Browser - Datenschutz – Einstellungen → öffnet
BACKEND_BASE_URL/datenschutzim 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: erweitertesClub-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/:dateId—DiaryApi.listFreeformActivities/addFreeformActivity, Abschnitt „Weitere Tages-Aktivitäten“ im Tagebuch-Detail
3.2 Trainingsplan (CRUD)
- Plan laden:
GET /diary-date-activities/:clubId/:diaryDateId—DiaryApi/ Tagebuch-Detail - Einträge anlegen:
POST /diary-date-activities/:clubId, ggf. GruppePOST /diary-date-activities/group— Android-Formulare +CreateDiaryPlanActivityRequest/AddDiaryPlanGroupActivityRequest - Einträge bearbeiten:
PUT /diary-date-activities/:clubId/:id(ZuordnunggroupIdim Body wie Backend) — Dialog „Bearbeiten“; Unter-Einträge (GroupActivity): APIupdateNestedGroupActivity, mobil z. B. nur Löschen - Reihenfolge:
PUT .../order— ↑/↓ je Trainingsgruppen-Scope - Löschen:
DELETE ..., Gruppen-AktivitätDELETE .../group/... - Zeitblöcke (
isTimeblock) inkl. UX wie Web — Checkbox beim Anlegen, Kennzeichnung in der Karte - Gruppen für Plan:
GET/POST/DELETE /api/group—GroupApi+ 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/group—ParticipantsApi.updateParticipantGroup, Dropdown bei anwesenden Teilnehmern wenn Trainingsgruppen existieren -
UX: Teilnehmerliste im Tagebuch-Detail aufklappbar, standard eingeklappt (
DiaryDetailScreen) -
GET /diary-member-activities/:clubId/:activityId—DiaryMemberActivitiesApi/ „Wer macht mit?“ je Planzeile bzw. Gruppen-Aktivität -
Zuweisen:
POST ...mitparticipantIds— inkl.ensureParticipantRowIdwenn noch keine Teilnehmer-Zeile -
Entfernen:
DELETE .../:participantId
3.5 Mitgliedsbezogene Notizen/Tags im Tagebuch
GET/POST .../diarymember/:clubId/note,DELETE .../note/:id(mitdiaryDateId/memberIdals Query) —DiaryMemberApi/ Dialog „Notizen & Tags“ je TeilnehmerGET/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/:id—PredefinedActivitiesApi.getById/DiaryManager.getPredefinedActivity(für spätere Detail-UI)
3.7 Unfälle / Vorfälle
POST /accident,GET /accident/:clubId/:diaryDateId—AccidentApi/DiaryManager/ Abschnitt im Tagebuch-Detail
3.8 Galerie & Bilder
- Mitgliederbilder:
memberProfileImagePath+AuthenticatedAsyncImage(Coil mitdiaryAuthHeaders) in der Teilnehmerliste beidiary.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 +PickVisualMediainDiaryDetailScreen
3.9 PDF / Export
- Trainingsplan- und Tages-PDF (
DiaryPdfExporter/writeTrainingPlanPdf,writeTrainingDaySummaryPdf), Teilen überFileProvider+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 inAppRoot.kt/DiaryDetailScreenentsprechend gekapselt
Phase 4 – Mitglieder (MembersView) — erledigt
- Mitglied-CRUD:
POST /api/clubmembers/set/:clubId—MembersApi.setMember,MemberSetBody/Member.toSetBody,MembersManager.saveMember; neu + bearbeiten inMemberEditRoute(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 inMemberDetailRoute/MemberPortraitCrop.kt - Aktivität / letzte Teilnahmen:
GET /api/member-activities/:clubId/:memberId(Perioden-Query),.../last-participations—MemberActivitiesApi, Abschnitte im Profil - Trainingsgruppen:
GET/POST/DELETE /api/training-groups/...—TrainingGroupsApi, Zuweisen/Entfernen im Profil - Trainingszeiten (Verein):
GET /api/training-times/:clubId—TrainingTimesApi, Anzeige je Gruppe im Profil - Bild zuschneiden: Yalantis UCrop nach
PickVisualMedia— JitPack,UCropActivityim Manifest
Phase 5 – Trainings-Statistik (Parität TrainingStatsView) — erledigt
- DTO / API:
TrainingStats.kt–weekdayStats,monthlyTrend,memberDistribution,overview.bestTrainingDay, Mitglied mitbirthDate,participationRate12Months,trainingGroups,trainingDetails,lastTrainingTsusw. - 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 (shareFileWithMimeinDiaryPdfShare.kt) - i18n-Local:
LanguageLocals.kt(LocalLanguageCode) ausAppRoot.ktausgelagert - Hinweis: Web hat keinen CSV-Export für diese Statistik; mobil zusätzlich CSV exportieren (gefilterte/sortierte Mitgliederliste)
Phase 6 – Terminplan (ScheduleView) — erledigt
- DTOs:
Schedule.kt–ClubTeamDto,ScheduleMatchDto,LeagueTableRowDto,UpdateMatchPlayersBody,ScheduleMatchScope,ScheduleViewMode - APIs:
ClubTeamsApi(GET /api/club-teams/club/:clubId),MatchesApi(/api/matches/leagues/...matches + Tabelle,PATCH /api/matches/:matchId/players) - Logik:
ScheduleLogic.kt– Sortierung, Merge, Filter „Erwachsene“, Mannschafts-Scope wie Web - State:
ScheduleManager.kt– Mannschaften laden, Mannschafts-/Gesamt-/Erwachsenen-Ansicht, Tabelle, Spieler-Patch + Refresh - Berechtigungen:
canReadSchedule/canWriteScheduleinClubPermissionHelpers.kt - UI:
ScheduleScreen.kt– Tab Terminplan (MainTab.Schedule), Home-Kachel bei Lese-Recht, Liste + Detail, Aufstellung (R/P/S) bei Schreib-Recht - Noch nicht mobil: CSV-Import (
POST /api/matches/import), MyTT-Tabellen-Fetch (POST .../table/.../fetch), Galerie/Lineup wie Web – bei Bedarf spätere Phase
Phase 7 – Turniere
- Vereins-Turniere (
TournamentsView.vue/TournamentTab.vue):GET /api/tournament/:clubId(optional?type=mini), clientseitig intern/offen wie Web;GET /api/tournament/:clubId/:idfür Detail – UITournamentsScreen.kt,TournamentsApi,ClubInternalTournamentsManager - Offizielle Teilnahmen (
OfficialTournaments.vue):GET /api/official-tournaments/:clubId,GET .../participations/summary–OfficialTournamentsApi,OfficialTournamentsReadManager, gleicher Screen - Navigation: Tab Turniere (
MainTab.Tournaments) beicanReadTournaments(), Start-Kachel; Deep-Link/tournamentsfür volle Web-Verwaltung - Nicht mobil: PDF-Import, Meldungen/ClickTT-Workflows, Spielstände pflegen, Gruppen/K.O. wie Web – bewusst Web-only
Phase 8 – Freigaben & Verwaltung
- Ausstehende Freigaben –
ClubApprovalsApi,PendingApprovalsManager, Screen unter „Mehr“ → Club-Verwaltung (ClubAdminScreens.kt) - Team-Management – Deep-Link
openBackendPath("/team-management")beicanReadTeams()(volle Parität zur Web-TeamManagementViewbewusst nicht mobil) - Berechtigungen – erweiterte
PermissionsApi,PermissionsAdminManager, UI Rolle/Status/Anpassen mitRolePermissionMatrix(ClubAdminScreens.kt) - Logs –
ApiLogsApi,ApiLogsManager, Liste + Pagination + Detail (ClubAdminScreens.kt);AppDependencies/ Logout / 401 räumen Manager auf
Phase 9 – Vereins- & Stammdaten-Einstellungen
- ClubSettings (
ClubSettings.vue) – Kernfelder inClubStammdatenScreens.kt+ Link Web; tiefergehend nur Web - Predefined Activities (
PredefinedActivities.vue) – Liste, Neu, Bearbeiten (PredefinedActivitiesApi); Medien/Web-only falls nötig - Mitgliedstransfer (
MemberTransferSettingsView.vue) – Basis in App, erweitert über Web-Link
Phase 10 – Persönliche Konten & Integrationen
- Persönliche Einstellungen vollständig (
PersonalSettings.vuevs. 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
- Beim Abhaken eines Punktes kurz vermerken (Commit-Message oder Unterpunkt), welche Datei/API neu ist.
- Wenn Web eine Funktion einstellt oder API ändert: TODO hier und
DEVELOPMENT.mdanpassen. - DiaryView zuerst in Unterkapitel zerlegen (3.1–3.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.