feat(TeamManagement): enhance team management features and introduce planning phase for Android
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
- Updated TODO.md to outline the new planning phase for Android, aligning it with existing web functionalities for team management. - Refactored AppDependencies to include TeamDocumentsApi, improving API integration for team-related documents. - Replaced MobileTeamsScreen with TeamManagementScreen in ClubStammdatenScreens for better navigation. - Enhanced TeamManagementScreen with improved state management and UI updates for team editing and data loading. - Added new API methods in ClubTeamsApi for managing team lineups, supporting better team planning and organization. - Introduced new methods in MatchesApi and MyTischtennisApi to enhance match and team data handling.
This commit is contained in:
@@ -5,6 +5,7 @@ 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 io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
@@ -35,4 +36,10 @@ class ApiLogsApi(
|
||||
val env = client.http.get("/api/logs/$id").body<ApiLogDetailEnvelopeDto>()
|
||||
return env.data
|
||||
}
|
||||
|
||||
suspend fun getSchedulerLastExecutions(clubId: Int? = null): SchedulerLastExecutionsEnvelopeDto {
|
||||
return client.http.get("/api/logs/scheduler/last-executions") {
|
||||
clubId?.let { parameter("clubId", it) }
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ 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 io.ktor.client.call.body
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
@@ -47,4 +49,16 @@ class ClubTeamsApi(
|
||||
suspend fun deleteClubTeam(clubTeamId: Int) {
|
||||
client.http.delete("/api/club-teams/$clubTeamId")
|
||||
}
|
||||
|
||||
suspend fun getLineup(clubTeamId: Int, half: String): List<ClubTeamLineupRowDto> {
|
||||
return client.http.get("/api/club-teams/$clubTeamId/lineup") {
|
||||
parameter("half", half)
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun updateLineup(clubTeamId: Int, body: TeamLineupUpdateBody): List<ClubTeamLineupRowDto> {
|
||||
return client.http.put("/api/club-teams/$clubTeamId/lineup") {
|
||||
setBody(body)
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.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
|
||||
@@ -29,6 +30,12 @@ class MatchesApi(
|
||||
return client.http.get("/api/matches/leagues/$clubId/table/$leagueId").body()
|
||||
}
|
||||
|
||||
suspend fun getLeaguePlayerStats(clubId: Int, leagueId: Int, seasonId: Int? = null): List<LeaguePlayerStatDto> {
|
||||
return client.http.get("/api/matches/leagues/$clubId/stats/$leagueId") {
|
||||
seasonId?.let { parameter("seasonid", it) }
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun updateMatchPlayers(matchId: Int, body: UpdateMatchPlayersBody) {
|
||||
client.http.patch("/api/matches/$matchId/players") {
|
||||
setBody(body)
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package de.tt_tagebuch.shared.api
|
||||
|
||||
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
|
||||
import de.tt_tagebuch.shared.api.models.MyTtConfigureLeagueBody
|
||||
import de.tt_tagebuch.shared.api.models.MyTtConfigureTeamBody
|
||||
import de.tt_tagebuch.shared.api.models.MyTtFetchJobEnvelopeDto
|
||||
import de.tt_tagebuch.shared.api.models.MyTtFetchJobStartDto
|
||||
import de.tt_tagebuch.shared.api.models.MyTtFetchTeamDataBody
|
||||
import de.tt_tagebuch.shared.api.models.MyTtParseUrlBody
|
||||
import de.tt_tagebuch.shared.api.models.MyTischtennisAccountEnvelope
|
||||
import de.tt_tagebuch.shared.api.models.MyTischtennisAccountSaveResponse
|
||||
import de.tt_tagebuch.shared.api.models.MyTischtennisAccountUpsertBody
|
||||
@@ -46,4 +52,31 @@ class MyTischtennisApi(
|
||||
suspend fun deleteAccount() {
|
||||
client.http.delete("/api/mytischtennis/account")
|
||||
}
|
||||
|
||||
suspend fun parseUrl(url: String): JsonObject =
|
||||
client.http.post("/api/mytischtennis/parse-url") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(MyTtParseUrlBody(url))
|
||||
}.body()
|
||||
|
||||
suspend fun configureTeam(body: MyTtConfigureTeamBody): JsonObject =
|
||||
client.http.post("/api/mytischtennis/configure-team") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(body)
|
||||
}.body()
|
||||
|
||||
suspend fun configureLeague(body: MyTtConfigureLeagueBody): JsonObject =
|
||||
client.http.post("/api/mytischtennis/configure-league") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(body)
|
||||
}.body()
|
||||
|
||||
suspend fun startFetchTeamDataJob(clubTeamId: Int): MyTtFetchJobStartDto =
|
||||
client.http.post("/api/mytischtennis/fetch-team-data/async") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(MyTtFetchTeamDataBody(clubTeamId))
|
||||
}.body()
|
||||
|
||||
suspend fun getFetchTeamDataJob(jobId: String): MyTtFetchJobEnvelopeDto =
|
||||
client.http.get("/api/mytischtennis/fetch-team-data/jobs/$jobId").body()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package de.tt_tagebuch.shared.api
|
||||
|
||||
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
|
||||
import de.tt_tagebuch.shared.api.models.TeamDocumentDto
|
||||
import de.tt_tagebuch.shared.api.models.TeamDocumentParseEnvelopeDto
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.contentType
|
||||
|
||||
class TeamDocumentsApi(
|
||||
private val client: AuthedHttpClient,
|
||||
) {
|
||||
suspend fun listByClubTeam(clubTeamId: Int): List<TeamDocumentDto> {
|
||||
return client.http.get("/api/team-documents/club-team/$clubTeamId").body()
|
||||
}
|
||||
|
||||
suspend fun upload(
|
||||
clubTeamId: Int,
|
||||
documentType: String,
|
||||
bytes: ByteArray,
|
||||
fileName: String,
|
||||
mimeType: String,
|
||||
): TeamDocumentDto {
|
||||
return client.http.post("/api/team-documents/club-team/$clubTeamId/upload") {
|
||||
contentType(ContentType.MultiPart.FormData)
|
||||
setBody(
|
||||
MultiPartFormDataContent(
|
||||
formData {
|
||||
append("documentType", documentType)
|
||||
append(
|
||||
"document",
|
||||
bytes,
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, mimeType)
|
||||
append(HttpHeaders.ContentDisposition, "filename=\"$fileName\"")
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun parse(documentId: Int, leagueId: Int): TeamDocumentParseEnvelopeDto {
|
||||
return client.http.post("/api/team-documents/$documentId/parse") {
|
||||
parameter("leagueid", leagueId)
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun download(documentId: Int): ByteArray {
|
||||
return client.http.get("/api/team-documents/$documentId/download").body()
|
||||
}
|
||||
|
||||
suspend fun delete(documentId: Int) {
|
||||
client.http.delete("/api/team-documents/$documentId")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package de.tt_tagebuch.shared.api.models
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
@Serializable
|
||||
data class LeaguePlayerStatDto(
|
||||
val memberId: Int,
|
||||
val firstName: String = "",
|
||||
val lastName: String = "",
|
||||
val totalSeason: Int = 0,
|
||||
val totalFirstHalf: Int = 0,
|
||||
val totalSecondHalf: Int = 0,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ClubTeamLineupRowDto(
|
||||
val id: Int? = null,
|
||||
val clubTeamId: Int? = null,
|
||||
val memberId: Int,
|
||||
val lineupHalf: String? = null,
|
||||
val position: Int = 0,
|
||||
val member: Member? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamLineupAssignmentItem(
|
||||
val memberId: Int,
|
||||
val position: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamLineupUpdateBody(
|
||||
val assignments: List<TeamLineupAssignmentItem>,
|
||||
val lineupHalf: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamDocumentDto(
|
||||
val id: Int,
|
||||
val fileName: String = "",
|
||||
val originalFileName: String = "",
|
||||
val documentType: String = "",
|
||||
val clubTeamId: Int? = null,
|
||||
val createdAt: String? = null,
|
||||
val mimeType: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamDocumentParseResultDto(
|
||||
val matchesFound: Int = 0,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamDocumentSaveResultDto(
|
||||
val created: Int = 0,
|
||||
val updated: Int = 0,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TeamDocumentParseEnvelopeDto(
|
||||
val parseResult: TeamDocumentParseResultDto? = null,
|
||||
val saveResult: TeamDocumentSaveResultDto? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SchedulerLastExecutionsEnvelopeDto(
|
||||
val success: Boolean = false,
|
||||
val data: SchedulerLastExecutionsDataDto? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SchedulerLastExecutionsDataDto(
|
||||
@SerialName("rating_updates")
|
||||
val ratingUpdates: SchedulerJobBlockDto? = null,
|
||||
@SerialName("match_results")
|
||||
val matchResults: SchedulerJobBlockDto? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SchedulerJobBlockDto(
|
||||
val lastRun: String? = null,
|
||||
val success: Boolean? = null,
|
||||
val executionTime: Int? = null,
|
||||
val updatedCount: Int? = null,
|
||||
val fetchedCount: Int? = null,
|
||||
val errorMessage: String? = null,
|
||||
val teamDetails: List<SchedulerTeamDetailDto> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SchedulerTeamDetailDto(
|
||||
val clubTeamId: Int = 0,
|
||||
val teamName: String? = null,
|
||||
val success: Boolean = false,
|
||||
val lastRun: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyTtParseUrlBody(val url: String)
|
||||
|
||||
@Serializable
|
||||
data class MyTtConfigureTeamBody(
|
||||
val url: String,
|
||||
val clubTeamId: Int,
|
||||
val createLeague: Boolean? = null,
|
||||
val createSeason: Boolean? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyTtConfigureLeagueBody(
|
||||
val url: String,
|
||||
val createSeason: Boolean? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyTtFetchTeamDataBody(val clubTeamId: Int)
|
||||
|
||||
@Serializable
|
||||
data class MyTtFetchJobStartDto(
|
||||
val success: Boolean = false,
|
||||
val jobId: String? = null,
|
||||
val status: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyTtFetchJobEnvelopeDto(
|
||||
val success: Boolean = false,
|
||||
val job: MyTtFetchJobDto? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyTtFetchJobDto(
|
||||
val jobId: String? = null,
|
||||
val status: String? = null,
|
||||
val result: JsonObject? = null,
|
||||
val error: String? = null,
|
||||
)
|
||||
Reference in New Issue
Block a user