Add Reiter and Pferd edit dialogs, extend Masterdata repository with save and fetch methods, and integrate editors into Nennungen tab UI. Fix DI configuration and update previews.
This commit is contained in:
+6
@@ -37,7 +37,13 @@ data class Verein(
|
||||
|
||||
interface MasterdataRepository {
|
||||
suspend fun searchReiter(query: String): Result<List<Reiter>>
|
||||
suspend fun getReiter(id: String): Result<Reiter>
|
||||
suspend fun saveReiter(reiter: Reiter): Result<Reiter>
|
||||
|
||||
suspend fun searchPferde(query: String): Result<List<Pferd>>
|
||||
suspend fun getPferd(id: String): Result<Pferd>
|
||||
suspend fun savePferd(pferd: Pferd): Result<Pferd>
|
||||
|
||||
suspend fun searchFunktionaere(query: String): Result<List<Funktionaer>>
|
||||
suspend fun listVereine(): Result<List<Verein>>
|
||||
suspend fun getVereinById(id: String): Result<Verein>
|
||||
|
||||
+48
-2
@@ -14,6 +14,9 @@ data class NennungenState(
|
||||
val nennungen: List<Nennung> = emptyList(),
|
||||
val searchResultsReiter: List<Reiter> = emptyList(),
|
||||
val searchResultsPferde: List<Pferd> = emptyList(),
|
||||
val searchResultsFunktionaere: List<Funktionaer> = emptyList(),
|
||||
val selectedReiter: Reiter? = null,
|
||||
val selectedPferd: Pferd? = null,
|
||||
val errorMessage: String? = null
|
||||
)
|
||||
|
||||
@@ -43,7 +46,10 @@ class NennungViewModel(
|
||||
}
|
||||
|
||||
fun searchReiter(query: String) {
|
||||
if (query.length < 2) return
|
||||
if (query.length < 2) {
|
||||
_state.value = _state.value.copy(searchResultsReiter = emptyList())
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
masterdataRepo.searchReiter(query).onSuccess { list ->
|
||||
_state.value = _state.value.copy(searchResultsReiter = list)
|
||||
@@ -51,8 +57,24 @@ class NennungViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun selectReiter(reiter: Reiter?) {
|
||||
_state.value = _state.value.copy(selectedReiter = reiter)
|
||||
}
|
||||
|
||||
fun saveReiter(reiter: Reiter) {
|
||||
scope.launch {
|
||||
masterdataRepo.saveReiter(reiter).onSuccess {
|
||||
_state.value = _state.value.copy(selectedReiter = null)
|
||||
// Evtl. Suchen/Listen aktualisieren
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun searchPferde(query: String) {
|
||||
if (query.length < 2) return
|
||||
if (query.length < 2) {
|
||||
_state.value = _state.value.copy(searchResultsPferde = emptyList())
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
masterdataRepo.searchPferde(query).onSuccess { list ->
|
||||
_state.value = _state.value.copy(searchResultsPferde = list)
|
||||
@@ -60,6 +82,30 @@ class NennungViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun selectPferd(pferd: Pferd?) {
|
||||
_state.value = _state.value.copy(selectedPferd = pferd)
|
||||
}
|
||||
|
||||
fun savePferd(pferd: Pferd) {
|
||||
scope.launch {
|
||||
masterdataRepo.savePferd(pferd).onSuccess {
|
||||
_state.value = _state.value.copy(selectedPferd = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun searchFunktionaere(query: String) {
|
||||
if (query.length < 2) {
|
||||
_state.value = _state.value.copy(searchResultsFunktionaere = emptyList())
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
masterdataRepo.searchFunktionaere(query).onSuccess { list ->
|
||||
_state.value = _state.value.copy(searchResultsFunktionaere = list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun einreichen(bewerbId: String, abteilungId: String, reiterId: String, pferdId: String) {
|
||||
_state.value = _state.value.copy(isLoading = true)
|
||||
scope.launch {
|
||||
|
||||
+48
@@ -22,6 +22,30 @@ class DefaultMasterdataRepository(
|
||||
} else emptyList()
|
||||
}
|
||||
|
||||
override suspend fun getReiter(id: String): Result<Reiter> = runCatching {
|
||||
val response = client.get("${ApiRoutes.Masterdata.REITER}/$id")
|
||||
if (response.status.isSuccess()) {
|
||||
response.body<ReiterApiDto>().toDomain()
|
||||
} else throw Exception("Reiter nicht gefunden")
|
||||
}
|
||||
|
||||
override suspend fun saveReiter(reiter: Reiter): Result<Reiter> = runCatching {
|
||||
val response = client.put("${ApiRoutes.Masterdata.REITER}/${reiter.id}") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(ReiterApiDto(
|
||||
reiterId = reiter.id,
|
||||
vorname = reiter.vorname,
|
||||
nachname = reiter.nachname,
|
||||
satznummer = reiter.satznummer,
|
||||
vereinsName = reiter.verein,
|
||||
feiId = reiter.feiId
|
||||
))
|
||||
}
|
||||
if (response.status.isSuccess()) {
|
||||
response.body<ReiterApiDto>().toDomain()
|
||||
} else throw Exception("Fehler beim Speichern des Reiters")
|
||||
}
|
||||
|
||||
override suspend fun searchPferde(query: String): Result<List<Pferd>> = runCatching {
|
||||
val response = client.get("${ApiRoutes.Masterdata.PFERDE}/search") {
|
||||
parameter("q", query)
|
||||
@@ -31,6 +55,30 @@ class DefaultMasterdataRepository(
|
||||
} else emptyList()
|
||||
}
|
||||
|
||||
override suspend fun getPferd(id: String): Result<Pferd> = runCatching {
|
||||
val response = client.get("${ApiRoutes.Masterdata.PFERDE}/$id")
|
||||
if (response.status.isSuccess()) {
|
||||
response.body<HorseApiDto>().toDomain()
|
||||
} else throw Exception("Pferd nicht gefunden")
|
||||
}
|
||||
|
||||
override suspend fun savePferd(pferd: Pferd): Result<Pferd> = runCatching {
|
||||
val response = client.put("${ApiRoutes.Masterdata.PFERDE}/${pferd.id}") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(HorseApiDto(
|
||||
pferdId = pferd.id,
|
||||
pferdeName = pferd.name,
|
||||
lebensnummer = pferd.lebensnummer,
|
||||
geschlecht = "UNBEKANNT", // Fallback
|
||||
geburtsjahr = pferd.geburtsjahr,
|
||||
satznummer = pferd.oepsNummer
|
||||
))
|
||||
}
|
||||
if (response.status.isSuccess()) {
|
||||
response.body<HorseApiDto>().toDomain()
|
||||
} else throw Exception("Fehler beim Speichern des Pferdes")
|
||||
}
|
||||
|
||||
override suspend fun searchFunktionaere(query: String): Result<List<Funktionaer>> = runCatching {
|
||||
val response = client.get("${ApiRoutes.Masterdata.FUNKTIONAERE}/search") {
|
||||
parameter("q", query)
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package at.mocode.turnier.feature.presentation
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.unit.dp
|
||||
import at.mocode.turnier.feature.domain.Pferd
|
||||
import at.mocode.turnier.feature.domain.Reiter
|
||||
|
||||
@Composable
|
||||
fun ReiterEditDialog(
|
||||
reiter: Reiter,
|
||||
onDismiss: () -> Unit,
|
||||
onSave: (Reiter) -> Unit
|
||||
) {
|
||||
var vorname by remember { mutableStateOf(reiter.vorname) }
|
||||
var nachname by remember { mutableStateOf(reiter.nachname) }
|
||||
var oepsNummer by remember { mutableStateOf(reiter.oepsNummer ?: "") }
|
||||
var verein by remember { mutableStateOf(reiter.verein ?: "") }
|
||||
var feiId by remember { mutableStateOf(reiter.feiId ?: "") }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text("Reiter bearbeiten") },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
OutlinedTextField(value = vorname, onValueChange = { vorname = it }, label = { Text("Vorname") })
|
||||
OutlinedTextField(value = nachname, onValueChange = { nachname = it }, label = { Text("Nachname") })
|
||||
OutlinedTextField(value = oepsNummer, onValueChange = { oepsNummer = it }, label = { Text("OEPS-Nr.") })
|
||||
OutlinedTextField(value = verein, onValueChange = { verein = it }, label = { Text("Verein") })
|
||||
OutlinedTextField(value = feiId, onValueChange = { feiId = it }, label = { Text("FEI-ID") })
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
Button(onClick = {
|
||||
onSave(reiter.copy(
|
||||
vorname = vorname,
|
||||
nachname = nachname,
|
||||
oepsNummer = oepsNummer,
|
||||
satznummer = oepsNummer,
|
||||
verein = verein,
|
||||
feiId = feiId
|
||||
))
|
||||
}) {
|
||||
Text("Speichern")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text("Abbrechen")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PferdEditDialog(
|
||||
pferd: Pferd,
|
||||
onDismiss: () -> Unit,
|
||||
onSave: (Pferd) -> Unit
|
||||
) {
|
||||
var name by remember { mutableStateOf(pferd.name) }
|
||||
var lebensnummer by remember { mutableStateOf(pferd.lebensnummer) }
|
||||
var oepsNummer by remember { mutableStateOf(pferd.oepsNummer ?: "") }
|
||||
var geburtsjahr by remember { mutableStateOf(pferd.geburtsjahr?.toString() ?: "") }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text("Pferd bearbeiten") },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
OutlinedTextField(value = name, onValueChange = { name = it }, label = { Text("Name") })
|
||||
OutlinedTextField(value = lebensnummer, onValueChange = { lebensnummer = it }, label = { Text("Lebensnummer") })
|
||||
OutlinedTextField(value = oepsNummer, onValueChange = { oepsNummer = it }, label = { Text("OEPS-Nr.") })
|
||||
OutlinedTextField(value = geburtsjahr, onValueChange = { geburtsjahr = it }, label = { Text("Geburtsjahr") })
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
Button(onClick = {
|
||||
onSave(pferd.copy(
|
||||
name = name,
|
||||
lebensnummer = lebensnummer,
|
||||
oepsNummer = oepsNummer,
|
||||
geburtsjahr = geburtsjahr.toIntOrNull()
|
||||
))
|
||||
}) {
|
||||
Text("Speichern")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text("Abbrechen")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
+16
@@ -36,6 +36,22 @@ fun NennungenTabContent(
|
||||
) {
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
// --- Editoren ---
|
||||
state.selectedReiter?.let { reiter ->
|
||||
ReiterEditDialog(
|
||||
reiter = reiter,
|
||||
onDismiss = { viewModel.selectReiter(null) },
|
||||
onSave = { viewModel.saveReiter(it) }
|
||||
)
|
||||
}
|
||||
state.selectedPferd?.let { pferd ->
|
||||
PferdEditDialog(
|
||||
pferd = pferd,
|
||||
onDismiss = { viewModel.selectPferd(null) },
|
||||
onSave = { viewModel.savePferd(it) }
|
||||
)
|
||||
}
|
||||
|
||||
Row(modifier = Modifier.fillMaxSize()) {
|
||||
// ── Linke Spalte: Suche + Tabelle ─────────────────────────────────────
|
||||
Column(modifier = Modifier.weight(1f).fillMaxHeight()) {
|
||||
|
||||
Reference in New Issue
Block a user