Files
trainingstagebuch/mobile-app/TODO.md
Torsten Schulz (local) e0196a6617
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
feat(TeamManagement): enhance team management features and introduce planning phase for Android
- Updated TODO.md to outline the new planning phase for Android, aligning it with existing web functionalities for team management.
- Refactored AppDependencies to include TeamDocumentsApi, improving API integration for team-related documents.
- Replaced MobileTeamsScreen with TeamManagementScreen in ClubStammdatenScreens for better navigation.
- Enhanced TeamManagementScreen with improved state management and UI updates for team editing and data loading.
- Added new API methods in ClubTeamsApi for managing team lineups, supporting better team planning and organization.
- Introduced new methods in MatchesApi and MyTischtennisApi to enhance match and team data handling.
2026-05-14 18:31:15 +02:00

23 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: Single-Activity-Modell mit MainTab + zustandsbasierter Tiefe (Tagebuch-Tag, Mitglieder-Details, Einstellungen-Unterseiten); Rail/Bottom-Nav; kein zentraler Navigation-Compose-NavHost für die Shell (bewusste Entscheidung, später migrierbar) siehe DEVELOPMENT.md § Architektur Phase 0, Umsetzung AppRoot.kt
  • Feature-Paketierung: Richtlinie und Ist: APIs/DTOs/Manager im shared, UI in composeApp/.../ui/ mit featurebezogenen Dateien; schrittweise Entschlackung großer Dateien DEVELOPMENT.md § Architektur Phase 0
  • Use-Cases: Geschäftslogik überwiegend in shared/state/*Manager und gezielt in plattformnahen Helfern (CalendarAggregator o. ä.); Composables orchestrieren DEVELOPMENT.md § Architektur Phase 0
  • 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): v1 ohne Web-Socket; Aktualisierung über LaunchedEffect / manuelles Neuladen dokumentiert; optional Socket/Polling später DEVELOPMENT.md § Architektur Phase 0
  • Medien: Coil für Bilder, FileProvider + Share-Intents für PDF; dokumentiert in DEVELOPMENT.md § Architektur Phase 0
  • Ö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) — 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 / canWriteSchedule in ClubPermissionHelpers.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/:id für Detail UI TournamentsScreen.kt, TournamentsApi, ClubInternalTournamentsManager
  • Offizielle Teilnahmen (OfficialTournaments.vue): GET /api/official-tournaments/:clubId, GET .../participations/summary OfficialTournamentsApi, OfficialTournamentsReadManager, gleicher Screen
  • Navigation: Tab Turniere (MainTab.Tournaments) bei canReadTournaments(), Start-Kachel; Deep-Link /tournaments fü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 (Mannschaften + Editor) TeamManagementScreen + TeamEditorScreen: Saison, Suche, CRUD Mannschaften; Tabs Stammdaten, Spielerstatistik (Liga), Aufstellung/Meldung, Dokumente, Scheduler-Jobs, MyTT (ClubTeamsApi, MatchesApi, TeamDocumentsApi, ApiLogsApi, MyTischtennisApi, Rechte canReadTeams/canWriteTeams)
  • Mannschafts-Planung (Android) siehe Unterabschnitt Phase 8a (Web hat das Planungsboard bereits; mobil bewusst offen)
  • Berechtigungen erweiterte PermissionsApi, PermissionsAdminManager, UI Rolle/Status/Anpassen mit RolePermissionMatrix (ClubAdminScreens.kt)
  • Logs ApiLogsApi, ApiLogsManager, Liste + Pagination + Detail (ClubAdminScreens.kt); AppDependencies / Logout / 401 räumen Manager auf

Phase 8a Mannschafts-Planung auf Android (Backlog / Plan)

Ziel: Gleiche fachliche Funktion wie Web Team-Verwaltung → Planung: Pool „möchte spielen“, mehrere Mannschaften der Saison parallel, Spieler nur eligibility-konform zuordnen, lokale Stammdaten (Name, geplante Liga, AK/GK) pro Team, Meldung (Lineup) je Team und gewählter Halbserie lesen/schreiben, optional Debounced Autosave wie Web.

Web-Referenz (1:1 zum Durchlesen der Logik):

Bereich Datei / Abschnitt
Umschalter „Mannschaften“ / „Planung“, Board einbinden frontend/src/views/TeamManagementView.vue (activeMainSection, TeamPlanningBoard)
UI Pool, Teams, Suche, Interesse markieren frontend/src/components/team/TeamPlanningBoard.vue
Lanes / Drag-Drop frontend/src/components/team/TeamPlanningLane.vue

Backend-APIs (aus Web apiClient; im shared ergänzen, falls noch fehlend):

  • GET /api/clubmembers/play-interest/:clubId mit Query seasonId, lineupHalf geladene Interessen für Pool (loadPlanningInterestedMemberIds)
  • POST /api/clubmembers/play-interest/:clubId Body memberId, seasonId, lineupHalf, interested Mitglied als „interessiert“ markieren (onPlanningMarkMemberInterested)
  • GET /api/clubmembers/get/:clubId/:showAll bereits MembersApi.listMembers
  • GET /api/club-teams/... Mannschaften Saison, GET …/lineup?half=, PUT …/lineup ClubTeamsApi (Planung lädt Lineups aller Teams der Saison parallel wie Web loadPlanningAssignments)
  • PUT /api/club-teams/:id Stammdaten Planungsteam (updateClubTeam)
  • POST /api/club-teams/club/:clubId neue Planungs-Mannschaft (createClubTeam o. ä.)
  • DELETE /api/club-teams/:id Planungs-Mannschaft löschen

Shared / Domäne:

  • DTOs für Play-Interest (Response-Zeilen: memberId, interested, …) + MembersApi Erweiterung
  • Optional: PlanningState-Use-Case (normalisierte Zuordnungen teamId/memberId/position, Halbserie, Recompute bei AK/GK-Wechsel) Web: normalizePlanningAssignments, removeAllIneligiblePlanningAssignments, isEligibleForPlanningTeam (analog TeamEditorLineupLogic.isEligibleForTeam + Team-spezifische AK/GK aus planningLocalTeams)

Android UI (Vorschlag für Umsetzungsschritte):

  1. Einstieg: In TeamManagementScreen (oder AppRoot) zweiter Modus „Planung“ neben „Mannschaften“ (wie Web-Workspace-Buttons), gleiche Saison-Auswahl wie Liste
  2. Screen TeamPlanningScreen.kt (oder modular TeamPlanningPool.kt / TeamPlanningTeamCard.kt): Pool + Liste der Teams; kein 1:1-Spiegel der Web-Grid-Optik nötig, aber alle Aktionen abdeckbar
  3. Drag-and-Drop: Entweder Compose Drag-and-Drop (Plattform-API) oder Fallback ohne DnD: „Mitglied auswählen → Ziel-Mannschaft“ / „Aus Mannschaft entfernen“ / Reihenfolge ↑↓ in der Lane (wie Aufstellungs-Tab)
  4. Halbserie (VR/RR) gemeinsam mit Web-Parameter lineupHalf an Play-Interest und Lineup-Requests
  5. „In Workspace öffnen“ / Team-Editor: Web convertPlanningTeamToRegular prüfen ggf. nur Navigation zum bestehenden TeamEditorScreen statt Konvertierungs-API
  6. Autosave: Web nutzt Debounce (schedulePlanningTeamAutosave) mobil entweder gleichziehen oder explizit „Speichern“ pro Team + Konflikt-Hinweis (Produktentscheidung)
  7. i18n: Keys aus teamManagement.planning* / markAsInterested usw. in MobileStrings oder Fallback-Kette wie andere Admin-Screens
  8. Tests: Serialisierung Play-Interest; optional Snapshot der Normalisierung planningAssignments

Hinweis im Code: Solange 8a offen ist, kann im Tab Aufstellung ein kurzer Verweis auf die zukünftige in-App-Planung stehen (nach Umsetzung Text anpassen oder entfernen).


Phase 9 Vereins- & Stammdaten-Einstellungen

  • ClubSettings (ClubSettings.vue) Kernfelder in ClubStammdatenScreens.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 (PersonalSettings.vue) Mehr → Hub: Sprache, MyTT, ClickTT; PersonalHubScreens.kt + AppRoot.kt SettingsScreen
  • MyTischtennis-Konto (MyTischtennisAccount.vue) MyTischtennisApi, Dialog/Verify/Unlink in PersonalHubScreens.kt
  • ClickTT-Konto (ClickTtAccount.vue) ClickTtAccountApi, analog in PersonalHubScreens.kt
  • ClickTT-Ansicht (ClickTtView.vue) Proxy-URL + WebView in ClickTtBrowserScreen

Phase 11 Abrechnung & Bestellungen

  • Orders (OrdersView.vue / OrdersPanel.vue global) MemberOrdersApi, MemberOrderDtos.kt, BillingOrdersScreens.kt (GlobalOrdersScreen)
  • Billing (BillingView.vue) Kernfluss ohne Web-PDF-Mapping-Editor BillingApi, BillingDtos.kt, BillingClubScreen (Vorlagen-Upload, Vorschau, Lauf anlegen, PDF erzeugen/teilen, Läufe); Mapping weiter über Browser
  • Rechtliches/UX: Button Abrechnung im Browser (/billing) für volle Web-Funktion; PDF-Teilen wie Tagebuch-PDF

Phase 12 Kalender (Vereinskalender)

Web-Route: /calendar · Referenz: CalendarView.vue (Aggregation mehrerer Datenquellen in einer Monatsansicht).

  • Navigation & Shell: Haupt-Tab MainTab.Calendar + Start-Hub-Kachel (AppRoot.kt), Monat vor/zurück, „Heute“, Monatsüberschrift (CalendarScreen.kt)
  • Monatsgitter: 7×6, außerhalb Monat / heute, Wochentagskopf (CalendarScreen.kt, CalendarAggregator.kt)
  • Legende / Filter: Eventtypen mit Schalter und Zähler (CalendarScreen.kt)
  • Daten laden (parallel, teilfehlertolerant): supervisorScope + async in CalendarScreen.kt; Quellen: DiaryManager.listDates, Trainingszeiten, TrainingCancellationApi, TournamentsApi, MatchesApi, OfficialTournamentsReadManager, CalendarHolidayApi (CalendarDtos.kt, APIs in shared)
  • Logik: CalendarAggregator.kt (wiederkehrende Zeiten, Merge, Ausfälle) an Web angelehnt
  • Trainingsausfall: Formular + Liste im Monat + API (TrainingCancellationApi, CalendarScreen.kt)
  • Agenda: sortierte Monatsliste (CalendarAggregator.eventsInMonth, CalendarScreen.kt)
  • Event-Aktion: CalendarEventAction → Tagebuch-Tag/Tab, Terminplan, Turniere, Web /tournament-participations (calendar/CalendarAggregator.kt / CalendarScreen.kt, Verdrahtung AppRoot.kt)
  • i18n: MobileStrings-Keys mit Fallback in CalendarScreen.kt / AppRoot.kt (navigation.calendar, home.tileCalendar, mobile.calendar*)
  • Web-Parität (Detail): Meldung wenn alle Kalender-Quellen fehlschlagen; Legenden-Zähler aus allen Events (unabhängig von den Schaltern); Agenda-Datum kurz/lokalisiert; Ausfall-Liste nur wenn Startdatum im Monat liegt (wie CalendarView.vue) CalendarScreen.kt

Phase 12 Backlog / offen

  • i18n: Kalender-Keys in MobileStrings.kt für alle unterstützten Sprachen ergänzen (nicht nur Fallback im Code)
  • Kalender vs. Web: Offizielle Teilnahmen mobil per Browser vs. Web in-app bewusst lassen oder später angleichen
  • Release: Bei isMinifyEnabled = true ProGuard/R8 für Ktor, kotlinx.serialization, ggf. Koin (composeApp/proguard-rules.pro)
  • Turniere (Produktiv-Crash): LazyColumn mit eindeutigen Keys (itemsIndexed für Vereins-Turniere, offizielle Liste, Teilnahmen-Zeilen), vermeidet Duplicate-Key-Abstürze; zudem tolerante Deserialisierung für allowsExternal / isDoublesTournament (0/1, Strings) TournamentsScreen.kt, FlexibleBooleanSerializers.kt, TournamentDtos.kt

Phase 13 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. Kalender: /calendar → Phase 12.