chore: erweitere Pferd-, Funktionär- und Reiter-Modelle um neue Felder, verbessere UI und Suche

Signed-off-by: StefanMoCoAt <stefan.mo.co@gmail.com>
This commit is contained in:
2026-04-21 13:47:35 +02:00
parent 574f8c470c
commit 2662d4e82e
10 changed files with 399 additions and 196 deletions
@@ -18,7 +18,9 @@ data class Reiter(
val geburtsdatum: String? = null,
val email: String? = null,
val telefon: String? = null,
val verein: String? = null
val verein: String? = null,
val nation: String? = "AUT",
val bundesland: String? = null
) {
val name: String get() = "$vorname $nachname"
}
@@ -1,10 +1,16 @@
package at.mocode.frontend.features.reiter.presentation
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
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 at.mocode.frontend.core.designsystem.components.*
import at.mocode.frontend.core.designsystem.models.PlaceholderContent
@@ -41,14 +47,20 @@ fun ReiterScreen(
onEmailChange = viewModel::onEditEmailChange,
onTelefonChange = viewModel::onEditTelefonChange,
onVereinChange = viewModel::onEditVereinChange,
onNationChange = viewModel::onEditNationChange,
onBundeslandChange = viewModel::onEditBundeslandChange,
onSave = viewModel::onSave,
onCancel = viewModel::onCancel
)
} else if (uiState.selectedReiter != null) {
ReiterCard(
reiter = uiState.selectedReiter,
onEdit = { viewModel.selectReiter(uiState.selectedReiter) }
)
Column(Modifier.fillMaxSize()) {
ReiterCardPreview(reiter = uiState.selectedReiter)
Spacer(Modifier.height(16.dp))
ReiterCard(
reiter = uiState.selectedReiter,
onEdit = { viewModel.selectReiter(uiState.selectedReiter) }
)
}
} else {
PlaceholderContent(
title = "Kein Reiter ausgewählt",
@@ -122,57 +134,9 @@ fun ReiterCard(
horizontalAlignment = Alignment.CenterHorizontally
) {
Card(
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
)
modifier = Modifier.fillMaxWidth().wrapContentHeight()
) {
Column(modifier = Modifier.padding(24.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Surface(
modifier = Modifier.size(48.dp),
shape = MaterialTheme.shapes.medium,
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
) {
Box(contentAlignment = Alignment.Center) {
Text(
text = (reiter.vorname.take(1) + reiter.nachname.take(1)).uppercase(),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary
)
}
}
Spacer(Modifier.width(16.dp))
Column {
Text(
reiter.name,
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onSurface
)
Text(
"ÖPS-Nr: ${reiter.oepsNummer ?: "-"}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
MsStatusBadge(
text = reiter.status.label,
containerColor = reiter.status.color.copy(alpha = 0.1f),
contentColor = reiter.status.color
)
}
Spacer(Modifier.height(24.dp))
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
Spacer(Modifier.height(24.dp))
Row(modifier = Modifier.fillMaxWidth()) {
ReiterDetailItem(label = "Lizenz", value = reiter.lizenz.label, modifier = Modifier.weight(1f))
ReiterDetailItem(label = "Hauptsparte", value = reiter.sparte.label, modifier = Modifier.weight(1f))
@@ -192,6 +156,13 @@ fun ReiterCard(
ReiterDetailItem(label = "FEI-ID", value = reiter.feiId ?: "-", modifier = Modifier.weight(1f))
}
Spacer(Modifier.height(16.dp))
Row(modifier = Modifier.fillMaxWidth()) {
ReiterDetailItem(label = "Nation", value = reiter.nation ?: "-", modifier = Modifier.weight(1f))
ReiterDetailItem(label = "Bundesland", value = reiter.bundesland ?: "-", modifier = Modifier.weight(1f))
}
Spacer(Modifier.height(32.dp))
MsButton(
@@ -204,6 +175,50 @@ fun ReiterCard(
}
}
@Composable
fun ReiterCardPreview(reiter: Reiter) {
Card(
modifier = Modifier.fillMaxWidth().padding(16.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
Box(
modifier = Modifier
.size(64.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) {
Icon(Icons.Default.Person, null, modifier = Modifier.size(32.dp), tint = MaterialTheme.colorScheme.primary)
}
Column(modifier = Modifier.weight(1f)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Text(reiter.name, style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold)
MsStatusBadge(
text = reiter.status.label,
containerColor = reiter.status.color.copy(alpha = 0.1f),
contentColor = reiter.status.color
)
}
Text(
text = buildString {
append("ÖPS: ${reiter.oepsNummer ?: "-"}")
if (!reiter.nation.isNullOrBlank()) append(" | ${reiter.nation}")
if (!reiter.bundesland.isNullOrBlank()) append(" (${reiter.bundesland})")
},
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
@Composable
private fun ReiterDetailItem(label: String, value: String, modifier: Modifier = Modifier) {
Column(modifier = modifier) {
@@ -225,17 +240,25 @@ private fun ReiterEditorContent(
onEmailChange: (String) -> Unit,
onTelefonChange: (String) -> Unit,
onVereinChange: (String) -> Unit,
onNationChange: (String) -> Unit,
onBundeslandChange: (String) -> Unit,
onSave: () -> Unit,
onCancel: () -> Unit
) {
Column(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
MsActionToolbar(
title = "Reiter Details",
title = if (uiState.selectedReiter == null) "Reiter anlegen" else "Reiter Details",
onSave = onSave,
onCancel = onCancel
)
Spacer(Modifier.height(24.dp))
Spacer(Modifier.height(16.dp))
// Preview in Editor
if (uiState.selectedReiter != null) {
ReiterCardPreview(reiter = uiState.selectedReiter)
Spacer(Modifier.height(16.dp))
}
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
MsTextField(
@@ -294,6 +317,25 @@ private fun ReiterEditorContent(
Spacer(Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
MsTextField(
value = uiState.editNation,
onValueChange = onNationChange,
label = "Nation",
modifier = Modifier.weight(1f),
compact = true
)
MsTextField(
value = uiState.editBundesland,
onValueChange = onBundeslandChange,
label = "Bundesland",
modifier = Modifier.weight(1f),
compact = true
)
}
Spacer(Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
MsTextField(
value = uiState.editEmail,
@@ -29,7 +29,9 @@ data class ReiterUiState(
val editGeburtsdatum: String = "",
val editEmail: String = "",
val editTelefon: String = "",
val editVerein: String = ""
val editVerein: String = "",
val editNation: String = "AUT",
val editBundesland: String = ""
)
/**
@@ -77,7 +79,9 @@ open class ReiterViewModel(initialLoad: Boolean = true) : ViewModel() {
editGeburtsdatum = reiter.geburtsdatum ?: "",
editEmail = reiter.email ?: "",
editTelefon = reiter.telefon ?: "",
editVerein = reiter.verein ?: ""
editVerein = reiter.verein ?: "",
editNation = reiter.nation ?: "AUT",
editBundesland = reiter.bundesland ?: ""
)
}
@@ -96,7 +100,9 @@ open class ReiterViewModel(initialLoad: Boolean = true) : ViewModel() {
editGeburtsdatum = "",
editEmail = "",
editTelefon = "",
editVerein = ""
editVerein = "",
editNation = "AUT",
editBundesland = ""
)
}
@@ -106,6 +112,8 @@ open class ReiterViewModel(initialLoad: Boolean = true) : ViewModel() {
fun onEditEmailChange(value: String) { uiState = uiState.copy(editEmail = value) }
fun onEditTelefonChange(value: String) { uiState = uiState.copy(editTelefon = value) }
fun onEditVereinChange(value: String) { uiState = uiState.copy(editVerein = value) }
fun onEditNationChange(value: String) { uiState = uiState.copy(editNation = value) }
fun onEditBundeslandChange(value: String) { uiState = uiState.copy(editBundesland = value) }
fun onEditVornameChange(value: String) {
uiState = uiState.copy(editVorname = value)