# Frontend Logic Inventory (Vue, Non-View)

Stand: aus `frontend/src` analysiert.

## services/
| Element | Zweck | Abhängigkeiten (API Endpoint, Socket Events, Store) | Android-Entsprechung |
|---|---|---|---|
| `services/socketService.js` | Zentrale Socket.IO-Verbindung (connect/disconnect, join/leave Club-Raum, Event-Listener on/off). | Nutzt `backendBaseUrl` aus `apiClient`; Events u. a. `participant:*`, `diary:*`, `activity:*`, `member:changed`, `group:changed`, `tournament:changed`, `schedule:match:updated`, `schedule:match-report:submitted`; kein direkter Store-Zugriff. | `network` (WebSocket-Client) + teilweise `repository` (Event-Adapter). |

## apiClient.js
| Element | Zweck | Abhängigkeiten (API Endpoint, Socket Events, Store) | Android-Entsprechung |
|---|---|---|---|
| `apiClient.js` (`axios.create`) | Globale HTTP-Basis: Base URL, Timeout (60s), Redirect-Handling, zentrale Request/Response-Interceptors. | Base URL: `VITE_BACKEND` oder `http://localhost:3005` (DEV) oder `window.location.origin`; Request-Header aus Store (`authcode`, `userid`); bei `401` `store.dispatch('logout')`; Netzwerk-/Timeout-Fehler werden ohne Auto-Logout weitergereicht. | `network` (OkHttp/Retrofit-Konfiguration + Interceptor). |

## store.js
| Element | Zweck | Abhängigkeiten (API Endpoint, Socket Events, Store) | Android-Entsprechung |
|---|---|---|---|
| `state` | Session/User/Club/Permissions/UI-State (Sidebar, Sprache, Dialog-Stack). | Persistenz via `safeSessionStorage` + `safeLocalStorage`. | `viewmodel` (global app state) + teilweise `domain`. |
| `mutations` | Synchrone Zustandsänderungen inkl. Persistenz und Dialog-Stack-Management. | Keine direkten API-Calls; schreibt in Storage. | `viewmodel` (state reducer). |
| `actions.login` | Session setzen und Clubs laden. | API: `GET /clubs`; setzt Token/Username/Permissions. | `repository` + `viewmodel`. |
| `actions.logout` | Session reset + Navigation auf Login. | Router-Push `/login`; löscht Token/Permissions. | `viewmodel` (Logout-Usecase). |
| `actions.setCurrentClub` + `loadPermissions` | Clubwechsel + Permissions nachladen. | API: `GET /permissions/{clubId}`; Fallback auf read-only bei Fehlern. | `repository` + `viewmodel` + `domain` (permission model). |
| `getters` | Abgeleitete Berechtigungslogik (`hasPermission`, `isClubOwner`, `userRole`) und UI-Selektionen. | Greift auf State zu; keine API. | `domain` + `viewmodel`. |

## composables/
| Element | Zweck | Abhängigkeiten (API Endpoint, Socket Events, Store) | Android-Entsprechung |
|---|---|---|---|
| `composables/useDialog.js` (`useDialog`, `useConfirm`, `useInfo`) | Wiederverwendbare Dialog-Steuerung (open/close/toggle, promise-basiertes Confirm/Info). | Nutzt `utils/dialogUtils.js` (`buildInfoConfig`, `buildConfirmConfig`, `safeErrorMessage`); keine API. | `ui component` + `viewmodel` (UI-state helper). |
| `composables/usePermissions.js` | Wiederverwendbare Permission-Prüfungen (`canRead/Write/Delete`, `isAdmin`, `hasRole`). | Liest Vuex-Getter (`currentPermissions`, `isClubOwner`, `userRole`, `hasPermission`). | `domain` (permission rules) + `viewmodel`. |

## components/ (UI-Komponenten + Nutzung in Views)
Hinweis: Mapping „View-Nutzung“ basiert auf Imports in `src/views/*.vue`.

| Component | Verwendet in Views | Zweck | Abhängigkeiten (API/Socket/Store) | Android-Entsprechung |
|---|---|---|---|---|
| `AccidentFormDialog.vue` | `DiaryView.vue` | Unfallformular-Dialog. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `BaseDialog.vue` | `DiaryView.vue`, `MembersView.vue`, `OfficialTournaments.vue`, `ScheduleView.vue` | Basis-Dialog (Draggable/Modal-Grundstruktur). | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `ConfirmDialog.vue` | `Activate.vue`, `ClubView.vue`, `CreateClub.vue`, `DiaryView.vue`, `Login.vue`, `MemberTransferSettingsView.vue`, `MembersView.vue`, `MyTischtennisAccount.vue`, `OfficialTournaments.vue`, `PendingApprovalsView.vue`, `PermissionsView.vue`, `PredefinedActivities.vue`, `Register.vue`, `ScheduleView.vue`, `TeamManagementView.vue`, `TournamentTab.vue` | Wiederverwendbarer Bestätigungsdialog. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `CourtDrawingDialog.vue` | `DiaryView.vue`, `PredefinedActivities.vue` | Dialog für Hallen-/Übungszeichnung. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `CourtDrawingRender.vue` | `DiaryView.vue` | Rendering/Animation von Zeichnungsdaten. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `CourtDrawingTool.vue` | - | Interaktives Zeichentool (derzeit nicht direkt in Views importiert). | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `CsvImportDialog.vue` | `ScheduleView.vue` | CSV-Import-Dialog. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `DialogExamples.vue` | - | Demo/Beispiel für Dialogsystem. | `useDialog` composable. | `ui component` |
| `DialogManager.vue` | (global über `App.vue`) | Verwaltung mehrerer/minimierter Dialoge. | Vuex (`dialogs`, z-index Handling). | `ui component` + `viewmodel` |
| `ImageDialog.vue` | `DiaryView.vue` | Bildanzeige-/Bearbeitungsdialog. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `ImageViewerDialog.vue` | `MembersView.vue` | Bildviewer. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `InfoDialog.vue` | `Activate.vue`, `ClubView.vue`, `CreateClub.vue`, `DiaryView.vue`, `ForgotPassword.vue`, `Login.vue`, `LogsView.vue`, `MemberTransferSettingsView.vue`, `MembersView.vue`, `MyTischtennisAccount.vue`, `OfficialTournaments.vue`, `PendingApprovalsView.vue`, `PermissionsView.vue`, `PredefinedActivities.vue`, `Register.vue`, `ResetPassword.vue`, `ScheduleView.vue`, `TeamManagementView.vue`, `TournamentTab.vue` | Wiederverwendbarer Info-/Statusdialog. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `MatchAccountDialog.vue` | - | Match-Account Dialog (nicht direkt in Views importiert). | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `MatchReportApiDialog.vue` | `ScheduleView.vue` | API-gestützter Spielbericht/NuScore-Workflow. | API u. a. `/nuscore/broadcast-draft`, `/clubs/{clubId}`; Socket: `schedule:match-report:submitted`. | `ui component` + `repository` |
| `MatchReportDialog.vue` | - | Iframe-/PIN-basierter Matchreport-Dialog. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `MatchReportHeaderActions.vue` | - | Header-Actions für Matchreport. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `MemberActivitiesDialog.vue` | `MembersView.vue` | Aktivitäts-Statistik pro Mitglied. | API (`member-activities` Endpunkte). | `ui component` + `repository` |
| `MemberActivityStatsDialog.vue` | `DiaryView.vue` | Member-Aktivitätsstatistiken im Diary-Kontext. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `MemberGalleryDialog.vue` | `DiaryView.vue` | Mitglieder-Galerie inkl. Bildabruf. | API: `/clubmembers/gallery/{clubId}`, `/clubmembers/image/{clubId}/{memberId}`. | `ui component` + `repository` |
| `MemberNotesDialog.vue` | `DiaryView.vue`, `MembersView.vue` | Notizdialog für Mitglieder. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `MemberSelectionDialog.vue` | `OfficialTournaments.vue` | Auswahl-/Empfehlungsdialog für Mitglieder. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `MemberTransferDialog.vue` | `MembersView.vue` | Transfer-Konfiguration/-Ausführung für Mitglieder. | API: `/member-transfer-config/{clubId}`, Transfer-POST; Vuex (`currentClub`). | `ui component` + `repository` |
| `MyTischtennisDialog.vue` | `MyTischtennisAccount.vue` | Verifikation/Konto-Dialog myTischtennis. | API: `/mytischtennis/verify`, `/mytischtennis/account`. | `ui component` + `repository` |
| `MyTischtennisHistoryDialog.vue` | - | Historie-Dialog für myTischtennis Sync. | API: `/mytischtennis/update-history`. | `ui component` + `repository` |
| `NuscoreAnalyzer.vue` | - | Analyse-/Hilfskomponente für NuScore. | Keine direkte API/Store-Abhängigkeit. | `ui component` |
| `PDFGenerator.js` | `DiaryView.vue`, `MembersView.vue`, `OfficialTournaments.vue`, `ScheduleView.vue`, `TournamentTab.vue` | PDF-Erzeugung aus UI-Daten. | Keine API/Store-Abhängigkeit (reine Utility). | `domain` (Dokument-Generierung) |
| `QuickAddMemberDialog.vue` | `DiaryView.vue` | Schnellanlage/-zuordnung Mitglied. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `SeasonSelector.vue` | `ScheduleView.vue`, `TeamManagementView.vue` | Saisonauswahl + Saisonanlage. | API: `/seasons` (GET/POST); Vuex Store. | `ui component` + `repository` |
| `TagHistoryDialog.vue` | `DiaryView.vue` | Verlauf/History von Tags. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `TrainingDetailsDialog.vue` | `TrainingStatsView.vue` | Detaildialog für Trainingseinträge/Stats. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `TrainingGroupsTab.vue` | `ClubSettings.vue` | CRUD Trainingsgruppen. | API: `/training-groups/{clubId}` + Member-Zuordnung; Vuex Store. | `ui component` + `repository` |
| `TrainingTimesTab.vue` | `ClubSettings.vue` | CRUD Trainingszeiten. | API: `/training-times/{clubId}`; Vuex Store. | `ui component` + `repository` |
| `tournament/TournamentConfigTab.vue` | `TournamentTab.vue` | Konfiguration Turnierphasen/Stages. | API: `/tournament/stages`, `/tournament/stages/advance`. | `ui component` + `repository` |
| `tournament/TournamentGroupsTab.vue` | `TournamentTab.vue` | Gruppen-Tab im Turnierfluss. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `tournament/TournamentParticipantsTab.vue` | `TournamentTab.vue` | Teilnehmer-Tab im Turnierfluss. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `tournament/TournamentPlacementsTab.vue` | `TournamentTab.vue` | Platzierungen/Seeding-Tab. | API: `/clubmembers/get/{clubId}/true`, `/tournament/external-participants`. | `ui component` + `repository` |
| `tournament/TournamentResultsTab.vue` | `TournamentTab.vue` | Ergebnis-Tab im Turnierfluss. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `tournament/PlayerDetailsDialog.vue` | - | Detaildialog für Spieler (intern/extern). | API: `/tournament/external-participants`, `/clubmembers/get/{clubId}/true`. | `ui component` + `repository` |
| `tournament/TournamentClassList.vue` | - | Klassenlisten-UI für Turniere. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |
| `tournament/TournamentClassSelector.vue` | - | Klassenauswahl-UI für Turniere. | Keine direkte API-Import-Abhängigkeit gefunden. | `ui component` |

## Kurzfazit zur Schichtzuordnung
- Vue `apiClient` + `services/socketService` entsprechen primär Android `network`.
- Vue `store/actions` + API-lastige Components entsprechen Android `repository` + `viewmodel` (in Vue oft direkt im Component vermischt).
- Vue `composables` + Permission-Regeln entsprechen Android `domain/viewmodel`-Hilfsschicht.
- Vue `components` entsprechen Android `ui component`.
