- Changed file permissions from 644 to 755 for various files in the mobile-app and mobile-app_legacy_rn_expo directories, ensuring executable permissions where necessary. - Added a new SQL migration script to the backend to introduce missing columns for club billing and invoice settings in the clubs table, maintaining synchronization with the current Sequelize model.
22 KiB
Executable File
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-NavHostfür die Shell (bewusste Entscheidung, später migrierbar) – sieheDEVELOPMENT.md§ Architektur Phase 0, UmsetzungAppRoot.kt - Feature-Paketierung: Richtlinie und Ist: APIs/DTOs/Manager im
shared, UI incomposeApp/.../ui/mit featurebezogenen Dateien; schrittweise Entschlackung großer Dateien –DEVELOPMENT.md§ Architektur Phase 0 - Use-Cases: Geschäftslogik überwiegend in
shared/state/*Managerund gezielt in plattformnahen Helfern (CalendarAggregatoro. ä.); 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,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) bearbeiten, Teilnehmer zuordnen und Drawing pflegen - 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/PUT/DELETE /api/group— Liste mit Mehrfachanlage, Lead-/Namensbearbeitung und bestaetigtem Loeschen - Drawing: Objekt-/String-kompatible API-Daten, Editor mit Folgeschlaegen, Anzeige nur per Icon und Vorschau-Dialog; Backend speichert
drawingDataohne doppelte Serialisierung
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) -
Testmitglieder-Workflow: Filter/Suche, Schnellanlage im Trainingstag, Formular-Uebergabe und Warnhinweis nach mehreren Teilnahmen
-
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) - Tages-PDF mit Plan-Gruppen und den je Aktivitaet/Unteraktivitaet zugeordneten Teilnehmern
3.10 Sonstiges Diary-UX
- Web-DiaryView → mobil (Kurzüberblick): Tages-Metadaten, sicher bestaetigtes Loeschen, Plan inkl. Zeitbloecke/Gruppen/Filter/Drawings und korrektem Bereitschaftsstatus, Teilnehmer inkl. Status/Gruppe/Testworkflow, „Wer macht mit?“, Freitext-Aktivitaeten, Tags/Notizen, Unfaelle, Galerie sowie PDF-Exporte.
- 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 (Mannschaften + Editor) –
TeamManagementScreen+TeamEditorScreen: Saison, Suche, CRUD Mannschaften; Tabs Stammdaten, Spielerstatistik (Liga), Aufstellung/Meldung, Dokumente, Scheduler-Jobs, MyTT (ClubTeamsApi,MatchesApi,TeamDocumentsApi,ApiLogsApi,MyTischtennisApi, RechtecanReadTeams/canWriteTeams) - Mannschafts-Planung (Android) –
TeamManagementScreenMannschaften | Planung;TeamPlanningScreen/TeamPlanningLogic;MembersApiPlay-Interest (TeamEditorModels) – Details Phase 8a - 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 8a – Mannschafts-Planung auf Android (umgesetzt, Stand 2026-05)
GET/POST/api/clubmembers/play-interest/:clubId–MembersApi+ DTOsMemberPlayInterestRowDto/MemberPlayInterestSetBody- UI:
TeamPlanningScreen.kt– Halbserie, Pool, Interesse markieren, Mannschaft hinzufügen, pro Team Stammdaten + Meldung, QTTR-Abstand, „Im Editor öffnen“ - Einstieg:
TeamManagementScreen– Segment Mannschaften | Planung - Logik:
TeamPlanningLogic.kt– Normalisierung Zuordnungen, Eligibility überTeamEditorLineupLogic, Default-Halbserie - Optional später: Drag-and-Drop statt Menüs; Debounced Autosave wie Web; dedizierte Tests Serialisierung
Hinweis im Code: Tab Aufstellung (TeamEditorScreen) verweist auf den Reiter Planung in derselben Team-Verwaltung.
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 (
PersonalSettings.vue) – Mehr → Hub: Sprache, MyTT, ClickTT;PersonalHubScreens.kt+AppRoot.ktSettingsScreen - MyTischtennis-Konto (
MyTischtennisAccount.vue) –MyTischtennisApi, Dialog/Verify/Unlink inPersonalHubScreens.kt - ClickTT-Konto (
ClickTtAccount.vue) –ClickTtAccountApi, analog inPersonalHubScreens.kt - ClickTT-Ansicht (
ClickTtView.vue) – Proxy-URL +WebViewinClickTtBrowserScreen
Phase 11 – Abrechnung & Bestellungen
- Orders (
OrdersView.vue/OrdersPanel.vueglobal) –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+asyncinCalendarScreen.kt; Quellen:DiaryManager.listDates, Trainingszeiten,TrainingCancellationApi,TournamentsApi,MatchesApi,OfficialTournamentsReadManager,CalendarHolidayApi(CalendarDtos.kt, APIs inshared) - 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, VerdrahtungAppRoot.kt) - i18n:
MobileStrings-Keys mit Fallback inCalendarScreen.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 13 – Backlog (abgeschlossen)
- i18n: Kalender-Strings (
mobile.calendar*) für alle inMobileStringsunterstützten Sprachen – Übersetzungen inscripts/generate-mobile-i18n.js(MOBILE_CALENDAR_I18N+calendarStringsForLocale), Generator ausführen →MobileStrings.kt - Kalender vs. Web: Offizielle Teilnahmen mobil über Tab Turnierteilnahmen (
MainTab.OfficialParticipations); tiefe Verwaltung wie Web unter/tournament-participations– bewusst getrennt, angleichen nur bei Bedarf - Release / R8: ProGuard-Regeln +
proguardFilesincomposeApp/build.gradle.kts(Phase 14);isMinifyEnabledbleibt bis gezieltem Release-Testfalse– siehe Phase 14 - Turniere (Produktiv-Crash):
LazyColumnmit eindeutigen Keys (itemsIndexedfür Vereins-Turniere, offizielle Liste, Teilnahmen-Zeilen), vermeidet Duplicate-Key-Abstürze; zudem tolerante Deserialisierung fürallowsExternal/isDoublesTournament(0/1, Strings) –TournamentsScreen.kt,FlexibleBooleanSerializers.kt,TournamentDtos.kt
Phase 14 – Qualität, Tests, Release
- Regression-Checkliste pro Phase (manuell) –
mobile-app/REGRESSION_CHECKLIST.md - Automatisierte Tests:
shared– Android-Unit-Tests (androidUnitTest), Startpunkt Serialisierung Turnier-DTOs (InternalTournamentSerializationTest.kt); ausführen:./gradlew :shared:testDebugUnitTest - Barrierefreiheit (Basis): Navigation Rail – TalkBack-taugliche
contentDescriptionfür Sektions-Icons (Ein-/Ausklappen) und zusammengefasste Beschriftung für Blatt-Einträge (NavRailLeafItem); Bottom-Tabs hatten bereits Label + Icon-Beschreibung - Performance: manuelle Stichproben und Erwartungen in
REGRESSION_CHECKLIST.md(Abschnitt Performance); Paging / Bildcache bei Bedarf spätere Iteration - Store / Compliance: Play Console Datenschutz, Berechtigungen (Kamera/Galerie, Internet) – Kurzhinweis in
REGRESSION_CHECKLIST.md(Abschnitt Store / Compliance); ausführliche Listing-Texte Verantwortung Release - Release / R8-Vorbereitung:
composeApp/proguard-rules.pro(Ktor,kotlinx.serialization, Koin, BuildConfig) +proguardFilesincomposeApp/build.gradle.kts;isMinifyEnabledbleibtfalsebis gezielter Release-Test
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. Kalender: /calendar → Phase 12.