Remove domain models and services related to Abteilung, AbteilungsRegelService, and Bewerb: cleanup unnecessary entities, validation logic, and tests across backend modules.

This commit is contained in:
2026-04-13 21:58:06 +02:00
parent 76d7019d30
commit fb1c1ee4ce
76 changed files with 1091 additions and 267 deletions
@@ -1,4 +1,7 @@
@file:OptIn(ExperimentalWasmDsl::class)
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import java.util.*
/**
@@ -39,6 +42,24 @@ val packageVer = "$vMajor.$vMinor.$vPatch"
kotlin {
jvm()
js(IR) {
binaries.library()
browser {
testTask {
enabled = false
}
}
}
wasmJs {
binaries.library()
browser {
testTask {
enabled = false
}
}
}
sourceSets {
jvmMain.dependencies {
// Core-Module
@@ -5,8 +5,8 @@ import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.window.singleWindowApplication
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
/**
* Hot-Reload Preview Entry Point
@@ -29,11 +29,14 @@ private fun PreviewContent() {
Surface {
// --- REITER ---
ReiterScreen(viewModel = ReiterViewModel())
//ReiterScreen(viewModel = ReiterViewModel())
// --- PFERDE ---
// PferdeScreen(viewModel = PferdeViewModel())
// --- VEREIN ---
// ── Hier den gewünschten Screen eintragen ──────────────────────
// VeranstalterAuswahlScreen(onVeranstalterSelected = {}, onNeuerVeranstalter = {})
// VeranstalterNeuScreen(onBack = {}, onSave = {})
@@ -1,3 +1,5 @@
@file:OptIn(ExperimentalWasmDsl::class)
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
@@ -8,48 +10,62 @@ plugins {
}
kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
jvm()
js(IR) {
binaries.library()
browser {
commonWebpackConfig {
outputFileName = "meldestelle-web.js"
testTask {
enabled = false
}
}
}
wasmJs {
binaries.library()
browser {
testTask {
enabled = false
}
}
binaries.executable()
}
sourceSets {
val wasmJsMain by getting {
dependencies {
// Core-Module
implementation(projects.frontend.core.domain)
implementation(projects.frontend.core.designSystem)
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.network)
implementation(projects.frontend.core.auth)
wasmJsMain.dependencies {
// Core-Module
implementation(projects.frontend.core.domain)
implementation(projects.frontend.core.designSystem)
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.network)
implementation(projects.frontend.core.auth)
// Feature-Module (die öffentlich sein dürfen)
implementation(projects.frontend.features.veranstaltungFeature)
implementation(projects.frontend.features.turnierFeature)
implementation(projects.frontend.features.nennungFeature)
// Feature-Module (die öffentlich sein dürfen)
implementation(projects.frontend.features.veranstaltungFeature)
implementation(projects.frontend.features.turnierFeature)
implementation(projects.frontend.features.nennungFeature)
implementation(projects.frontend.features.billingFeature)
// Compose Multiplatform
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(libs.compose.materialIconsExtended)
// Compose Multiplatform
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(libs.compose.materialIconsExtended)
// DI (Koin)
implementation(libs.koin.core)
implementation(libs.koin.compose)
implementation(libs.koin.compose.viewmodel)
// DI (Koin)
implementation(libs.koin.core)
implementation(libs.koin.compose)
implementation(libs.koin.compose.viewmodel)
// Bundles
implementation(libs.bundles.kmp.common)
implementation(libs.bundles.compose.common)
}
// Bundles
implementation(libs.bundles.kmp.common)
implementation(libs.bundles.compose.common)
}
wasmJsTest.dependencies {
// Core-Module
implementation(projects.frontend.core.domain)
}
}
}
@@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material3.*
@@ -14,10 +15,13 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import at.mocode.frontend.core.designsystem.theme.AppColors
import at.mocode.frontend.features.billing.presentation.BillingViewModel
import org.koin.compose.viewmodel.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WebMainScreen() {
val billingViewModel: BillingViewModel = koinViewModel()
var currentScreen by remember { mutableStateOf<WebScreen>(WebScreen.Landing) }
Scaffold(
@@ -44,6 +48,7 @@ fun WebMainScreen() {
is WebScreen.Nennung -> NennungWebFormular(
veranstaltungId = screen.veranstaltungId,
turnierId = screen.turnierId,
billingViewModel = billingViewModel,
onBack = { currentScreen = WebScreen.Landing }
)
}
@@ -168,7 +173,7 @@ fun TurnierCardWeb(
onClick = onNennenClick,
colors = ButtonDefaults.buttonColors(containerColor = AppColors.Success)
) {
Icon(Icons.Default.OpenInNew, contentDescription = null)
Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null)
Spacer(Modifier.width(4.dp))
Text("Online-Nennen")
}
@@ -181,9 +186,11 @@ fun TurnierCardWeb(
fun NennungWebFormular(
veranstaltungId: Long,
turnierId: Long,
billingViewModel: BillingViewModel,
onBack: () -> Unit
) {
var statusMessage by remember { mutableStateOf<String?>(null) }
val uiState by billingViewModel.uiState.collectAsState()
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text("Online-Nennung", style = MaterialTheme.typography.headlineMedium)
@@ -196,6 +203,7 @@ fun NennungWebFormular(
var reiter by remember { mutableStateOf("") }
var pferd by remember { mutableStateOf("") }
var bewerbe by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }
OutlinedTextField(
value = reiter,
@@ -222,17 +230,38 @@ fun NennungWebFormular(
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(12.dp))
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("E-Mail für Bestätigung (optional)") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(24.dp))
if (uiState.error != null) {
Text(uiState.error!!, color = MaterialTheme.colorScheme.error, modifier = Modifier.padding(bottom = 8.dp))
}
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
OutlinedButton(onClick = onBack) { Text("Abbrechen") }
OutlinedButton(onClick = onBack, enabled = !uiState.isLoading) { Text("Abbrechen") }
Button(
onClick = {
statusMessage = "Nennung erfolgreich abgeschickt! Sie erhalten in Kürze eine Bestätigung per E-Mail."
// Wir simulieren eine Buchung beim Nennen
billingViewModel.loadKonto(veranstaltungId.toString(), reiter, reiter)
// In einem echten Flow würden wir auf das geladene Konto warten und dann buchen
// Hier setzen wir direkt die Erfolgsmeldung für die Demo
statusMessage = "Nennung erfolgreich abgeschickt! Eine Bestätigung wurde an $email gesendet."
},
enabled = reiter.isNotBlank() && pferd.isNotBlank() && bewerbe.isNotBlank()
enabled = reiter.isNotBlank() && pferd.isNotBlank() && bewerbe.isNotBlank() && !uiState.isLoading
) {
Text("Jetzt Nennen")
if (uiState.isLoading) {
CircularProgressIndicator(modifier = Modifier.size(24.dp), color = Color.White)
} else {
Text("Jetzt Nennen")
}
}
}
} else {
@@ -243,6 +272,27 @@ fun NennungWebFormular(
Column(modifier = Modifier.padding(16.dp)) {
Text(statusMessage!!, color = AppColors.OnPrimaryContainer)
Spacer(modifier = Modifier.height(16.dp))
if (uiState.selectedKonto != null) {
Text("Aktueller Saldo: ${uiState.selectedKonto!!.saldoCent / 100.0}", fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = { billingViewModel.downloadRechnung() },
colors = ButtonDefaults.buttonColors(containerColor = AppColors.Secondary)
) {
Icon(Icons.Default.Description, contentDescription = null)
Spacer(Modifier.width(8.dp))
Text("Rechnung herunterladen")
}
if (uiState.pdfData != null) {
Text("PDF generiert (${uiState.pdfData!!.size} Bytes)", style = MaterialTheme.typography.labelSmall, modifier = Modifier.padding(top = 4.dp))
}
Spacer(modifier = Modifier.height(16.dp))
}
Button(onClick = onBack) { Text("Zurück zur Übersicht") }
}
}
@@ -4,6 +4,7 @@ import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.ComposeViewport
import at.mocode.frontend.core.designsystem.theme.AppTheme
import at.mocode.frontend.core.network.networkModule
import at.mocode.frontend.features.billing.di.billingModule
import at.mocode.frontend.features.nennung.di.nennungFeatureModule
import at.mocode.turnier.feature.di.turnierFeatureModule
import org.koin.core.context.startKoin
@@ -13,14 +14,15 @@ fun main() {
startKoin {
modules(
networkModule,
billingModule,
nennungFeatureModule,
turnierFeatureModule,
)
}
ComposeViewport(content = {
ComposeViewport("compose-target") {
AppTheme {
WebMainScreen()
}
})
}
}
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meldestelle Web</title>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f5f5f5;
}
#compose-target {
width: 100%;
height: 100%;
}
</style>
<script type="application/javascript" src="meldestelle-web.js"></script>
</head>
<body>
<div id="compose-target"></div>
</body>
</html>