fix: update application namespace and clean up deprecated files
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 45s

- Changed application namespace from `de.tt_tagebuch.app` to `de.tsschulz.tt_tagebuch` in build.gradle.kts and AndroidManifest.xml for consistency.
- Updated DEVELOPMENT.md to reflect the correct package name for the app.
- Removed deprecated files related to AppDependencies, MainActivity, MainApplication, and PDF generation, streamlining the codebase.
- Enhanced TODO.md to reflect the current status of the Android team planning phase implementation.
This commit is contained in:
Torsten Schulz (local)
2026-05-14 19:17:51 +02:00
parent e0196a6617
commit 56ebffce69
201 changed files with 1816 additions and 984 deletions

View File

@@ -63,7 +63,7 @@ Testest du mit der **LAN-IP deines PCs** (echtes Gerät), musst du diese IP dort
2. **Alte Installation / Build-Cache:** Emulator-App deinstallieren, Clean, neu installieren:
```bash
cd mobile-app
adb uninstall de.tt_tagebuch.app
adb uninstall de.tsschulz.tt_tagebuch
./gradlew :composeApp:clean :composeApp:installDebug --no-configuration-cache
```
Oder das Skript: `./scripts/install-debug-emulator.sh`

View File

@@ -165,49 +165,19 @@ Web: `DiaryView.vue` (sehr groß). API-Cluster (Auszug in Web nach `apiClien
- [x] **Ausstehende Freigaben** `ClubApprovalsApi`, `PendingApprovalsManager`, Screen unter „Mehr“ → Club-Verwaltung (`ClubAdminScreens.kt`)
- [x] **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**)
- [x] **Mannschafts-Planung (Android)** `TeamManagementScreen` **Mannschaften | Planung**; `TeamPlanningScreen` / `TeamPlanningLogic`; `MembersApi` Play-Interest (`TeamEditorModels`) Details **Phase 8a**
- [x] **Berechtigungen** erweiterte `PermissionsApi`, `PermissionsAdminManager`, UI Rolle/Status/Anpassen mit `RolePermissionMatrix` (`ClubAdminScreens.kt`)
- [x] **Logs** `ApiLogsApi`, `ApiLogsManager`, Liste + Pagination + Detail (`ClubAdminScreens.kt`); `AppDependencies` / Logout / 401 räumen Manager auf
### Phase 8a Mannschafts-Planung auf Android (Backlog / Plan)
### Phase 8a Mannschafts-Planung auf Android (umgesetzt, Stand 2026-05)
**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.
- [x] `GET/POST` **`/api/clubmembers/play-interest/:clubId`** `MembersApi` + DTOs `MemberPlayInterestRowDto` / `MemberPlayInterestSetBody`
- [x] **UI:** `TeamPlanningScreen.kt` Halbserie, Pool, Interesse markieren, Mannschaft hinzufügen, pro Team Stammdaten + Meldung, QTTR-Abstand, „Im Editor öffnen“
- [x] **Einstieg:** `TeamManagementScreen` Segment **Mannschaften | Planung**
- [x] **Logik:** `TeamPlanningLogic.kt` Normalisierung Zuordnungen, Eligibility über `TeamEditorLineupLogic`, Default-Halbserie
- [ ] **Optional später:** Drag-and-Drop statt Menüs; Debounced Autosave wie Web; dedizierte Tests Serialisierung
**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`)
- [x] `GET /api/clubmembers/get/:clubId/:showAll` bereits `MembersApi.listMembers`
- [x] `GET /api/club-teams/...` Mannschaften Saison, `GET …/lineup?half=`, `PUT …/lineup` `ClubTeamsApi` (Planung lädt Lineups **aller** Teams der Saison parallel wie Web `loadPlanningAssignments`)
- [x] `PUT /api/club-teams/:id` Stammdaten Planungsteam (`updateClubTeam`)
- [x] `POST /api/club-teams/club/:clubId` neue Planungs-Mannschaft (`createClubTeam` o. ä.)
- [x] `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).
**Hinweis im Code:** Tab Aufstellung (`TeamEditorScreen`) verweist auf den Reiter **Planung** in derselben Team-Verwaltung.
---

View File

@@ -51,11 +51,11 @@ kotlin {
}
android {
namespace = "de.tt_tagebuch.app"
namespace = "de.tsschulz.tt_tagebuch"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
applicationId = "de.tt_tagebuch.app"
applicationId = "de.tsschulz.tt_tagebuch"
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
versionCode = 1

Binary file not shown.

View File

@@ -4,16 +4,16 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:name=".app.MainApplication"
android:allowBackup="true"
android:icon="@android:mipmap/sym_def_app_icon"
android:icon="@mipmap/ic_launcher"
android:label="Trainingstagebuch"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@android:mipmap/sym_def_app_icon"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<activity
android:name=".MainActivity"
android:name=".app.MainActivity"
android:exported="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar"
android:windowSoftInputMode="adjustResize">

View File

@@ -1,59 +1,60 @@
package de.tt_tagebuch.app
package de.tsschulz.tt_tagebuch.app
import android.content.Context
import de.tt_tagebuch.shared.api.BillingApi
import de.tt_tagebuch.shared.api.CalendarHolidayApi
import de.tt_tagebuch.shared.api.AccidentApi
import de.tt_tagebuch.shared.api.ApiLogsApi
import de.tt_tagebuch.shared.api.ClubApprovalsApi
import de.tt_tagebuch.shared.api.ClickTtAccountApi
import de.tt_tagebuch.shared.api.ApiConfig
import de.tt_tagebuch.shared.api.AuthApi
import de.tt_tagebuch.shared.api.PublicAuthApi
import de.tt_tagebuch.shared.api.ClubTeamsApi
import de.tt_tagebuch.shared.api.ClubsApi
import de.tt_tagebuch.shared.api.DiaryApi
import de.tt_tagebuch.shared.api.DiaryMemberActivitiesApi
import de.tt_tagebuch.shared.api.DiaryMemberApi
import de.tt_tagebuch.shared.api.GroupApi
import de.tt_tagebuch.shared.api.ParticipantsApi
import de.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tt_tagebuch.shared.api.MatchesApi
import de.tt_tagebuch.shared.api.MemberActivitiesApi
import de.tt_tagebuch.shared.api.MemberGroupPhotosApi
import de.tt_tagebuch.shared.api.MemberTransferConfigApi
import de.tt_tagebuch.shared.api.MemberOrdersApi
import de.tt_tagebuch.shared.api.TrainingCancellationApi
import de.tt_tagebuch.shared.api.MembersApi
import de.tt_tagebuch.shared.api.MyTischtennisApi
import de.tt_tagebuch.shared.api.OfficialTournamentsApi
import de.tt_tagebuch.shared.api.PermissionsApi
import de.tt_tagebuch.shared.api.SeasonsApi
import de.tt_tagebuch.shared.api.SessionApi
import de.tt_tagebuch.shared.api.TeamDocumentsApi
import de.tt_tagebuch.shared.api.TrainingGroupsApi
import de.tt_tagebuch.shared.api.TrainingStatsApi
import de.tt_tagebuch.shared.api.TrainingTimesApi
import de.tt_tagebuch.shared.api.TournamentsApi
import de.tt_tagebuch.shared.api.http.AndroidHttpClientEngineFactory
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.http.PublicHttpClient
import de.tt_tagebuch.shared.state.AndroidClubStorage
import de.tt_tagebuch.shared.state.AndroidLanguageStorage
import de.tt_tagebuch.shared.state.AndroidTokenStorage
import de.tt_tagebuch.shared.state.ApiLogsManager
import de.tt_tagebuch.shared.state.AuthManager
import de.tt_tagebuch.shared.state.ClubInternalTournamentsManager
import de.tt_tagebuch.shared.state.ClubManager
import de.tt_tagebuch.shared.state.DiaryManager
import de.tt_tagebuch.shared.state.LanguageManager
import de.tt_tagebuch.shared.state.MembersManager
import de.tt_tagebuch.shared.state.MutableTokenProvider
import de.tt_tagebuch.shared.state.OfficialTournamentsReadManager
import de.tt_tagebuch.shared.state.PendingApprovalsManager
import de.tt_tagebuch.shared.state.PermissionsAdminManager
import de.tt_tagebuch.shared.state.ScheduleManager
import de.tt_tagebuch.shared.state.TrainingStatsManager
import de.tsschulz.tt_tagebuch.BuildConfig
import de.tsschulz.tt_tagebuch.shared.api.BillingApi
import de.tsschulz.tt_tagebuch.shared.api.CalendarHolidayApi
import de.tsschulz.tt_tagebuch.shared.api.AccidentApi
import de.tsschulz.tt_tagebuch.shared.api.ApiLogsApi
import de.tsschulz.tt_tagebuch.shared.api.ClubApprovalsApi
import de.tsschulz.tt_tagebuch.shared.api.ClickTtAccountApi
import de.tsschulz.tt_tagebuch.shared.api.ApiConfig
import de.tsschulz.tt_tagebuch.shared.api.AuthApi
import de.tsschulz.tt_tagebuch.shared.api.PublicAuthApi
import de.tsschulz.tt_tagebuch.shared.api.ClubTeamsApi
import de.tsschulz.tt_tagebuch.shared.api.ClubsApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryMemberActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryMemberApi
import de.tsschulz.tt_tagebuch.shared.api.GroupApi
import de.tsschulz.tt_tagebuch.shared.api.ParticipantsApi
import de.tsschulz.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.MatchesApi
import de.tsschulz.tt_tagebuch.shared.api.MemberActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.MemberGroupPhotosApi
import de.tsschulz.tt_tagebuch.shared.api.MemberTransferConfigApi
import de.tsschulz.tt_tagebuch.shared.api.MemberOrdersApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingCancellationApi
import de.tsschulz.tt_tagebuch.shared.api.MembersApi
import de.tsschulz.tt_tagebuch.shared.api.MyTischtennisApi
import de.tsschulz.tt_tagebuch.shared.api.OfficialTournamentsApi
import de.tsschulz.tt_tagebuch.shared.api.PermissionsApi
import de.tsschulz.tt_tagebuch.shared.api.SeasonsApi
import de.tsschulz.tt_tagebuch.shared.api.SessionApi
import de.tsschulz.tt_tagebuch.shared.api.TeamDocumentsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingGroupsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingStatsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingTimesApi
import de.tsschulz.tt_tagebuch.shared.api.TournamentsApi
import de.tsschulz.tt_tagebuch.shared.api.http.AndroidHttpClientEngineFactory
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.http.PublicHttpClient
import de.tsschulz.tt_tagebuch.shared.state.AndroidClubStorage
import de.tsschulz.tt_tagebuch.shared.state.AndroidLanguageStorage
import de.tsschulz.tt_tagebuch.shared.state.AndroidTokenStorage
import de.tsschulz.tt_tagebuch.shared.state.ApiLogsManager
import de.tsschulz.tt_tagebuch.shared.state.AuthManager
import de.tsschulz.tt_tagebuch.shared.state.ClubInternalTournamentsManager
import de.tsschulz.tt_tagebuch.shared.state.ClubManager
import de.tsschulz.tt_tagebuch.shared.state.DiaryManager
import de.tsschulz.tt_tagebuch.shared.state.LanguageManager
import de.tsschulz.tt_tagebuch.shared.state.MembersManager
import de.tsschulz.tt_tagebuch.shared.state.MutableTokenProvider
import de.tsschulz.tt_tagebuch.shared.state.OfficialTournamentsReadManager
import de.tsschulz.tt_tagebuch.shared.state.PendingApprovalsManager
import de.tsschulz.tt_tagebuch.shared.state.PermissionsAdminManager
import de.tsschulz.tt_tagebuch.shared.state.ScheduleManager
import de.tsschulz.tt_tagebuch.shared.state.TrainingStatsManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app
package de.tsschulz.tt_tagebuch.app
import android.os.Bundle
import androidx.activity.ComponentActivity
@@ -9,8 +9,8 @@ import androidx.compose.material.Surface
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import de.tt_tagebuch.app.ui.AppRoot
import de.tt_tagebuch.app.ui.TtTagebuchTheme
import de.tsschulz.tt_tagebuch.app.ui.AppRoot
import de.tsschulz.tt_tagebuch.app.ui.TtTagebuchTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app
package de.tsschulz.tt_tagebuch.app
import android.app.Application

View File

@@ -1,14 +1,14 @@
package de.tt_tagebuch.app.calendar
package de.tsschulz.tt_tagebuch.app.calendar
import de.tt_tagebuch.shared.api.models.CalendarHolidayRowDto
import de.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import de.tt_tagebuch.shared.api.models.DiaryDate
import de.tt_tagebuch.shared.api.models.InternalTournamentSummaryDto
import de.tt_tagebuch.shared.api.models.OfficialParticipationBucketDto
import de.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tt_tagebuch.shared.api.models.TrainingCancellationDto
import de.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tsschulz.tt_tagebuch.shared.api.models.CalendarHolidayRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDate
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentSummaryDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParticipationBucketDto
import de.tsschulz.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingCancellationDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingTimeDto
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.LocalTime

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.pdf
package de.tsschulz.tt_tagebuch.app.pdf
import android.graphics.Canvas
import android.graphics.Color
@@ -8,12 +8,12 @@ import android.graphics.pdf.PdfDocument
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import de.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tt_tagebuch.shared.api.models.DiaryTrainingParticipant
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.displayTitle
import de.tt_tagebuch.shared.api.models.isPresentParticipant
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryTrainingParticipant
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.displayTitle
import de.tsschulz.tt_tagebuch.shared.api.models.isPresentParticipant
import java.io.File
import java.io.FileOutputStream
import java.util.Locale

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app.pdf
package de.tsschulz.tt_tagebuch.app.pdf
import android.content.Context
import android.content.Intent
import androidx.core.content.FileProvider
import de.tt_tagebuch.app.BuildConfig
import de.tsschulz.tt_tagebuch.BuildConfig
import java.io.File
fun shareFileWithMime(context: Context, file: File, mimeType: String, chooserTitle: String) {

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.pdf
package de.tsschulz.tt_tagebuch.app.pdf
import android.graphics.Canvas
import android.graphics.Color
@@ -8,8 +8,8 @@ import android.graphics.pdf.PdfDocument
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.MemberContactDto
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.MemberContactDto
import java.io.File
import java.io.FileOutputStream
import java.time.LocalDate

View File

@@ -1,10 +1,10 @@
package de.tt_tagebuch.app.stats
package de.tsschulz.tt_tagebuch.app.stats
import de.tt_tagebuch.shared.api.models.TrainingStatsDay
import de.tt_tagebuch.shared.api.models.TrainingStatsMember
import de.tt_tagebuch.shared.api.models.TrainingStatsMemberDistribution
import de.tt_tagebuch.shared.api.models.TrainingStatsMonthlyTrend
import de.tt_tagebuch.shared.api.models.TrainingStatsWeekdayBucket
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsDay
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsMember
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsMemberDistribution
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsMonthlyTrend
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsWeekdayBucket
import java.time.DayOfWeek
import java.time.LocalDate
import java.util.Locale

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.content.Intent
import android.net.Uri
@@ -89,61 +89,61 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlin.math.max
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.pdf.sharePdfFile
import de.tt_tagebuch.app.pdf.writeMembersPhoneListPdf
import de.tt_tagebuch.app.pdf.writeTrainingDaySummaryPdf
import de.tt_tagebuch.app.pdf.writeTrainingPlanPdf
import de.tt_tagebuch.shared.api.memberProfileImagePath
import de.tt_tagebuch.shared.api.toAbsoluteUrl
import de.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tt_tagebuch.shared.api.models.canReadApprovals
import de.tt_tagebuch.shared.api.models.canReadClubPermissions
import de.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tt_tagebuch.shared.api.models.canReadPredefinedActivities
import de.tt_tagebuch.shared.api.models.canReadDiary
import de.tt_tagebuch.shared.api.models.canReadTeams
import de.tt_tagebuch.shared.api.models.canReadMembers
import de.tt_tagebuch.shared.api.models.canReadSchedule
import de.tt_tagebuch.shared.api.models.canReadStatistics
import de.tt_tagebuch.shared.api.models.canReadTournaments
import de.tt_tagebuch.shared.api.models.canWriteDiary
import de.tt_tagebuch.shared.api.models.canWriteMembers
import de.tt_tagebuch.shared.api.models.canWriteMyTischtennis
import de.tt_tagebuch.shared.api.models.mainActivityImagePath
import de.tt_tagebuch.shared.api.models.nestedActivityImagePath
import de.tt_tagebuch.shared.api.models.AccidentReportDto
import de.tt_tagebuch.shared.api.models.Club
import de.tt_tagebuch.shared.api.models.DiaryDate
import de.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tt_tagebuch.shared.api.models.AddDiaryPlanGroupActivityRequest
import de.tt_tagebuch.shared.api.models.CreateDiaryPlanActivityRequest
import de.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tt_tagebuch.shared.api.models.DiaryPlanGroup
import de.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityRequest
import de.tt_tagebuch.shared.api.models.DiaryMemberNoteDto
import de.tt_tagebuch.shared.api.models.DiaryMemberTagLinkDto
import de.tt_tagebuch.shared.api.models.DiaryTag
import de.tt_tagebuch.shared.api.models.PredefinedActivityDto
import de.tt_tagebuch.shared.api.models.displayLabel as predefinedDtoDisplayLabel
import de.tt_tagebuch.shared.api.models.tagDefinitionId
import de.tt_tagebuch.shared.api.models.tagDisplayName
import de.tt_tagebuch.shared.api.models.DiaryTrainingParticipant
import de.tt_tagebuch.shared.api.models.isPresentParticipant
import de.tt_tagebuch.shared.api.models.displayLabel
import de.tt_tagebuch.shared.api.models.displayTitle
import de.tt_tagebuch.shared.api.models.memberLabel
import de.tt_tagebuch.shared.api.models.MemberActivityStatDto
import de.tt_tagebuch.shared.api.models.MemberContactDto
import de.tt_tagebuch.shared.api.models.MemberContactSetBody
import de.tt_tagebuch.shared.api.models.MemberDataQualityRequirements
import de.tt_tagebuch.shared.api.models.MemberLastParticipationDto
import de.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tt_tagebuch.shared.api.models.toSetBody
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.UserClubPermissions
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.pdf.sharePdfFile
import de.tsschulz.tt_tagebuch.app.pdf.writeMembersPhoneListPdf
import de.tsschulz.tt_tagebuch.app.pdf.writeTrainingDaySummaryPdf
import de.tsschulz.tt_tagebuch.app.pdf.writeTrainingPlanPdf
import de.tsschulz.tt_tagebuch.shared.api.memberProfileImagePath
import de.tsschulz.tt_tagebuch.shared.api.toAbsoluteUrl
import de.tsschulz.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tsschulz.tt_tagebuch.shared.api.models.canReadApprovals
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubPermissions
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tsschulz.tt_tagebuch.shared.api.models.canReadPredefinedActivities
import de.tsschulz.tt_tagebuch.shared.api.models.canReadDiary
import de.tsschulz.tt_tagebuch.shared.api.models.canReadTeams
import de.tsschulz.tt_tagebuch.shared.api.models.canReadMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canReadSchedule
import de.tsschulz.tt_tagebuch.shared.api.models.canReadStatistics
import de.tsschulz.tt_tagebuch.shared.api.models.canReadTournaments
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteDiary
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteMyTischtennis
import de.tsschulz.tt_tagebuch.shared.api.models.mainActivityImagePath
import de.tsschulz.tt_tagebuch.shared.api.models.nestedActivityImagePath
import de.tsschulz.tt_tagebuch.shared.api.models.AccidentReportDto
import de.tsschulz.tt_tagebuch.shared.api.models.Club
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDate
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryPlanGroupActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.CreateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryPlanGroup
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberNoteDto
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberTagLinkDto
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryTag
import de.tsschulz.tt_tagebuch.shared.api.models.PredefinedActivityDto
import de.tsschulz.tt_tagebuch.shared.api.models.displayLabel as predefinedDtoDisplayLabel
import de.tsschulz.tt_tagebuch.shared.api.models.tagDefinitionId
import de.tsschulz.tt_tagebuch.shared.api.models.tagDisplayName
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryTrainingParticipant
import de.tsschulz.tt_tagebuch.shared.api.models.isPresentParticipant
import de.tsschulz.tt_tagebuch.shared.api.models.displayLabel
import de.tsschulz.tt_tagebuch.shared.api.models.displayTitle
import de.tsschulz.tt_tagebuch.shared.api.models.memberLabel
import de.tsschulz.tt_tagebuch.shared.api.models.MemberActivityStatDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberContactDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberContactSetBody
import de.tsschulz.tt_tagebuch.shared.api.models.MemberDataQualityRequirements
import de.tsschulz.tt_tagebuch.shared.api.models.MemberLastParticipationDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tsschulz.tt_tagebuch.shared.api.models.toSetBody
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.UserClubPermissions
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.content.Context
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -46,16 +46,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.pdf.sharePdfFile
import de.tt_tagebuch.shared.api.models.BillingCreateRunBody
import de.tt_tagebuch.shared.api.models.BillingRunDto
import de.tt_tagebuch.shared.api.models.BillingTemplateDto
import de.tt_tagebuch.shared.api.models.MemberOrderDto
import de.tt_tagebuch.shared.api.models.MemberOrderPatchBody
import de.tt_tagebuch.shared.api.models.canReadMembers
import de.tt_tagebuch.shared.api.models.canWriteMembers
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.pdf.sharePdfFile
import de.tsschulz.tt_tagebuch.shared.api.models.BillingCreateRunBody
import de.tsschulz.tt_tagebuch.shared.api.models.BillingRunDto
import de.tsschulz.tt_tagebuch.shared.api.models.BillingTemplateDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrderDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrderPatchBody
import de.tsschulz.tt_tagebuch.shared.api.models.canReadMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteMembers
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -37,16 +37,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.calendar.CalendarAggregator
import de.tt_tagebuch.app.calendar.CalendarEventAction
import de.tt_tagebuch.app.calendar.CalendarEventType
import de.tt_tagebuch.app.calendar.CalendarUiEvent
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.calendar.CalendarAggregator
import de.tsschulz.tt_tagebuch.app.calendar.CalendarEventAction
import de.tsschulz.tt_tagebuch.app.calendar.CalendarEventType
import de.tsschulz.tt_tagebuch.app.calendar.CalendarUiEvent
import android.util.Log
import de.tt_tagebuch.shared.api.http.ApiException
import de.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import de.tt_tagebuch.shared.api.models.TrainingCancellationUpsertBody
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.shared.api.http.ApiException
import de.tsschulz.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingCancellationUpsertBody
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Arrangement
@@ -45,16 +45,16 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.RolePermissionMatrix
import de.tt_tagebuch.shared.api.models.ApiLogDetailDto
import de.tt_tagebuch.shared.api.models.ClubPermissionMemberDto
import de.tt_tagebuch.shared.api.models.PermissionResourceDto
import de.tt_tagebuch.shared.api.models.canReadApprovals
import de.tt_tagebuch.shared.api.models.canReadClubPermissions
import de.tt_tagebuch.shared.api.models.canWriteApprovals
import de.tt_tagebuch.shared.api.models.canWriteClubPermissions
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.RolePermissionMatrix
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogDetailDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubPermissionMemberDto
import de.tsschulz.tt_tagebuch.shared.api.models.PermissionResourceDto
import de.tsschulz.tt_tagebuch.shared.api.models.canReadApprovals
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubPermissions
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteApprovals
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteClubPermissions
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -45,20 +45,20 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.Club
import de.tt_tagebuch.shared.api.models.CreateTrainingTimeBody
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.MemberDataQualityRequirements
import de.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tt_tagebuch.shared.api.models.TrainingGroupMemberBrief
import de.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tt_tagebuch.shared.api.models.UpdateTrainingTimeBody
import de.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tt_tagebuch.shared.api.models.canReadMembers
import de.tt_tagebuch.shared.api.models.canWriteClubSettings
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.Club
import de.tsschulz.tt_tagebuch.shared.api.models.CreateTrainingTimeBody
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.MemberDataQualityRequirements
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupMemberBrief
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTrainingTimeBody
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tsschulz.tt_tagebuch.shared.api.models.canReadMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteClubSettings
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
private val ClubSettingsPad = 20.dp

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Arrangement
@@ -44,23 +44,23 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tt_tagebuch.shared.api.models.MemberTransferConfigSaveBody
import de.tt_tagebuch.shared.api.models.PredefinedActivityDto
import de.tt_tagebuch.shared.api.models.PredefinedActivityUpsertBody
import de.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tt_tagebuch.shared.api.models.UpdateTrainingTimeBody
import de.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tt_tagebuch.shared.api.models.canReadMembers
import de.tt_tagebuch.shared.api.models.canReadPredefinedActivities
import de.tt_tagebuch.shared.api.models.canWriteMembers
import de.tt_tagebuch.shared.api.models.canWritePredefinedActivities
import de.tt_tagebuch.shared.api.models.displayLabel
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigSaveBody
import de.tsschulz.tt_tagebuch.shared.api.models.PredefinedActivityDto
import de.tsschulz.tt_tagebuch.shared.api.models.PredefinedActivityUpsertBody
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTrainingTimeBody
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tsschulz.tt_tagebuch.shared.api.models.canReadMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canReadPredefinedActivities
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canWritePredefinedActivities
import de.tsschulz.tt_tagebuch.shared.api.models.displayLabel
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -31,23 +31,23 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.TournamentsApi
import de.tt_tagebuch.shared.api.models.AddTournamentClassBody
import de.tt_tagebuch.shared.api.models.CreateTournamentPairingBody
import de.tt_tagebuch.shared.api.models.TournamentAddInternalParticipantBody
import de.tt_tagebuch.shared.api.models.TournamentAddMatchResultBody
import de.tt_tagebuch.shared.api.models.TournamentClassDto
import de.tt_tagebuch.shared.api.models.TournamentDeleteKnockoutBody
import de.tt_tagebuch.shared.api.models.TournamentExternalParticipantRowDto
import de.tt_tagebuch.shared.api.models.TournamentFinishMatchBody
import de.tt_tagebuch.shared.api.models.TournamentMatchDto
import de.tt_tagebuch.shared.api.models.TournamentParticipantRowDto
import de.tt_tagebuch.shared.api.models.TournamentRemoveInternalParticipantBody
import de.tt_tagebuch.shared.api.models.UpdateParticipantClassBody
import de.tt_tagebuch.shared.api.models.UpdateTournamentClassBody
import de.tt_tagebuch.shared.api.models.AddExternalTournamentParticipantBody
import de.tt_tagebuch.shared.api.models.RemoveExternalTournamentParticipantBody
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.TournamentsApi
import de.tsschulz.tt_tagebuch.shared.api.models.AddTournamentClassBody
import de.tsschulz.tt_tagebuch.shared.api.models.CreateTournamentPairingBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentAddInternalParticipantBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentAddMatchResultBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentClassDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentDeleteKnockoutBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentExternalParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentFinishMatchBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentRemoveInternalParticipantBody
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateParticipantClassBody
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTournamentClassBody
import de.tsschulz.tt_tagebuch.shared.api.models.AddExternalTournamentParticipantBody
import de.tsschulz.tt_tagebuch.shared.api.models.RemoveExternalTournamentParticipantBody
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -38,20 +38,20 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.InternalTournamentDetailDto
import de.tt_tagebuch.shared.api.models.SetTournamentModusBody
import de.tt_tagebuch.shared.api.models.TournamentClassDto
import de.tt_tagebuch.shared.api.models.TournamentClubTournamentBody
import de.tt_tagebuch.shared.api.models.TournamentCreateGroupMatchesBody
import de.tt_tagebuch.shared.api.models.TournamentCreateGroupsBody
import de.tt_tagebuch.shared.api.models.TournamentExternalParticipantRowDto
import de.tt_tagebuch.shared.api.models.TournamentGetExternalParticipantsBody
import de.tt_tagebuch.shared.api.models.TournamentGetParticipantsBody
import de.tt_tagebuch.shared.api.models.TournamentMatchDto
import de.tt_tagebuch.shared.api.models.TournamentParticipantRowDto
import de.tt_tagebuch.shared.api.models.UpdateTournamentMetaBody
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentDetailDto
import de.tsschulz.tt_tagebuch.shared.api.models.SetTournamentModusBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentClassDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentClubTournamentBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentCreateGroupMatchesBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentCreateGroupsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentExternalParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentGetExternalParticipantsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentGetParticipantsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTournamentMetaBody
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -59,7 +59,7 @@ import kotlinx.serialization.json.JsonElement
/**
* Vollständiger Turnier-Workspace (analog Web [TournamentTab]): Stammdaten, Ablauf/Gruppen,
* Klassen, Teilnehmer, Spiele, Doppel-Paarungen. Lädt und speichert über [de.tt_tagebuch.shared.api.TournamentsApi].
* Klassen, Teilnehmer, Spiele, Doppel-Paarungen. Lädt und speichert über [de.tsschulz.tt_tagebuch.shared.api.TournamentsApi].
*/
@Composable
internal fun InternalTournamentEditorScreen(
@@ -347,7 +347,7 @@ private fun TournamentEditorFlowTab(
detail: InternalTournamentDetailDto,
groupsJson: JsonElement?,
tr: (String, String) -> String,
api: de.tt_tagebuch.shared.api.TournamentsApi,
api: de.tsschulz.tt_tagebuch.shared.api.TournamentsApi,
scope: kotlinx.coroutines.CoroutineScope,
onReload: () -> Unit,
onError: (String?) -> Unit,
@@ -500,7 +500,7 @@ private fun TournamentEditorFlowTab(
runCatching {
kotlinx.coroutines.withContext(Dispatchers.IO) {
api.startKnockout(
de.tt_tagebuch.shared.api.models.TournamentStartKnockoutBody(clubId, tournamentId),
de.tsschulz.tt_tagebuch.shared.api.models.TournamentStartKnockoutBody(clubId, tournamentId),
)
}
}.onFailure { onError(it.message) }

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -28,10 +28,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.InternalTournamentStatsAgeOption
import de.tt_tagebuch.shared.api.models.InternalTournamentStatsDto
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentStatsAgeOption
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentStatsDto
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
private fun allBandKeysFromOptions(options: List<InternalTournamentStatsAgeOption>): Set<String> {
val seen = mutableSetOf<String>()

View File

@@ -1,6 +1,6 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.runtime.compositionLocalOf
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
internal val LocalLanguageCode = compositionLocalOf { MobileStrings.DEFAULT_LANGUAGE }

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.graphics.Bitmap
import android.graphics.BitmapFactory
@@ -60,9 +60,9 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.app.Activity
import android.content.Context

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -37,12 +37,12 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tt_tagebuch.shared.api.models.MemberTransferRunBody
import de.tt_tagebuch.shared.api.toAbsoluteUrl
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferRunBody
import de.tsschulz.tt_tagebuch.shared.api.toAbsoluteUrl
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.booleanOrNull

View File

@@ -1,6 +1,6 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import de.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import java.time.LocalDate
import java.time.Period
import java.time.ZoneId

View File

@@ -1,14 +1,14 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import de.tt_tagebuch.app.util.OfficialTournamentEligibility
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.OfficialCompetitionMemberStateDto
import de.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tt_tagebuch.shared.api.models.OfficialParsedDataDto
import de.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import de.tt_tagebuch.shared.api.models.OfficialParticipationBucketDto
import de.tt_tagebuch.shared.api.models.OfficialParticipationEntryDto
import de.tt_tagebuch.shared.api.models.OfficialTournamentListRowDto
import de.tsschulz.tt_tagebuch.app.util.OfficialTournamentEligibility
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialCompetitionMemberStateDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedDataDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParticipationBucketDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParticipationEntryDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialTournamentListRowDto
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonNull

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -55,18 +55,18 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.util.OfficialTournamentEligibility
import de.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import de.tt_tagebuch.shared.api.models.OfficialPatchTournamentBody
import de.tt_tagebuch.shared.api.models.OfficialParticipantStatusBody
import de.tt_tagebuch.shared.api.models.OfficialTournamentListRowDto
import de.tt_tagebuch.shared.api.models.OfficialUpsertParticipationBody
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.canReadTournaments
import de.tt_tagebuch.shared.api.models.canWriteTournaments
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.util.OfficialTournamentEligibility
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialPatchTournamentBody
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParticipantStatusBody
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialTournamentListRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialUpsertParticipationBody
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.canReadTournaments
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteTournaments
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.annotation.SuppressLint
import android.view.ViewGroup
@@ -49,15 +49,15 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.http.ApiException
import de.tt_tagebuch.shared.api.models.ClickTtAccountDto
import de.tt_tagebuch.shared.api.models.ClickTtAccountStatusDto
import de.tt_tagebuch.shared.api.models.ClickTtAccountUpsertBody
import de.tt_tagebuch.shared.api.models.MyTischtennisAccountDto
import de.tt_tagebuch.shared.api.models.MyTischtennisAccountUpsertBody
import de.tt_tagebuch.shared.api.models.MyTischtennisStatusDto
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.http.ApiException
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountStatusDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountUpsertBody
import de.tsschulz.tt_tagebuch.shared.api.models.MyTischtennisAccountDto
import de.tsschulz.tt_tagebuch.shared.api.models.MyTischtennisAccountUpsertBody
import de.tsschulz.tt_tagebuch.shared.api.models.MyTischtennisStatusDto
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
@@ -349,7 +349,7 @@ private fun MyTischtennisEditorDialog(
onSaved: () -> Unit,
onLoggedIn: () -> Unit,
scope: kotlinx.coroutines.CoroutineScope,
api: de.tt_tagebuch.shared.api.MyTischtennisApi,
api: de.tsschulz.tt_tagebuch.shared.api.MyTischtennisApi,
) {
var email by remember(account?.id, loginMode) { mutableStateOf(account?.email.orEmpty()) }
var password by remember(account?.id, loginMode) { mutableStateOf("") }
@@ -614,7 +614,7 @@ private fun ClickTtEditorDialog(
onSaved: () -> Unit,
onLoggedIn: () -> Unit,
scope: kotlinx.coroutines.CoroutineScope,
api: de.tt_tagebuch.shared.api.ClickTtAccountApi,
api: de.tsschulz.tt_tagebuch.shared.api.ClickTtAccountApi,
) {
var username by remember(account?.id, loginMode) { mutableStateOf(account?.username.orEmpty()) }
var password by remember(account?.id, loginMode) { mutableStateOf("") }

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.content.Intent
import android.net.Uri
@@ -46,14 +46,14 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.stats.TrainingStatsDerived
import de.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tt_tagebuch.shared.api.models.ScheduleMatchScope
import de.tt_tagebuch.shared.api.models.ScheduleViewMode
import de.tt_tagebuch.shared.api.models.canReadSchedule
import de.tt_tagebuch.shared.api.models.canWriteSchedule
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.stats.TrainingStatsDerived
import de.tsschulz.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.ScheduleMatchScope
import de.tsschulz.tt_tagebuch.shared.api.models.ScheduleViewMode
import de.tsschulz.tt_tagebuch.shared.api.models.canReadSchedule
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteSchedule
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
private val SchedulePad = 20.dp

View File

@@ -1,6 +1,6 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import de.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import java.util.Calendar
import java.util.GregorianCalendar

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import android.content.Context
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -49,19 +49,19 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.pdf.shareFileWithMime
import de.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tt_tagebuch.shared.api.models.ClubTeamCreateBody
import de.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tt_tagebuch.shared.api.models.ClubTeamLineupRowDto
import de.tt_tagebuch.shared.api.models.ClubTeamUpdateBody
import de.tt_tagebuch.shared.api.models.LeaguePlayerStatDto
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.TeamLineupAssignmentItem
import de.tt_tagebuch.shared.api.models.TeamLineupUpdateBody
import de.tt_tagebuch.shared.api.models.canWriteTeams
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.pdf.shareFileWithMime
import de.tsschulz.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamCreateBody
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamLineupRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamUpdateBody
import de.tsschulz.tt_tagebuch.shared.api.models.LeaguePlayerStatDto
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.TeamLineupAssignmentItem
import de.tsschulz.tt_tagebuch.shared.api.models.TeamLineupUpdateBody
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteTeams
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@@ -196,13 +196,13 @@ internal fun TeamEditorScreen(
var loadingLineup by remember { mutableStateOf(false) }
var savingLineup by remember { mutableStateOf(false) }
var documents by remember { mutableStateOf<List<de.tt_tagebuch.shared.api.models.TeamDocumentDto>>(emptyList()) }
var documents by remember { mutableStateOf<List<de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto>>(emptyList()) }
var loadingDocs by remember { mutableStateOf(false) }
var parsingDocId by remember { mutableStateOf<Int?>(null) }
var schedulerLoaded by remember { mutableStateOf(false) }
var schedulerBlock by remember {
mutableStateOf<de.tt_tagebuch.shared.api.models.SchedulerJobBlockDto?>(
mutableStateOf<de.tsschulz.tt_tagebuch.shared.api.models.SchedulerJobBlockDto?>(
null,
)
}
@@ -617,7 +617,7 @@ internal fun TeamEditorScreen(
runCatching {
withContext(Dispatchers.IO) {
dependencies.myTischtennisApi.configureTeam(
de.tt_tagebuch.shared.api.models.MyTtConfigureTeamBody(
de.tsschulz.tt_tagebuch.shared.api.models.MyTtConfigureTeamBody(
url = myTtUrl.trim(),
clubTeamId = team!!.id,
createLeague = createLeague,
@@ -640,7 +640,7 @@ internal fun TeamEditorScreen(
runCatching {
withContext(Dispatchers.IO) {
dependencies.myTischtennisApi.configureLeague(
de.tt_tagebuch.shared.api.models.MyTtConfigureLeagueBody(
de.tsschulz.tt_tagebuch.shared.api.models.MyTtConfigureLeagueBody(
url = myTtLeagueUrl.trim(),
createSeason = createSeasonLeague,
),
@@ -1091,13 +1091,13 @@ private fun LineupTab(
Card(elevation = 0.dp, modifier = Modifier.fillMaxWidth(), backgroundColor = MaterialTheme.colors.surface) {
Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
Text(
t("mobile.teamPlanningTitle", "Mannschafts-Planung (Web)"),
t("mobile.teamPlanningTitle", "Mannschafts-Planung"),
fontWeight = FontWeight.Medium,
)
Text(
t(
"mobile.teamPlanningBody",
"Die Planungs-Ansicht mit Pool, mehreren Mannschaften und Drag-and-Drop gibt es in der Web-App unter Team-Verwaltung → Planung. In dieser App bearbeitest du die Meldung je Mannschaft hier im Tab Aufstellung.",
"Die übergreifende Planung (Pool „Möchte spielen“, mehrere Mannschaften) findest du in der Team-Verwaltung unter dem Reiter „Planung. Hier pflegst du die Meldung nur für diese eine Mannschaft.",
),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.82f),
@@ -1118,12 +1118,12 @@ private fun DocumentsTab(
t: (String, String) -> String,
canWrite: Boolean,
team: ClubTeamDto,
documents: List<de.tt_tagebuch.shared.api.models.TeamDocumentDto>,
documents: List<de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto>,
loading: Boolean,
parsingId: Int?,
onPickUpload: (String) -> Unit,
onParse: (de.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onOpen: (de.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onParse: (de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onOpen: (de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
) {
fun latest(type: String) = documents.filter { it.documentType == type }.maxByOrNull { it.id }
Column(Modifier.verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(12.dp)) {
@@ -1154,12 +1154,12 @@ private fun DocumentsTab(
@Composable
private fun DocCard(
title: String,
latest: de.tt_tagebuch.shared.api.models.TeamDocumentDto?,
latest: de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto?,
canWrite: Boolean,
parsingId: Int?,
onUpload: () -> Unit,
onParse: (de.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onOpen: (de.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onParse: (de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
onOpen: (de.tsschulz.tt_tagebuch.shared.api.models.TeamDocumentDto) -> Unit,
t: (String, String) -> String,
) {
Card(elevation = 1.dp, modifier = Modifier.fillMaxWidth()) {
@@ -1192,7 +1192,7 @@ private fun DocCard(
@Composable
private fun JobsTab(
t: (String, String) -> String,
block: de.tt_tagebuch.shared.api.models.SchedulerJobBlockDto?,
block: de.tsschulz.tt_tagebuch.shared.api.models.SchedulerJobBlockDto?,
teamId: Int,
) {
val detail = block?.teamDetails?.find { it.clubTeamId == teamId }

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -38,14 +38,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.ScheduleLogic
import de.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tt_tagebuch.shared.api.models.SeasonDto
import de.tt_tagebuch.shared.api.models.canReadTeams
import de.tt_tagebuch.shared.api.models.canWriteTeams
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.ScheduleLogic
import de.tsschulz.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.SeasonDto
import de.tsschulz.tt_tagebuch.shared.api.models.canReadTeams
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteTeams
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -53,6 +53,11 @@ import kotlinx.coroutines.withContext
private val TeamPad = 20.dp
private enum class TeamWorkspaceSection {
Teams,
Planning,
}
@Composable
internal fun TeamManagementScreen(
dependencies: AppDependencies,
@@ -81,6 +86,8 @@ internal fun TeamManagementScreen(
var editorOpen by remember { mutableStateOf(false) }
var editorTeamId by remember { mutableStateOf<Int?>(null) }
var workspace by remember { mutableStateOf(TeamWorkspaceSection.Teams) }
var seasonMenu by remember { mutableStateOf(false) }
var deleteTarget by remember { mutableStateOf<ClubTeamDto?>(null) }
@@ -172,7 +179,7 @@ internal fun TeamManagementScreen(
fontWeight = FontWeight.SemiBold,
modifier = Modifier.weight(1f),
)
if (canWrite) {
if (canWrite && workspace == TeamWorkspaceSection.Teams) {
Button(
onClick = { openNewTeamEditor() },
enabled = !loading && selectedSeasonId != null,
@@ -187,11 +194,19 @@ internal fun TeamManagementScreen(
return@Column
}
Text(
getMobileString("mobile.teamsIntro", "Mannschaften pro Saison verwalten (Name, Liga, geplante Liga, Geschlechtsklasse, Altersklasse)."),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.72f),
)
if (workspace == TeamWorkspaceSection.Teams) {
Text(
getMobileString("mobile.teamsIntro", "Mannschaften pro Saison verwalten (Name, Liga, geplante Liga, Geschlechtsklasse, Altersklasse)."),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.72f),
)
} else {
Text(
getMobileString("teamManagement.planningSubtitle", "Spieler dem Pool „Möchte spielen“ zuordnen und auf Mannschaften verteilen."),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.72f),
)
}
Spacer(Modifier.height(8.dp))
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
@@ -217,78 +232,131 @@ internal fun TeamManagementScreen(
}
Spacer(Modifier.height(8.dp))
OutlinedTextField(
value = search,
onValueChange = { search = it },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
label = { Text(getMobileString("mobile.teamSearch", "Mannschaft suchen")) },
)
error?.let {
Spacer(Modifier.height(8.dp))
Text(it, color = MaterialTheme.colors.error)
}
if (loading && teams.isEmpty()) {
Box(Modifier.fillMaxWidth().padding(top = 24.dp), contentAlignment = Alignment.Center) {
CircularProgressIndicator()
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
if (workspace == TeamWorkspaceSection.Teams) {
Button(onClick = { }, enabled = false, modifier = Modifier.weight(1f)) {
Text(getMobileString("mobile.teamWorkspaceTeams", "Mannschaften"))
}
} else {
OutlinedButton(onClick = { workspace = TeamWorkspaceSection.Teams }, modifier = Modifier.weight(1f)) {
Text(getMobileString("mobile.teamWorkspaceTeams", "Mannschaften"))
}
}
if (workspace == TeamWorkspaceSection.Planning) {
Button(onClick = { }, enabled = false, modifier = Modifier.weight(1f)) {
Text(getMobileString("mobile.teamWorkspacePlanning", "Planung"))
}
} else {
OutlinedButton(
onClick = { workspace = TeamWorkspaceSection.Planning },
enabled = selectedSeasonId != null,
modifier = Modifier.weight(1f),
) {
Text(getMobileString("mobile.teamWorkspacePlanning", "Planung"))
}
}
return@Column
}
if (!loading && teams.isEmpty()) {
Spacer(Modifier.height(16.dp))
Text(getMobileString("mobile.noTeams", "Keine Mannschaften für diese Saison."))
return@Column
}
Spacer(Modifier.height(8.dp))
LazyColumn(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
items(filtered, key = { it.id }) { team ->
Card(elevation = 1.dp, modifier = Modifier.fillMaxWidth()) {
Column(Modifier.padding(12.dp)) {
Text(team.name.ifBlank { "#${team.id}" }, fontWeight = FontWeight.SemiBold)
val lg = team.league?.name?.takeIf { it.isNotBlank() }
?: getMobileString("mobile.noLeague", "Keine Liga")
Text(lg, style = MaterialTheme.typography.caption)
team.season?.season?.takeIf { it.isNotBlank() }?.let {
Text(it, style = MaterialTheme.typography.caption)
}
team.plannedLeagueName?.takeIf { it.isNotBlank() }?.let { pl ->
Text(
getMobileString("mobile.plannedLeagueShort", "Geplant: ") + pl,
style = MaterialTheme.typography.caption,
)
}
val g = team.teamGender ?: "open"
val a = team.teamAgeGroup ?: "adult"
val genShort = getMobileString("mobile.teamGenderShort", "Geschlecht")
val ageShort = getMobileString("mobile.teamAgeShort", "AK")
Text(
"$genShort: ${labelGender(getMobileString, g)} · $ageShort: ${labelAge(getMobileString, a)}",
style = MaterialTheme.typography.caption,
)
team.myTischtennisTeamId?.takeIf { it.isNotBlank() }?.let { mid ->
Text("myTischtennis: $mid", style = MaterialTheme.typography.caption)
}
if (canWrite) {
Row(Modifier.padding(top = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
TextButton(onClick = { openEditor(team) }) {
Text(getMobileString("common.edit", "Bearbeiten"))
when (workspace) {
TeamWorkspaceSection.Teams -> {
OutlinedTextField(
value = search,
onValueChange = { search = it },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
label = { Text(getMobileString("mobile.teamSearch", "Mannschaft suchen")) },
)
error?.let {
Spacer(Modifier.height(8.dp))
Text(it, color = MaterialTheme.colors.error)
}
if (loading && teams.isEmpty()) {
Box(Modifier.fillMaxWidth().padding(top = 24.dp), contentAlignment = Alignment.Center) {
CircularProgressIndicator()
}
return@Column
}
if (!loading && teams.isEmpty()) {
Spacer(Modifier.height(16.dp))
Text(getMobileString("mobile.noTeams", "Keine Mannschaften für diese Saison."))
return@Column
}
LazyColumn(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
items(filtered, key = { it.id }) { team ->
Card(elevation = 1.dp, modifier = Modifier.fillMaxWidth()) {
Column(Modifier.padding(12.dp)) {
Text(team.name.ifBlank { "#${team.id}" }, fontWeight = FontWeight.SemiBold)
val lg = team.league?.name?.takeIf { it.isNotBlank() }
?: getMobileString("mobile.noLeague", "Keine Liga")
Text(lg, style = MaterialTheme.typography.caption)
team.season?.season?.takeIf { it.isNotBlank() }?.let {
Text(it, style = MaterialTheme.typography.caption)
}
TextButton(onClick = { deleteTarget = team }) {
Text(getMobileString("common.delete", "Löschen"), color = MaterialTheme.colors.error)
team.plannedLeagueName?.takeIf { it.isNotBlank() }?.let { pl ->
Text(
getMobileString("mobile.plannedLeagueShort", "Geplant: ") + pl,
style = MaterialTheme.typography.caption,
)
}
val g = team.teamGender ?: "open"
val a = team.teamAgeGroup ?: "adult"
val genShort = getMobileString("mobile.teamGenderShort", "Geschlecht")
val ageShort = getMobileString("mobile.teamAgeShort", "AK")
Text(
"$genShort: ${labelGender(getMobileString, g)} · $ageShort: ${labelAge(getMobileString, a)}",
style = MaterialTheme.typography.caption,
)
team.myTischtennisTeamId?.takeIf { it.isNotBlank() }?.let { mid ->
Text("myTischtennis: $mid", style = MaterialTheme.typography.caption)
}
if (canWrite) {
Row(Modifier.padding(top = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
TextButton(onClick = { openEditor(team) }) {
Text(getMobileString("common.edit", "Bearbeiten"))
}
TextButton(onClick = { deleteTarget = team }) {
Text(getMobileString("common.delete", "Löschen"), color = MaterialTheme.colors.error)
}
}
}
}
}
}
}
}
TeamWorkspaceSection.Planning -> {
val sid = selectedSeasonId
if (sid == null) {
Text(getMobileString("mobile.seasonPick", "Saison wählen"))
} else {
TeamPlanningScreen(
dependencies = dependencies,
clubId = clubId,
seasonId = sid,
seasonLabel = seasons.find { it.id == sid }?.season.orEmpty(),
teams = teams,
canWrite = canWrite,
onTeamsChanged = { loadTick++ },
onOpenTeamEditor = { tid ->
editorTeamId = tid
editorOpen = true
},
t = getMobileString,
modifier = Modifier.weight(1f).fillMaxWidth(),
)
}
}
}
}
}

View File

@@ -0,0 +1,101 @@
package de.tsschulz.tt_tagebuch.app.ui
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import java.util.Calendar
import java.util.GregorianCalendar
/**
* Zuordnungen Spieler ↔ Mannschaft in der Saison-Planung (Halbserie),
* analog `planningAssignments` / `normalizePlanningTeamAssignments` in `TeamManagementView.vue`.
*/
internal data class PlanningAssignment(
val teamId: Int,
val memberId: Int,
val position: Int,
)
internal object TeamPlanningLogic {
fun defaultLineupHalf(): String =
if (isSecondHalfSeason()) "second_half" else "first_half"
private fun isSecondHalfSeason(): Boolean {
val now = GregorianCalendar()
val seasonStart = GregorianCalendar(now.get(Calendar.YEAR), Calendar.JULY, 1, 0, 0, 0)
if (seasonStart.after(now)) {
seasonStart.add(Calendar.YEAR, -1)
}
val secondHalfStart = GregorianCalendar(seasonStart.get(Calendar.YEAR) + 1, Calendar.JANUARY, 1, 0, 0, 0)
return now.timeInMillis >= secondHalfStart.timeInMillis
}
fun normalizeAssignments(raw: List<PlanningAssignment>): List<PlanningAssignment> {
val filtered = raw.filter { it.teamId > 0 && it.memberId > 0 }
val byTeam = filtered.groupBy { it.teamId }
val out = ArrayList<PlanningAssignment>()
byTeam.entries.sortedBy { it.key }.forEach { (_, entries) ->
entries
.sortedBy { it.position }
.forEachIndexed { idx, e ->
out.add(PlanningAssignment(teamId = e.teamId, memberId = e.memberId, position = idx + 1))
}
}
return out
}
fun withoutMember(assignments: List<PlanningAssignment>, memberId: Int): List<PlanningAssignment> =
assignments.filter { it.memberId != memberId }
fun assignToTeamEnd(
assignments: List<PlanningAssignment>,
teamId: Int,
memberId: Int,
): List<PlanningAssignment> {
val without = withoutMember(assignments, memberId)
val teamCount = without.count { it.teamId == teamId }
return without + PlanningAssignment(teamId = teamId, memberId = memberId, position = teamCount + 1)
}
fun removeFromTeam(assignments: List<PlanningAssignment>, teamId: Int, memberId: Int): List<PlanningAssignment> {
val without = assignments.filterNot { it.teamId == teamId && it.memberId == memberId }
return normalizeAssignments(without)
}
fun moveWithinTeam(
assignments: List<PlanningAssignment>,
teamId: Int,
memberId: Int,
direction: Int,
): List<PlanningAssignment>? {
val teamEntries = assignments.filter { it.teamId == teamId }.sortedBy { it.position }
val index = teamEntries.indexOfFirst { it.memberId == memberId }
if (index < 0) return null
val target = index + direction
if (target < 0 || target >= teamEntries.size) return null
val reordered = teamEntries.toMutableList()
val tmp = reordered[index]
reordered[index] = reordered[target]
reordered[target] = tmp
val others = assignments.filter { it.teamId != teamId }
val updated = others + reordered.mapIndexed { idx, e ->
PlanningAssignment(teamId = teamId, memberId = e.memberId, position = idx + 1)
}
return normalizeAssignments(updated)
}
fun teamLineupMembers(assignments: List<PlanningAssignment>, teamId: Int, membersById: Map<Int, Member>): List<Member> =
assignments
.filter { it.teamId == teamId }
.sortedBy { it.position }
.mapNotNull { membersById[it.memberId] }
fun isEligible(member: Member, team: ClubTeamDto, seasonLabel: String): Boolean {
val tAge = TeamEditorLineupLogic.configuredTeamAgeGroup(team.teamAgeGroup, team.league?.name)
val tGender = TeamEditorLineupLogic.configuredTeamGender(team.teamGender, team.league?.name)
return TeamEditorLineupLogic.isEligibleForTeam(member, tAge, tGender, seasonLabel)
}
fun lineupGapOk(membersOrdered: List<Member>, template: (String, String) -> String): String? =
TeamEditorLineupLogic.lineupGapViolationMessage(membersOrdered, template)
}

View File

@@ -0,0 +1,645 @@
package de.tsschulz.tt_tagebuch.app.ui
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamCreateBody
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamUpdateBody
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.MemberPlayInterestSetBody
import de.tsschulz.tt_tagebuch.shared.api.models.TeamLineupAssignmentItem
import de.tsschulz.tt_tagebuch.shared.api.models.TeamLineupUpdateBody
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
private data class TeamDraft(
val name: String,
val plannedLeagueName: String,
val teamGender: String,
val teamAgeGroup: String,
)
private fun filterAssignmentsForTeamEligibility(
teamId: Int,
src: List<PlanningAssignment>,
teams: List<ClubTeamDto>,
drafts: Map<Int, TeamDraft>,
membersById: Map<Int, Member>,
seasonLabel: String,
): List<PlanningAssignment> {
val team = teams.find { it.id == teamId } ?: return src
val d = drafts[teamId] ?: return src
val pseudo = team.copy(
name = d.name,
plannedLeagueName = d.plannedLeagueName.ifBlank { null },
teamGender = d.teamGender,
teamAgeGroup = d.teamAgeGroup,
)
return TeamPlanningLogic.normalizeAssignments(
src.filter { a ->
if (a.teamId != teamId) return@filter true
val m = membersById[a.memberId] ?: return@filter false
TeamPlanningLogic.isEligible(m, pseudo, seasonLabel)
},
)
}
@Composable
internal fun TeamPlanningScreen(
dependencies: AppDependencies,
clubId: Int,
seasonId: Int,
seasonLabel: String,
teams: List<ClubTeamDto>,
canWrite: Boolean,
onTeamsChanged: () -> Unit,
onOpenTeamEditor: (Int) -> Unit,
t: (String, String) -> String,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
var lineupHalf by remember { mutableStateOf(TeamPlanningLogic.defaultLineupHalf()) }
var members by remember { mutableStateOf<List<Member>>(emptyList()) }
var interestedIds by remember { mutableStateOf<Set<Int>>(emptySet()) }
var assignments by remember { mutableStateOf<List<PlanningAssignment>>(emptyList()) }
val drafts = remember { mutableStateMapOf<Int, TeamDraft>() }
var loading by remember { mutableStateOf(true) }
var poolSearch by remember { mutableStateOf("") }
var addInterestMemberId by remember { mutableStateOf<Int?>(null) }
var addInterestMenu by remember { mutableStateOf(false) }
var markingInterest by remember { mutableStateOf(false) }
var deleteTeamId by remember { mutableStateOf<Int?>(null) }
var info by remember { mutableStateOf<String?>(null) }
val membersById = remember(members) { members.associateBy { it.id } }
LaunchedEffect(teams.map { "${it.id}:${it.name}:${it.teamGender}:${it.teamAgeGroup}" }.joinToString("|")) {
teams.forEach { team ->
drafts[team.id] = TeamDraft(
name = team.name,
plannedLeagueName = team.plannedLeagueName.orEmpty(),
teamGender = team.teamGender?.takeIf { it.isNotBlank() } ?: "open",
teamAgeGroup = team.teamAgeGroup?.takeIf { it.isNotBlank() } ?: "adult",
)
}
val keep = teams.map { it.id }.toSet()
drafts.keys.filter { it !in keep }.forEach { drafts.remove(it) }
}
suspend fun loadPlanningData() {
loading = true
runCatching {
coroutineScope {
val memJob = async(Dispatchers.IO) {
dependencies.membersApi.listMembers(clubId, showAll = true)
}
val intJob = async(Dispatchers.IO) {
dependencies.membersApi.listPlayInterests(clubId, seasonId, lineupHalf)
}
members = memJob.await()
interestedIds = intJob.await().map { it.memberId }.toSet()
val lineupJobs = teams.map { team ->
async(Dispatchers.IO) {
runCatching {
team.id to dependencies.clubTeamsApi.getLineup(team.id, lineupHalf)
}.getOrElse { team.id to emptyList() }
}
}
val lineups = lineupJobs.awaitAll()
assignments = TeamPlanningLogic.normalizeAssignments(
lineups.flatMap { (teamId, rows) ->
rows.sortedBy { it.position }.mapIndexed { idx, row ->
PlanningAssignment(teamId = teamId, memberId = row.memberId, position = idx + 1)
}
},
)
}
}.onFailure { ex ->
if (ex !is CancellationException) {
info = ex.message ?: t("mobile.teamLoadError", "Laden fehlgeschlagen")
}
}
loading = false
}
LaunchedEffect(clubId, seasonId, lineupHalf, teams.map { it.id }.sorted().joinToString(",")) {
loadPlanningData()
}
val poolMembers = remember(members, interestedIds, poolSearch) {
val q = poolSearch.trim().lowercase()
members.filter { it.id in interestedIds && it.active }
.filter {
if (q.isEmpty()) true
else "${it.firstName} ${it.lastName}".lowercase().contains(q)
}
.sortedWith(compareBy({ it.lastName.lowercase() }, { it.firstName.lowercase() }))
}
val assignedIds = remember(assignments) { assignments.map { it.memberId }.toSet() }
val unassignedPool = remember(poolMembers, assignedIds) {
poolMembers.filter { it.id !in assignedIds }
}
val selectableForInterest = remember(members, interestedIds, poolSearch) {
val q = poolSearch.trim().lowercase()
members.filter { m ->
m.active && m.testMembership != true && m.id !in interestedIds &&
(q.isEmpty() || "${m.firstName} ${m.lastName}".lowercase().contains(q))
}.sortedWith(compareBy({ it.lastName.lowercase() }, { it.firstName.lowercase() }))
}
fun persistTeam(teamId: Int, nextAssignments: List<PlanningAssignment>, onDone: () -> Unit = {}) {
val team = teams.find { it.id == teamId } ?: return
val draft = drafts[teamId] ?: return
scope.launch {
val byId = members.associateBy { it.id }
runCatching {
val orderedMembers = TeamPlanningLogic.teamLineupMembers(nextAssignments, teamId, byId)
val gap = TeamPlanningLogic.lineupGapOk(orderedMembers) { hi, lo ->
t("mobile.lineupGapWarn", "QTTR-Abstand >30: $hi über $lo")
}
if (gap != null) {
Toast.makeText(context, gap, Toast.LENGTH_LONG).show()
return@launch
}
val items = orderedMembers.mapIndexed { i, m -> TeamLineupAssignmentItem(m.id, i + 1) }
withContext(Dispatchers.IO) {
dependencies.clubTeamsApi.updateClubTeam(
teamId,
ClubTeamUpdateBody(
name = draft.name.trim(),
leagueId = team.leagueId,
seasonId = team.seasonId ?: seasonId,
teamGender = draft.teamGender,
teamAgeGroup = draft.teamAgeGroup,
plannedLeagueName = draft.plannedLeagueName.trim().ifBlank { null },
),
)
dependencies.clubTeamsApi.updateLineup(
teamId,
TeamLineupUpdateBody(assignments = items, lineupHalf = lineupHalf),
)
}
assignments = TeamPlanningLogic.normalizeAssignments(nextAssignments)
onTeamsChanged()
onDone()
}.onFailure { ex ->
if (ex !is CancellationException) info = ex.message
}
}
}
Column(modifier.fillMaxSize()) {
Text(
t("teamManagement.planningSubtitle", "Spieler dem Pool „Möchte spielen“ zuordnen und auf Mannschaften verteilen."),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.78f),
)
Spacer(Modifier.height(8.dp))
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
Text(t("common.period", "Halbserie"), style = MaterialTheme.typography.body2)
listOf("first_half" to "VR", "second_half" to "RR").forEach { (v, label) ->
OutlinedButton(
onClick = { lineupHalf = v },
enabled = !loading && lineupHalf != v,
) { Text(label) }
}
Spacer(Modifier.weight(1f))
OutlinedButton(onClick = { scope.launch { loadPlanningData() } }, enabled = !loading) {
Text(t("teamManagement.refreshStats", "Aktualisieren"))
}
}
if (loading) {
CircularProgressIndicator(Modifier.padding(16.dp))
} else {
LazyColumn(
Modifier
.weight(1f)
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
item {
Text(t("teamManagement.playersWantToPlay", "Möchte spielen (Pool)"), fontWeight = FontWeight.SemiBold)
OutlinedTextField(
value = poolSearch,
onValueChange = { poolSearch = it },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
label = { Text(t("teamManagement.searchMembers", "Mitglieder suchen")) },
)
Text(
t("mobile.teamPlanningUnassigned", "Noch keiner Mannschaft zugeordnet") + ": ${unassignedPool.size}",
style = MaterialTheme.typography.caption,
)
}
items(unassignedPool, key = { it.id }) { m ->
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text("${m.firstName} ${m.lastName}", fontWeight = FontWeight.Medium)
}
if (canWrite) {
var addMenu by remember(key1 = m.id) { mutableStateOf(false) }
Box {
OutlinedButton(onClick = { addMenu = true }) {
Text(t("mobile.teamPlanningAssign", "Zu Mannschaft …"))
}
DropdownMenu(expanded = addMenu, onDismissRequest = { addMenu = false }) {
teams.forEach { team ->
val draft = drafts[team.id] ?: return@forEach
val pseudo = team.copy(
name = draft.name,
plannedLeagueName = draft.plannedLeagueName.ifBlank { null },
teamGender = draft.teamGender,
teamAgeGroup = draft.teamAgeGroup,
)
val ok = TeamPlanningLogic.isEligible(m, pseudo, seasonLabel)
DropdownMenuItem(
onClick = {
addMenu = false
if (!ok) {
Toast.makeText(
context,
t(
"mobile.teamPlanningNotEligible",
"Mitglied passt nicht zu Alters-/Geschlechtsklasse dieser Mannschaft.",
),
Toast.LENGTH_LONG,
).show()
return@DropdownMenuItem
}
val next = TeamPlanningLogic.assignToTeamEnd(assignments, team.id, m.id)
val gapMembers = TeamPlanningLogic.teamLineupMembers(next, team.id, membersById)
val gap = TeamPlanningLogic.lineupGapOk(gapMembers) { hi, lo ->
t("mobile.lineupGapWarn", "QTTR-Abstand >30: $hi über $lo")
}
if (gap != null) {
Toast.makeText(context, gap, Toast.LENGTH_LONG).show()
return@DropdownMenuItem
}
persistTeam(team.id, next)
},
enabled = ok,
) {
Text(team.name.ifBlank { "#${team.id}" })
}
}
}
}
}
}
}
item {
Divider()
Text(t("teamManagement.markAsInterested", "Als interessiert markieren"), fontWeight = FontWeight.SemiBold)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Box(Modifier.weight(1f)) {
OutlinedButton(
onClick = { addInterestMenu = true },
enabled = canWrite && !markingInterest,
modifier = Modifier.fillMaxWidth(),
) {
Text(
addInterestMemberId?.let { id ->
membersById[id]?.let { "${it.firstName} ${it.lastName}" }
} ?: t("teamManagement.selectMember", "Mitglied wählen"),
)
}
DropdownMenu(expanded = addInterestMenu, onDismissRequest = { addInterestMenu = false }) {
selectableForInterest.take(400).forEach { m ->
DropdownMenuItem(
onClick = {
addInterestMemberId = m.id
addInterestMenu = false
},
) { Text("${m.firstName} ${m.lastName}") }
}
}
}
Button(
onClick = {
val mid = addInterestMemberId ?: return@Button
scope.launch {
markingInterest = true
runCatching {
withContext(Dispatchers.IO) {
dependencies.membersApi.setPlayInterest(
clubId,
MemberPlayInterestSetBody(
memberId = mid,
seasonId = seasonId,
lineupHalf = lineupHalf,
interested = true,
),
)
}
interestedIds = interestedIds + mid
addInterestMemberId = null
}.onFailure { if (it !is CancellationException) info = it.message }
markingInterest = false
}
},
enabled = canWrite && addInterestMemberId != null && !markingInterest,
) {
Text(if (markingInterest) "" else t("teamManagement.markAsInterested", "Interesse speichern"))
}
}
}
item {
Divider()
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
Text(t("teamManagement.planningTitle", "Planung"), fontWeight = FontWeight.SemiBold)
if (canWrite) {
Button(
onClick = {
scope.launch {
runCatching {
val nextIndex = teams.size + 1
withContext(Dispatchers.IO) {
dependencies.clubTeamsApi.createClubTeam(
clubId,
ClubTeamCreateBody(
name = t("teamManagement.teamName", "Mannschaft") + " $nextIndex",
leagueId = null,
seasonId = seasonId,
teamGender = "open",
teamAgeGroup = "adult",
plannedLeagueName = null,
),
)
}
onTeamsChanged()
}.onFailure { if (it !is CancellationException) info = it.message }
}
},
) {
Text(t("teamManagement.addPlanningTeam", "Mannschaft hinzufügen"))
}
}
}
}
items(teams, key = { it.id }) { team ->
val teamId = team.id
val draft = drafts[teamId] ?: return@items
CardTeamPlanningBlock(
team = team,
draft = draft,
onDraftChange = { nd -> drafts[teamId] = nd },
assignments = assignments,
membersById = membersById,
canWrite = canWrite,
t = t,
onPersistLineup = { next -> persistTeam(teamId, next) },
onSaveTeamMeta = {
val fa = filterAssignmentsForTeamEligibility(
teamId,
assignments,
teams,
drafts,
membersById,
seasonLabel,
)
persistTeam(teamId, fa)
},
onMoveInTeam = { memberId, dir ->
val next = TeamPlanningLogic.moveWithinTeam(assignments, teamId, memberId, dir)
if (next != null) persistTeam(teamId, next)
},
onRemoveMember = { memberId ->
val next = TeamPlanningLogic.removeFromTeam(assignments, teamId, memberId)
persistTeam(teamId, next)
},
onOpenEditor = { onOpenTeamEditor(teamId) },
onDeleteRequest = { deleteTeamId = teamId },
poolAddCandidates = unassignedPool.filter { u ->
val pseudo = team.copy(
name = draft.name,
plannedLeagueName = draft.plannedLeagueName.ifBlank { null },
teamGender = draft.teamGender,
teamAgeGroup = draft.teamAgeGroup,
)
TeamPlanningLogic.isEligible(u, pseudo, seasonLabel)
},
)
}
}
}
}
deleteTeamId?.let { tid ->
AlertDialog(
onDismissRequest = { deleteTeamId = null },
title = { Text(t("mobile.teamDeleteTitle", "Mannschaft löschen?")) },
text = { Text(teams.find { it.id == tid }?.name.orEmpty()) },
confirmButton = {
TextButton(
onClick = {
deleteTeamId = null
scope.launch {
runCatching {
withContext(Dispatchers.IO) { dependencies.clubTeamsApi.deleteClubTeam(tid) }
onTeamsChanged()
}.onFailure { if (it !is CancellationException) info = it.message }
}
},
) { Text(t("common.delete", "Löschen")) }
},
dismissButton = { TextButton(onClick = { deleteTeamId = null }) { Text(t("common.cancel", "Abbrechen")) } },
)
}
info?.let { msg ->
AlertDialog(
onDismissRequest = { info = null },
title = { Text(t("common.error", "Fehler")) },
text = { Text(msg) },
confirmButton = { TextButton(onClick = { info = null }) { Text(t("common.ok", "OK")) } },
)
}
}
@Composable
private fun CardTeamPlanningBlock(
team: ClubTeamDto,
draft: TeamDraft,
onDraftChange: (TeamDraft) -> Unit,
assignments: List<PlanningAssignment>,
membersById: Map<Int, Member>,
canWrite: Boolean,
t: (String, String) -> String,
onPersistLineup: (List<PlanningAssignment>) -> Unit,
onSaveTeamMeta: () -> Unit,
onMoveInTeam: (Int, Int) -> Unit,
onRemoveMember: (Int) -> Unit,
onOpenEditor: () -> Unit,
onDeleteRequest: () -> Unit,
poolAddCandidates: List<Member>,
) {
val teamId = team.id
val ordered = TeamPlanningLogic.teamLineupMembers(assignments, teamId, membersById)
var metaMenu by remember { mutableStateOf(false) }
var addMemberMenu by remember { mutableStateOf(false) }
val cardContext = LocalContext.current
Column(Modifier.fillMaxWidth()) {
Text(team.name.ifBlank { "#$teamId" }, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.subtitle1)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
OutlinedButton(onClick = onOpenEditor) {
Text(t("teamManagement.openInWorkspace", "Im Editor öffnen"))
}
if (canWrite) {
OutlinedButton(onClick = onDeleteRequest) {
Text(t("common.delete", "Löschen"))
}
}
}
Spacer(Modifier.height(6.dp))
OutlinedTextField(
value = draft.name,
onValueChange = { onDraftChange(draft.copy(name = it)) },
label = { Text(t("teamManagement.teamName", "Mannschaft")) },
modifier = Modifier.fillMaxWidth(),
enabled = canWrite,
singleLine = true,
)
OutlinedTextField(
value = draft.plannedLeagueName,
onValueChange = { onDraftChange(draft.copy(plannedLeagueName = it)) },
label = { Text(t("teamManagement.plannedLeague", "Geplante Liga")) },
modifier = Modifier.fillMaxWidth(),
enabled = canWrite,
singleLine = true,
)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Box {
OutlinedButton(onClick = { metaMenu = true }, enabled = canWrite) {
Text(t("mobile.teamAgeShort", "AK") + ": ${draft.teamAgeGroup}")
}
DropdownMenu(expanded = metaMenu, onDismissRequest = { metaMenu = false }) {
listOf("adult", "J19", "J17", "J15", "J13", "J11").forEach { a ->
DropdownMenuItem(
onClick = {
metaMenu = false
onDraftChange(draft.copy(teamAgeGroup = a))
onSaveTeamMeta()
},
) { Text(a) }
}
}
}
Box {
var gMenu by remember { mutableStateOf(false) }
OutlinedButton(onClick = { gMenu = true }, enabled = canWrite) {
Text(t("mobile.teamGenderShort", "GK") + ": ${draft.teamGender}")
}
DropdownMenu(expanded = gMenu, onDismissRequest = { gMenu = false }) {
listOf("open", "female").forEach { g ->
DropdownMenuItem(
onClick = {
gMenu = false
onDraftChange(draft.copy(teamGender = g))
onSaveTeamMeta()
},
) { Text(g) }
}
}
}
}
if (canWrite) {
Button(
onClick = { onSaveTeamMeta() },
modifier = Modifier.fillMaxWidth(),
) {
Text(t("mobile.teamPlanningSaveTeam", "Mannschaft speichern"))
}
}
Spacer(Modifier.height(4.dp))
Text(t("teamManagement.selectedLineup", "Meldung"), fontWeight = FontWeight.Medium)
ordered.forEachIndexed { index, m ->
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
Text("${index + 1}. ${m.firstName} ${m.lastName}")
if (canWrite) {
Row {
TextButton(onClick = { onMoveInTeam(m.id, -1) }, enabled = index > 0) { Text("") }
TextButton(onClick = { onMoveInTeam(m.id, 1) }, enabled = index < ordered.lastIndex) { Text("") }
TextButton(onClick = { onRemoveMember(m.id) }) { Text("") }
}
}
}
}
if (canWrite && poolAddCandidates.isNotEmpty()) {
Box {
OutlinedButton(onClick = { addMemberMenu = true }) {
Text(t("mobile.teamLineupAddToLineup", "Hinzufügen"))
}
DropdownMenu(expanded = addMemberMenu, onDismissRequest = { addMemberMenu = false }) {
poolAddCandidates.forEach { m ->
DropdownMenuItem(
onClick = {
addMemberMenu = false
val next = TeamPlanningLogic.assignToTeamEnd(assignments, teamId, m.id)
val gapMembers = TeamPlanningLogic.teamLineupMembers(next, teamId, membersById)
val gap = TeamPlanningLogic.lineupGapOk(gapMembers) { hi, lo ->
t("mobile.lineupGapWarn", "QTTR-Abstand >30: $hi über $lo")
}
if (gap != null) {
Toast.makeText(cardContext, gap, Toast.LENGTH_LONG).show()
} else {
onPersistLineup(next)
}
},
) { Text("${m.firstName} ${m.lastName}") }
}
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -40,15 +40,15 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.shared.api.models.AddMiniChampionshipBody
import de.tt_tagebuch.shared.api.models.AddStandardTournamentBody
import de.tt_tagebuch.shared.api.models.InternalTournamentSummaryDto
import de.tt_tagebuch.shared.api.models.OfficialParticipationEntryDto
import de.tt_tagebuch.shared.api.models.canReadTournaments
import de.tt_tagebuch.shared.api.models.canWriteTournaments
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tt_tagebuch.shared.state.ClubTournamentDisplayFilter
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.AddMiniChampionshipBody
import de.tsschulz.tt_tagebuch.shared.api.models.AddStandardTournamentBody
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentSummaryDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParticipationEntryDto
import de.tsschulz.tt_tagebuch.shared.api.models.canReadTournaments
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteTournaments
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.shared.state.ClubTournamentDisplayFilter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
@@ -42,11 +42,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import de.tt_tagebuch.app.AppDependencies
import de.tt_tagebuch.app.pdf.shareFileWithMime
import de.tt_tagebuch.app.stats.TrainingStatsDerived
import de.tt_tagebuch.shared.api.models.TrainingStatsMember
import de.tt_tagebuch.shared.i18n.MobileStrings
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.app.pdf.shareFileWithMime
import de.tsschulz.tt_tagebuch.app.stats.TrainingStatsDerived
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingStatsMember
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.material.MaterialTheme
import androidx.compose.material.lightColors

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.app.util
package de.tsschulz.tt_tagebuch.app.util
import de.tt_tagebuch.shared.api.models.Member
import de.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedCompetitionDto
import de.tsschulz.tt_tagebuch.shared.api.models.OfficialParsedTournamentEnvelopeDto
import java.text.Collator
import java.text.SimpleDateFormat
import java.util.Calendar

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Entspricht legacy Expo android.adaptiveIcon.backgroundColor -->
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app
package de.tsschulz.tt_tagebuch.app
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import cafe.adriel.voyager.navigator.Navigator
import de.tt_tagebuch.app.ui.LoginScreen
import de.tsschulz.tt_tagebuch.app.ui.LoginScreen
@Composable
fun App() {

View File

@@ -0,0 +1,16 @@
package de.tsschulz.tt_tagebuch.app.di
import de.tsschulz.tt_tagebuch.app.viewmodel.DiaryScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.LoginScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.ParticipantScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberEditScreenModel
import org.koin.dsl.module
val appModule = module {
factory { LoginScreenModel(get()) }
factory { DiaryScreenModel(get()) }
factory { MemberScreenModel(get()) } // Updated
factory { ParticipantScreenModel(get()) }
factory { MemberEditScreenModel(get()) }
}

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@@ -13,8 +13,8 @@ import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import de.tt_tagebuch.app.viewmodel.DiaryScreenModel
import de.tt_tagebuch.app.viewmodel.DiaryState
import de.tsschulz.tt_tagebuch.app.viewmodel.DiaryScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.DiaryState
class DiaryScreen(private val clubId: Int) : Screen {
@Composable
@@ -65,7 +65,7 @@ class DiaryScreen(private val clubId: Int) : Screen {
}
@Composable
fun DiaryDateItem(date: de.tt_tagebuch.shared.models.DiaryDate, onClick: () -> Unit) {
fun DiaryDateItem(date: de.tsschulz.tt_tagebuch.shared.models.DiaryDate, onClick: () -> Unit) {
Card(
modifier = Modifier.fillMaxWidth().padding(8.dp).clickable { onClick() },
elevation = 4.dp

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
@@ -10,9 +10,9 @@ import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import de.tt_tagebuch.app.viewmodel.LoginScreenModel
import de.tt_tagebuch.app.viewmodel.LoginState
import de.tt_tagebuch.app.ui.HomeScreen
import de.tsschulz.tt_tagebuch.app.viewmodel.LoginScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.LoginState
import de.tsschulz.tt_tagebuch.app.ui.HomeScreen
class LoginScreen : Screen {
@Composable

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -16,7 +16,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import de.tt_tagebuch.shared.models.Member
import de.tsschulz.tt_tagebuch.shared.models.Member
class MemberDetailScreen(private val member: Member) : Screen {
@Composable
@@ -121,7 +121,7 @@ class MemberDetailScreen(private val member: Member) : Screen {
}
@Composable
fun ContactRow(contact: de.tt_tagebuch.shared.models.MemberContact) {
fun ContactRow(contact: de.tsschulz.tt_tagebuch.shared.models.MemberContact) {
Row(
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -16,10 +16,10 @@ import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import de.tt_tagebuch.app.viewmodel.MemberEditScreenModel
import de.tt_tagebuch.app.viewmodel.MemberEditState
import de.tt_tagebuch.shared.models.Member
import de.tt_tagebuch.shared.models.MemberContact
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberEditScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberEditState
import de.tsschulz.tt_tagebuch.shared.models.Member
import de.tsschulz.tt_tagebuch.shared.models.MemberContact
class MemberEditScreen(private val clubId: Int, private val member: Member? = null) : Screen {
@Composable

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@@ -13,8 +13,8 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import de.tt_tagebuch.app.viewmodel.MemberScreenModel
import de.tt_tagebuch.app.viewmodel.MemberState
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.MemberState
import cafe.adriel.voyager.navigator.LocalNavigator
@@ -70,7 +70,7 @@ class MemberScreen(private val clubId: Int) : Screen {
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun MemberItem(member: de.tt_tagebuch.shared.models.Member, onClick: () -> Unit) {
fun MemberItem(member: de.tsschulz.tt_tagebuch.shared.models.Member, onClick: () -> Unit) {
ListItem(
modifier = Modifier.clickable { onClick() },
text = { Text("${member.firstName} ${member.lastName}") },

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.app.ui
package de.tsschulz.tt_tagebuch.app.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@@ -14,8 +14,8 @@ import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import de.tt_tagebuch.app.viewmodel.ParticipantScreenModel
import de.tt_tagebuch.app.viewmodel.ParticipantState
import de.tsschulz.tt_tagebuch.app.viewmodel.ParticipantScreenModel
import de.tsschulz.tt_tagebuch.app.viewmodel.ParticipantState
class ParticipantScreen(private val dateId: Int, private val dateStr: String) : Screen {
@Composable
@@ -69,7 +69,7 @@ class ParticipantScreen(private val dateId: Int, private val dateStr: String) :
@Composable
fun ParticipantItem(
participant: de.tt_tagebuch.shared.models.Participant,
participant: de.tsschulz.tt_tagebuch.shared.models.Participant,
onStatusChange: (String) -> Unit
) {
val member = participant.member

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app.viewmodel
package de.tsschulz.tt_tagebuch.app.viewmodel
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import de.tt_tagebuch.shared.models.DiaryDate
import de.tt_tagebuch.shared.repository.DiaryRepository
import de.tsschulz.tt_tagebuch.shared.models.DiaryDate
import de.tsschulz.tt_tagebuch.shared.repository.DiaryRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.app.viewmodel
package de.tsschulz.tt_tagebuch.app.viewmodel
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import de.tt_tagebuch.shared.repository.AuthRepository
import de.tsschulz.tt_tagebuch.shared.repository.AuthRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app.viewmodel
package de.tsschulz.tt_tagebuch.app.viewmodel
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import de.tt_tagebuch.shared.models.Member
import de.tt_tagebuch.shared.repository.MemberRepository
import de.tsschulz.tt_tagebuch.shared.models.Member
import de.tsschulz.tt_tagebuch.shared.repository.MemberRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app.viewmodel
package de.tsschulz.tt_tagebuch.app.viewmodel
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import de.tt_tagebuch.shared.models.Member
import de.tt_tagebuch.shared.repository.DiaryRepository
import de.tsschulz.tt_tagebuch.shared.models.Member
import de.tsschulz.tt_tagebuch.shared.repository.DiaryRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.app.viewmodel
package de.tsschulz.tt_tagebuch.app.viewmodel
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import de.tt_tagebuch.shared.models.Participant
import de.tt_tagebuch.shared.repository.DiaryRepository
import de.tsschulz.tt_tagebuch.shared.models.Participant
import de.tsschulz.tt_tagebuch.shared.repository.DiaryRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View File

@@ -1,16 +0,0 @@
package de.tt_tagebuch.app.di
import de.tt_tagebuch.app.viewmodel.DiaryScreenModel
import de.tt_tagebuch.app.viewmodel.LoginScreenModel
import de.tt_tagebuch.app.viewmodel.MemberScreenModel
import de.tt_tagebuch.app.viewmodel.ParticipantScreenModel
import de.tt_tagebuch.app.viewmodel.MemberEditScreenModel
import org.koin.dsl.module
val appModule = module {
factory { LoginScreenModel(get()) }
factory { DiaryScreenModel(get()) }
factory { MemberScreenModel(get()) } // Updated
factory { ParticipantScreenModel(get()) }
factory { MemberEditScreenModel(get()) }
}

View File

@@ -3,7 +3,7 @@
# Nutzung: von mobile-app/ aus: ./scripts/install-debug-emulator.sh
set -euo pipefail
cd "$(dirname "$0")/.."
adb uninstall de.tt_tagebuch.app 2>/dev/null || true
adb uninstall de.tsschulz.tt_tagebuch 2>/dev/null || true
./gradlew :composeApp:clean :composeApp:installDebug \
-PbackendBaseUrl=http://10.0.2.2:3005 \
--no-configuration-cache

View File

@@ -47,7 +47,7 @@ kotlin {
}
android {
namespace = "de.tt_tagebuch.shared"
namespace = "de.tsschulz.tt_tagebuch.shared"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.shared.api.http
package de.tsschulz.tt_tagebuch.shared.api.http
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.engine.okhttp.OkHttp

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.shared.state
package de.tsschulz.tt_tagebuch.shared.state
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.shared.state
package de.tsschulz.tt_tagebuch.shared.state
import android.content.Context
import kotlinx.coroutines.Dispatchers

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.shared.state
package de.tsschulz.tt_tagebuch.shared.state
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.AccidentReportDto
import de.tt_tagebuch.shared.api.models.CreateAccidentBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.AccidentReportDto
import de.tsschulz.tt_tagebuch.shared.api.models.CreateAccidentBody
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.post

View File

@@ -1,6 +1,6 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.models.*
import de.tsschulz.tt_tagebuch.shared.models.*
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*

View File

@@ -1,4 +1,4 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
data class ApiConfig(
val baseUrl: String,

View File

@@ -1,11 +1,11 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.ApiLogDetailDto
import de.tt_tagebuch.shared.api.models.ApiLogDetailEnvelopeDto
import de.tt_tagebuch.shared.api.models.ApiLogsListEnvelopeDto
import de.tt_tagebuch.shared.api.models.ApiLogsListPageDto
import de.tt_tagebuch.shared.api.models.SchedulerLastExecutionsEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogDetailDto
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogDetailEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogsListEnvelopeDto
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogsListPageDto
import de.tsschulz.tt_tagebuch.shared.api.models.SchedulerLastExecutionsEnvelopeDto
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.LoginRequest
import de.tt_tagebuch.shared.api.models.LoginResponse
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.LoginRequest
import de.tsschulz.tt_tagebuch.shared.api.models.LoginResponse
import io.ktor.client.call.body
import io.ktor.client.request.post
import io.ktor.client.request.setBody

View File

@@ -1,14 +1,14 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.BillingCreateRunBody
import de.tt_tagebuch.shared.api.models.BillingCreateRunEnvelope
import de.tt_tagebuch.shared.api.models.BillingGenerateBody
import de.tt_tagebuch.shared.api.models.BillingGenerateEnvelope
import de.tt_tagebuch.shared.api.models.BillingHoursPreviewEnvelope
import de.tt_tagebuch.shared.api.models.BillingRunsEnvelope
import de.tt_tagebuch.shared.api.models.BillingSettingsEnvelope
import de.tt_tagebuch.shared.api.models.BillingTemplatesEnvelope
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.BillingCreateRunBody
import de.tsschulz.tt_tagebuch.shared.api.models.BillingCreateRunEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingGenerateBody
import de.tsschulz.tt_tagebuch.shared.api.models.BillingGenerateEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingHoursPreviewEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingRunsEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingSettingsEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingTemplatesEnvelope
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.forms.MultiPartFormDataContent

View File

@@ -1,7 +1,7 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.ClubCalendarHolidaysEnvelope
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter

View File

@@ -1,12 +1,12 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.ClickTtAccountEnvelope
import de.tt_tagebuch.shared.api.models.ClickTtAccountSaveResponse
import de.tt_tagebuch.shared.api.models.ClickTtAccountStatusDto
import de.tt_tagebuch.shared.api.models.ClickTtAccountUpsertBody
import de.tt_tagebuch.shared.api.models.ClickTtVerifyBody
import de.tt_tagebuch.shared.api.models.ClickTtVerifyResponseDto
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountSaveResponse
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountStatusDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtAccountUpsertBody
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtVerifyBody
import de.tsschulz.tt_tagebuch.shared.api.models.ClickTtVerifyResponseDto
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.ClubAccessDecisionBody
import de.tt_tagebuch.shared.api.models.PendingUserClubJoinDto
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.ClubAccessDecisionBody
import de.tsschulz.tt_tagebuch.shared.api.models.PendingUserClubJoinDto
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.post

View File

@@ -1,12 +1,12 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tt_tagebuch.shared.api.models.ClubTeamCreateBody
import de.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tt_tagebuch.shared.api.models.ClubTeamLineupRowDto
import de.tt_tagebuch.shared.api.models.ClubTeamUpdateBody
import de.tt_tagebuch.shared.api.models.TeamLineupUpdateBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.ClubLeagueOptionDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamCreateBody
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamLineupRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamUpdateBody
import de.tsschulz.tt_tagebuch.shared.api.models.TeamLineupUpdateBody
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.Club
import de.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.Club
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.post

View File

@@ -1,21 +1,21 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.AddDiaryNoteRequest
import de.tt_tagebuch.shared.api.models.AddFreeformActivityBody
import de.tt_tagebuch.shared.api.models.AddDiaryPlanGroupActivityRequest
import de.tt_tagebuch.shared.api.models.CreateDiaryDateRequest
import de.tt_tagebuch.shared.api.models.CreateDiaryPlanActivityRequest
import de.tt_tagebuch.shared.api.models.DiaryDate
import de.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tt_tagebuch.shared.api.models.DiaryNote
import de.tt_tagebuch.shared.api.models.DiaryTag
import de.tt_tagebuch.shared.api.models.LinkDiaryTagRequest
import de.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityOrderRequest
import de.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityRequest
import de.tt_tagebuch.shared.api.models.UpdateDiaryTimesRequest
import de.tt_tagebuch.shared.api.models.UpdateNestedPlanGroupActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryNoteRequest
import de.tsschulz.tt_tagebuch.shared.api.models.AddFreeformActivityBody
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryPlanGroupActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.CreateDiaryDateRequest
import de.tsschulz.tt_tagebuch.shared.api.models.CreateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDate
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryNote
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryTag
import de.tsschulz.tt_tagebuch.shared.api.models.LinkDiaryTagRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityOrderRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryTimesRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateNestedPlanGroupActivityRequest
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.AddMemberActivityParticipantsBody
import de.tt_tagebuch.shared.api.models.DiaryMemberActivityLink
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.AddMemberActivityParticipantsBody
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberActivityLink
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,10 +1,10 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.AddDiaryMemberNoteBody
import de.tt_tagebuch.shared.api.models.DiaryMemberNoteDto
import de.tt_tagebuch.shared.api.models.DiaryMemberTagLinkDto
import de.tt_tagebuch.shared.api.models.DiaryMemberTagMutationBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryMemberNoteBody
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberNoteDto
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberTagLinkDto
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryMemberTagMutationBody
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,10 +1,10 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.CreateTrainingGroupBody
import de.tt_tagebuch.shared.api.models.DeleteTrainingGroupBody
import de.tt_tagebuch.shared.api.models.DiaryPlanGroup
import de.tt_tagebuch.shared.api.models.UpdateTrainingGroupBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.CreateTrainingGroupBody
import de.tsschulz.tt_tagebuch.shared.api.models.DeleteTrainingGroupBody
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryPlanGroup
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTrainingGroupBody
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

View File

@@ -1,10 +1,10 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.LeaguePlayerStatDto
import de.tt_tagebuch.shared.api.models.LeagueTableRowDto
import de.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tt_tagebuch.shared.api.models.UpdateMatchPlayersBody
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.LeaguePlayerStatDto
import de.tsschulz.tt_tagebuch.shared.api.models.LeagueTableRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.ScheduleMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateMatchPlayersBody
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.MemberActivityStatDto
import de.tt_tagebuch.shared.api.models.MemberLastParticipationDto
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.MemberActivityStatDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberLastParticipationDto
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter

View File

@@ -1,8 +1,8 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tt_tagebuch.shared.api.models.MemberGroupPhotoListResponse
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberGroupPhotoListResponse
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.forms.MultiPartFormDataContent

View File

@@ -1,10 +1,10 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.MemberOrderCreateBody
import de.tt_tagebuch.shared.api.models.MemberOrderEnvelope
import de.tt_tagebuch.shared.api.models.MemberOrderPatchBody
import de.tt_tagebuch.shared.api.models.MemberOrdersListEnvelope
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrderCreateBody
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrderEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrderPatchBody
import de.tsschulz.tt_tagebuch.shared.api.models.MemberOrdersListEnvelope
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.patch

View File

@@ -1,9 +1,9 @@
package de.tt_tagebuch.shared.api
package de.tsschulz.tt_tagebuch.shared.api
import de.tt_tagebuch.shared.api.http.ApiException
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tt_tagebuch.shared.api.models.MemberTransferConfigSaveBody
import de.tsschulz.tt_tagebuch.shared.api.http.ApiException
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigSaveBody
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get

Some files were not shown because too many files have changed in this diff Show More