feat(Tournament): add official tournament participation feature
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 43s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 43s
- Introduced functionality to load and display official tournament participation events in the CalendarView. - Updated the API client to fetch official tournament data, enhancing the event management capabilities. - Added new UI elements to represent official tournaments, including visual indicators and event details. - Enhanced the ClubManager to support fetching and managing official tournament data. - Updated the mobile app's TODO list to reflect progress on tournament-related features.
This commit is contained in:
@@ -2,9 +2,11 @@ package de.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 io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.put
|
||||
import io.ktor.client.request.setBody
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -28,6 +30,12 @@ class ClubsApi(
|
||||
return client.http.get("/api/clubs/$clubId").body()
|
||||
}
|
||||
|
||||
suspend fun updateClubSettings(clubId: Int, body: UpdateClubSettingsBody) {
|
||||
client.http.put("/api/clubs/$clubId/settings") {
|
||||
setBody(body)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun requestAccess(clubId: Int) {
|
||||
client.http.get("/api/clubs/request/$clubId")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.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 io.ktor.client.call.body
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
|
||||
class MemberTransferConfigApi(
|
||||
private val client: AuthedHttpClient,
|
||||
) {
|
||||
suspend fun get(clubId: Int): MemberTransferConfigEnvelope? {
|
||||
return try {
|
||||
client.http.get("/api/member-transfer-config/$clubId").body()
|
||||
} catch (e: ApiException) {
|
||||
if (e.statusCode == 404) null else throw e
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun save(clubId: Int, body: MemberTransferConfigSaveBody): MemberTransferConfigEnvelope {
|
||||
return client.http.post("/api/member-transfer-config/$clubId") {
|
||||
setBody(body)
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun delete(clubId: Int): MemberTransferConfigEnvelope {
|
||||
return client.http.delete("/api/member-transfer-config/$clubId").body()
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,13 @@ package de.tt_tagebuch.shared.api
|
||||
|
||||
import de.tt_tagebuch.shared.api.http.AuthedHttpClient
|
||||
import de.tt_tagebuch.shared.api.models.PredefinedActivityDto
|
||||
import de.tt_tagebuch.shared.api.models.PredefinedActivityUpsertBody
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.put
|
||||
import io.ktor.client.request.setBody
|
||||
|
||||
class PredefinedActivitiesApi(
|
||||
private val client: AuthedHttpClient,
|
||||
@@ -25,4 +29,16 @@ class PredefinedActivitiesApi(
|
||||
suspend fun getById(id: Int): PredefinedActivityDto {
|
||||
return client.http.get("/api/predefined-activities/$id").body()
|
||||
}
|
||||
|
||||
suspend fun create(body: PredefinedActivityUpsertBody): PredefinedActivityDto {
|
||||
return client.http.post("/api/predefined-activities") {
|
||||
setBody(body)
|
||||
}.body()
|
||||
}
|
||||
|
||||
suspend fun update(id: Int, body: PredefinedActivityUpsertBody): PredefinedActivityDto {
|
||||
return client.http.put("/api/predefined-activities/$id") {
|
||||
setBody(body)
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,26 @@ package de.tt_tagebuch.shared.api.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MemberDataQualityRequirements(
|
||||
val requireStreet: Boolean = true,
|
||||
val requirePostalCode: Boolean = true,
|
||||
val requireCity: Boolean = true,
|
||||
val requirePhone: Boolean = true,
|
||||
val requireEmail: Boolean = true,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UpdateClubSettingsBody(
|
||||
val greetingText: String? = null,
|
||||
val associationMemberNumber: String? = null,
|
||||
val countryCode: String? = null,
|
||||
val stateCode: String? = null,
|
||||
val myTischtennisFedNickname: String? = null,
|
||||
val autoFetchRankings: Boolean? = null,
|
||||
val memberDataQualityRequirements: MemberDataQualityRequirements? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Club(
|
||||
val id: Int,
|
||||
@@ -10,5 +30,8 @@ data class Club(
|
||||
val associationMemberNumber: String? = null,
|
||||
val myTischtennisFedNickname: String? = null,
|
||||
val autoFetchRankings: Boolean? = null,
|
||||
val countryCode: String? = null,
|
||||
val stateCode: String? = null,
|
||||
val memberDataQualityRequirements: MemberDataQualityRequirements? = null,
|
||||
)
|
||||
|
||||
|
||||
@@ -81,3 +81,23 @@ fun UserClubPermissions.canWriteTournaments(): Boolean {
|
||||
if (isOwner) return true
|
||||
return permissions.boolAt("tournaments", "write")
|
||||
}
|
||||
|
||||
fun UserClubPermissions.canReadClubSettings(): Boolean {
|
||||
if (isOwner) return true
|
||||
return permissions.boolAt("settings", "read")
|
||||
}
|
||||
|
||||
fun UserClubPermissions.canWriteClubSettings(): Boolean {
|
||||
if (isOwner) return true
|
||||
return permissions.boolAt("settings", "write")
|
||||
}
|
||||
|
||||
fun UserClubPermissions.canReadPredefinedActivities(): Boolean {
|
||||
if (isOwner) return true
|
||||
return permissions.boolAt("predefined_activities", "read")
|
||||
}
|
||||
|
||||
fun UserClubPermissions.canWritePredefinedActivities(): Boolean {
|
||||
if (isOwner) return true
|
||||
return permissions.boolAt("predefined_activities", "write")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.tt_tagebuch.shared.api.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
@Serializable
|
||||
data class MemberTransferLoginCredentialsDto(
|
||||
val username: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MemberTransferConfigDto(
|
||||
val id: Int? = null,
|
||||
val clubId: Int? = null,
|
||||
val server: String? = null,
|
||||
val loginEndpoint: String? = null,
|
||||
val loginFormat: String? = null,
|
||||
val loginCredentials: MemberTransferLoginCredentialsDto? = null,
|
||||
val transferEndpoint: String? = null,
|
||||
val transferMethod: String? = null,
|
||||
val transferFormat: String? = null,
|
||||
val transferTemplate: String? = null,
|
||||
val useBulkMode: Boolean? = null,
|
||||
val bulkWrapperTemplate: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MemberTransferConfigEnvelope(
|
||||
val success: Boolean = false,
|
||||
val config: MemberTransferConfigDto? = null,
|
||||
val message: String? = null,
|
||||
val error: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MemberTransferConfigSaveBody(
|
||||
val server: String,
|
||||
val loginEndpoint: String? = null,
|
||||
val loginFormat: String = "json",
|
||||
val loginCredentials: JsonObject? = null,
|
||||
val transferEndpoint: String,
|
||||
val transferMethod: String = "POST",
|
||||
val transferFormat: String = "json",
|
||||
val transferTemplate: String,
|
||||
val useBulkMode: Boolean = false,
|
||||
val bulkWrapperTemplate: String? = null,
|
||||
)
|
||||
@@ -13,6 +13,18 @@ data class PredefinedActivityDto(
|
||||
val excludeFromStats: Boolean? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PredefinedActivityUpsertBody(
|
||||
val name: String? = null,
|
||||
val code: String? = null,
|
||||
val description: String? = null,
|
||||
val duration: Int? = null,
|
||||
val durationText: String? = null,
|
||||
val imageLink: String? = null,
|
||||
val drawingData: String? = null,
|
||||
val excludeFromStats: Boolean? = null,
|
||||
)
|
||||
|
||||
fun PredefinedActivityDto.displayLabel(): String {
|
||||
val n = name?.trim().orEmpty()
|
||||
if (n.isNotEmpty()) return n
|
||||
|
||||
@@ -3,6 +3,7 @@ package de.tt_tagebuch.shared.state
|
||||
import de.tt_tagebuch.shared.api.ClubsApi
|
||||
import de.tt_tagebuch.shared.api.PermissionsApi
|
||||
import de.tt_tagebuch.shared.api.models.Club
|
||||
import de.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -50,6 +51,10 @@ class ClubManager(
|
||||
return clubsApi.getClub(clubId)
|
||||
}
|
||||
|
||||
suspend fun updateClubSettings(clubId: Int, body: UpdateClubSettingsBody) {
|
||||
clubsApi.updateClubSettings(clubId, body)
|
||||
}
|
||||
|
||||
suspend fun selectClub(clubId: Int) {
|
||||
_state.value = _state.value.copy(isLoading = true, error = null)
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user