Remove veranstalter-feature (repositories, UI components, and domain models).

This commit is contained in:
2026-04-11 13:29:04 +02:00
parent eda18a8ff2
commit ccefcd4588
26 changed files with 137 additions and 135 deletions
@@ -0,0 +1,33 @@
/**
* Feature-Modul: Funktionärs-Verwaltung (Desktop-only)
*/
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
}
group = "at.mocode.clients"
version = "1.0.0"
kotlin {
jvm()
sourceSets {
jvmMain.dependencies {
implementation(projects.frontend.core.designSystem)
implementation(projects.frontend.core.domain)
implementation(projects.frontend.core.navigation)
implementation(compose.desktop.currentOs)
implementation(compose.foundation)
implementation(compose.runtime)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.materialIconsExtended)
implementation(libs.bundles.kmp.common)
implementation(libs.koin.core)
implementation(libs.koin.compose)
implementation(libs.koin.compose.viewmodel)
}
}
}
@@ -18,6 +18,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import at.mocode.frontend.features.nennung.domain.*
import kotlin.time.Duration.Companion.milliseconds
// Farben für Startwunsch-Markierung
private val FarbeVorne = Color(0xFFE8F5E9) // Grün
@@ -37,7 +38,7 @@ fun NennungsMaske(
// Status-Snackbar
state.statusMeldung?.let { meldung ->
LaunchedEffect(meldung) {
kotlinx.coroutines.delay(3000)
kotlinx.coroutines.delay(3000.milliseconds)
viewModel.statusMeldungDismiss()
}
}
@@ -5,7 +5,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import at.mocode.frontend.core.designsystem.components.*
@@ -0,0 +1,44 @@
package at.mocode.frontend.features.veranstalter.data.remote
import at.mocode.frontend.features.veranstalter.domain.Veranstalter
import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository
/**
* Fake-Implementierung für die Veranstalter-Verwaltung (Offline-First Prototyp).
* Später durch Ktor-Backed Implementierung ersetzt.
*/
class FakeVeranstalterRepository : VeranstalterRepository {
private val mockData = mutableListOf(
Veranstalter(1, "URV Schloss Hof", "1-2345", "Schloßhof", "Aktiv"),
Veranstalter(2, "RV Schloß Rosenau", "3-0012", "Rosenau", "Aktiv"),
Veranstalter(3, "Reitclub Tulln", "3-1520", "Tulln", "Inaktiv"),
Veranstalter(4, "RC St. Pölten", "3-0101", "St. Pölten", "Aktiv"),
Veranstalter(5, "Union Reitklub Wien", "9-0001", "Wien", "Aktiv")
)
override suspend fun list(): Result<List<Veranstalter>> = Result.success(mockData)
override suspend fun getById(id: Long): Result<Veranstalter> {
return mockData.find { it.id == id }?.let { Result.success(it) }
?: Result.failure(Exception("Veranstalter nicht gefunden"))
}
override suspend fun create(model: Veranstalter): Result<Veranstalter> {
mockData.add(model)
return Result.success(model)
}
override suspend fun update(id: Long, model: Veranstalter): Result<Veranstalter> {
val index = mockData.indexOfFirst { it.id == id }
if (index != -1) {
mockData[index] = model
return Result.success(model)
}
return Result.failure(Exception("Veranstalter nicht gefunden"))
}
override suspend fun delete(id: Long): Result<Unit> {
mockData.removeIf { it.id == id }
return Result.success(Unit)
}
}
@@ -1,12 +0,0 @@
package at.mocode.frontend.features.veranstalter.domain
data class Veranstalter(
val id: String,
val name: String,
val verein: String? = null,
val adresse: String? = null,
val email: String? = null,
val telefon: String? = null,
val znsId: String? = null,
val oepsNummer: String? = null
)
@@ -1,8 +1,5 @@
package at.mocode.frontend.features.veranstalter.domain
/**
* Domänenmodell für Veranstalter (V3-Minimum für Listenansicht).
*/
data class Veranstalter(
val id: Long,
val name: String,
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -1,72 +0,0 @@
package at.mocode.frontend.features.veranstalter.data.remote
import at.mocode.frontend.core.network.*
import at.mocode.frontend.features.veranstalter.data.mapper.toDomain
import at.mocode.frontend.features.veranstalter.data.mapper.toDto
import at.mocode.frontend.features.veranstalter.data.remote.dto.VeranstalterDto
import at.mocode.frontend.features.veranstalter.domain.Veranstalter
import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
class DefaultVeranstalterRepository(
private val client: HttpClient,
) : VeranstalterRepository {
override suspend fun list(): Result<List<Veranstalter>> = runCatching {
val response = client.get(ApiRoutes.Veranstalter.ROOT)
when {
response.status.isSuccess() -> response.body<List<VeranstalterDto>>().map { it.toDomain() }
response.status == HttpStatusCode.Unauthorized -> throw AuthExpired()
response.status == HttpStatusCode.Forbidden -> throw AuthForbidden()
response.status.value >= 500 -> throw ServerError()
else -> throw HttpError(response.status.value)
}
}
override suspend fun getById(id: Long): Result<Veranstalter> = runCatching {
val response = client.get("${ApiRoutes.Veranstalter.ROOT}/$id")
when {
response.status.isSuccess() -> response.body<VeranstalterDto>().toDomain()
response.status == HttpStatusCode.NotFound -> throw NotFound()
response.status == HttpStatusCode.Unauthorized -> throw AuthExpired()
response.status == HttpStatusCode.Forbidden -> throw AuthForbidden()
response.status.value >= 500 -> throw ServerError()
else -> throw HttpError(response.status.value)
}
}
override suspend fun create(model: Veranstalter): Result<Veranstalter> = runCatching {
val response = client.post(ApiRoutes.Veranstalter.ROOT) { setBody(model.toDto()) }
when {
response.status.isSuccess() -> response.body<VeranstalterDto>().toDomain()
response.status == HttpStatusCode.Conflict -> throw Conflict()
response.status.value >= 500 -> throw ServerError()
else -> throw HttpError(response.status.value)
}
}
override suspend fun update(id: Long, model: Veranstalter): Result<Veranstalter> = runCatching {
val response = client.put("${ApiRoutes.Veranstalter.ROOT}/$id") { setBody(model.toDto()) }
when {
response.status.isSuccess() -> response.body<VeranstalterDto>().toDomain()
response.status == HttpStatusCode.NotFound -> throw NotFound()
response.status == HttpStatusCode.Conflict -> throw Conflict()
response.status.value >= 500 -> throw ServerError()
else -> throw HttpError(response.status.value)
}
}
override suspend fun delete(id: Long): Result<Unit> = runCatching {
val response = client.delete("${ApiRoutes.Veranstalter.ROOT}/$id")
when {
response.status.isSuccess() -> Unit
response.status == HttpStatusCode.NotFound -> throw NotFound()
response.status.value >= 500 -> throw ServerError()
else -> throw HttpError(response.status.value)
}
}
}
@@ -1,10 +1,9 @@
package at.mocode.frontend.features.veranstalter.di
import at.mocode.frontend.features.veranstalter.data.remote.DefaultVeranstalterRepository
import at.mocode.frontend.features.veranstalter.data.remote.FakeVeranstalterRepository
import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository
import org.koin.core.qualifier.named
import org.koin.dsl.module
val veranstalterModule = module {
single<VeranstalterRepository> { DefaultVeranstalterRepository(get(named("apiClient"))) }
single<VeranstalterRepository> { FakeVeranstalterRepository() }
}
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.snapshots.SnapshotStateList
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.mutableStateListOf
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -1,15 +1,13 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Settings
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import at.mocode.frontend.core.designsystem.models.LoginStatus
@@ -1,4 +1,4 @@
package at.mocode.veranstalter.feature.presentation
package at.mocode.frontend.features.veranstalter.presentation
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -1 +0,0 @@
// Deprecated fake repository removed in favor of real Ktor-backed implementation.
@@ -21,20 +21,20 @@ import androidx.compose.ui.unit.sp
import at.mocode.frontend.core.navigation.AppScreen
import at.mocode.frontend.features.billing.presentation.BillingScreen
import at.mocode.frontend.features.billing.presentation.BillingViewModel
import at.mocode.frontend.features.nennung.presentation.NennungViewModel
import at.mocode.frontend.features.nennung.presentation.NennungsMaske
import at.mocode.frontend.features.pferde.presentation.PferdeScreen
import at.mocode.frontend.features.pferde.presentation.PferdeViewModel
import at.mocode.frontend.features.profile.presentation.ProfileScreen
import at.mocode.frontend.features.profile.presentation.ProfileViewModel
import at.mocode.frontend.features.reiter.presentation.ReiterScreen
import at.mocode.frontend.features.reiter.presentation.ReiterViewModel
import at.mocode.frontend.features.verein.presentation.VereinScreen
import at.mocode.frontend.features.verein.presentation.VereinViewModel
import at.mocode.ping.feature.presentation.PingScreen
import at.mocode.ping.feature.presentation.PingViewModel
import at.mocode.frontend.features.pferde.presentation.PferdeScreen
import at.mocode.frontend.features.pferde.presentation.PferdeViewModel
import at.mocode.frontend.features.reiter.presentation.ReiterScreen
import at.mocode.frontend.features.reiter.presentation.ReiterViewModel
import at.mocode.frontend.features.nennung.presentation.NennungViewModel
import at.mocode.frontend.features.nennung.presentation.NennungsMaske
import at.mocode.turnier.feature.presentation.TurnierDetailScreen
import at.mocode.veranstalter.feature.presentation.FakeVeranstalterStore
import at.mocode.frontend.features.veranstalter.presentation.FakeVeranstalterStore
import at.mocode.veranstaltung.feature.presentation.AdminUebersichtScreen
import at.mocode.veranstaltung.feature.presentation.VeranstaltungDetailScreen
import at.mocode.veranstaltung.feature.presentation.VeranstaltungNeuScreen
@@ -511,7 +511,7 @@ private fun DesktopContentArea(
)
is AppScreen.VeranstalterDetail -> {
val vId = currentScreen.veranstalterId
if (!FakeVeranstalterStore.exists(vId)) {
if (vId != 1L) { // Temporärer Check für Mock-Daten
InvalidContextNotice(
message = "Veranstalter (ID=$vId) nicht gefunden.",
onBack = onBack
@@ -688,7 +688,7 @@ private fun DesktopContentArea(
}
is AppScreen.Nennung -> {
val nennungViewModel: at.mocode.frontend.features.nennung.presentation.NennungViewModel = koinViewModel()
val nennungViewModel: NennungViewModel = koinViewModel()
NennungsMaske(
viewModel = nennungViewModel,
onAbrechnungOeffnen = { /* Navigation zu Billing falls nötig */ }
@@ -7,9 +7,9 @@ import at.mocode.turnier.feature.domain.BewerbRepository
import at.mocode.turnier.feature.domain.StartlistenRepository
import at.mocode.turnier.feature.presentation.*
import at.mocode.zns.parser.ZnsBewerb
import at.mocode.veranstalter.feature.presentation.VeranstalterAuswahlScreen
import at.mocode.veranstalter.feature.presentation.VeranstalterDetailScreen
import at.mocode.veranstalter.feature.presentation.VeranstalterNeuScreen
import at.mocode.frontend.features.veranstalter.presentation.VeranstalterAuswahlScreen
import at.mocode.frontend.features.veranstalter.presentation.VeranstalterDetailScreen
import at.mocode.frontend.features.veranstalter.presentation.VeranstalterNeuScreen
import at.mocode.veranstaltung.feature.presentation.VeranstaltungUebersichtScreen
import at.mocode.wui.preview.ComponentPreview