chore: erweitere Veranstalter-Wizard um Bearbeitungsmodus, füge Kontaktdaten und Step-Logik hinzu
Signed-off-by: StefanMoCoAt <stefan.mo.co@gmail.com>
This commit is contained in:
+13
@@ -178,6 +178,17 @@ fun DesktopContentArea(
|
||||
onBack = onBack,
|
||||
onZurVeranstaltung = { evtId: Long -> onNavigate(AppScreen.EventProfil(currentScreen.id, evtId)) },
|
||||
onNeuVeranstaltung = { onNavigate(AppScreen.EventNeu) },
|
||||
onEditVeranstalter = { id ->
|
||||
onNavigate(AppScreen.VeranstalterProfilEdit(id))
|
||||
}
|
||||
)
|
||||
|
||||
is AppScreen.VeranstalterProfilEdit -> VeranstalterAnlegenWizard(
|
||||
editId = currentScreen.id,
|
||||
onCancel = onBack,
|
||||
onVereinCreated = { id ->
|
||||
onNavigate(AppScreen.VeranstalterProfil(id))
|
||||
}
|
||||
)
|
||||
|
||||
// Neuer Flow: Veranstalter auswählen → Event-Wizard
|
||||
@@ -188,6 +199,7 @@ fun DesktopContentArea(
|
||||
)
|
||||
|
||||
is AppScreen.VeranstalterNeu -> VeranstalterAnlegenWizard(
|
||||
editId = null,
|
||||
onCancel = onBack,
|
||||
onVereinCreated = { newId: Long -> onNavigate(AppScreen.VeranstalterProfil(newId)) }
|
||||
)
|
||||
@@ -199,6 +211,7 @@ fun DesktopContentArea(
|
||||
onBack = onBack,
|
||||
onZurVeranstaltung = { evtId -> onNavigate(AppScreen.EventProfil(vId, evtId)) },
|
||||
onNeuVeranstaltung = { onNavigate(AppScreen.EventKonfig(vId)) },
|
||||
onEditVeranstalter = { id -> onNavigate(AppScreen.VeranstalterProfilEdit(id)) }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -30,12 +30,14 @@ fun VeranstalterDetail(
|
||||
onBack: () -> Unit,
|
||||
onZurVeranstaltung: (Long) -> Unit,
|
||||
onNeuVeranstaltung: () -> Unit,
|
||||
onEditVeranstalter: (Long) -> Unit,
|
||||
) {
|
||||
VeranstalterDetailScreen(
|
||||
veranstalterId = veranstalterId,
|
||||
viewModel = koinInject(),
|
||||
onZurueck = onBack,
|
||||
onVeranstaltungOeffnen = onZurVeranstaltung,
|
||||
onVeranstaltungNeu = onNeuVeranstaltung
|
||||
onVeranstaltungNeu = onNeuVeranstaltung,
|
||||
onEditVeranstalter = onEditVeranstalter
|
||||
)
|
||||
}
|
||||
|
||||
+1
@@ -82,6 +82,7 @@ fun PreviewVeranstalterDetailScreen() {
|
||||
onZurueck = {},
|
||||
onVeranstaltungOeffnen = {},
|
||||
onVeranstaltungNeu = {},
|
||||
onEditVeranstalter = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+120
-14
@@ -4,37 +4,61 @@ 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.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import at.mocode.frontend.shell.desktop.data.Store
|
||||
import at.mocode.frontend.core.domain.zns.ZnsImportProvider
|
||||
import at.mocode.frontend.core.domain.zns.ZnsImportState
|
||||
import at.mocode.frontend.features.veranstalter.presentation.VeranstalterWizardIntent
|
||||
import at.mocode.frontend.features.veranstalter.presentation.VeranstalterWizardViewModel
|
||||
import at.mocode.frontend.shell.desktop.data.Store
|
||||
import at.mocode.frontend.shell.desktop.screens.veranstaltung.components.pickZnsFile
|
||||
import org.koin.compose.koinInject
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun VeranstalterAnlegenWizard(
|
||||
editId: Long? = null,
|
||||
onCancel: () -> Unit,
|
||||
onVereinCreated: (Long) -> Unit
|
||||
) {
|
||||
var step by remember { mutableStateOf(1) }
|
||||
var selectedVereinId by remember { mutableLongStateOf(0L) }
|
||||
val viewModel = koinViewModel<VeranstalterWizardViewModel>()
|
||||
val state by viewModel.state.collectAsState()
|
||||
var step by remember { mutableIntStateOf(1) }
|
||||
|
||||
LaunchedEffect(editId) {
|
||||
if (editId != null) {
|
||||
viewModel.send(VeranstalterWizardIntent.Load(editId))
|
||||
step = 2 // Direkt zu den Details beim Editieren
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(state.success) {
|
||||
if (state.success) {
|
||||
onVereinCreated(state.editId ?: 0L)
|
||||
}
|
||||
}
|
||||
|
||||
val znsImporter = koinInject<ZnsImportProvider>()
|
||||
val znsState = znsImporter.state
|
||||
|
||||
Column(Modifier.fillMaxSize().padding(24.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
IconButton(onClick = onCancel) { Icon(Icons.Default.Close, null) }
|
||||
Text("Veranstalter registrieren", style = MaterialTheme.typography.headlineSmall)
|
||||
Text(
|
||||
if (editId == null) "Veranstalter registrieren" else "Veranstalter-Profil bearbeiten",
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
}
|
||||
|
||||
LinearProgressIndicator(
|
||||
@@ -47,14 +71,21 @@ fun VeranstalterAnlegenWizard(
|
||||
1 -> Step1Veranstalter(
|
||||
znsState = znsState,
|
||||
znsImporter = znsImporter,
|
||||
selectedVereinId = selectedVereinId,
|
||||
onVereinSelected = { selectedVereinId = it },
|
||||
selectedVereinId = state.editId ?: 0L,
|
||||
onVereinSelected = { id ->
|
||||
// Mock: Wir laden die Daten des Vereins aus dem Store in das VM
|
||||
at.mocode.frontend.shell.desktop.data.Store.vereine.find { it.id == id }?.let { v ->
|
||||
viewModel.send(VeranstalterWizardIntent.UpdateName(v.name))
|
||||
viewModel.send(VeranstalterWizardIntent.UpdateOeps(v.oepsNummer))
|
||||
viewModel.send(VeranstalterWizardIntent.UpdateOrt(v.ort ?: ""))
|
||||
}
|
||||
},
|
||||
onVeranstalterCreated = {
|
||||
selectedVereinId = it
|
||||
onVereinCreated(it)
|
||||
// Nicht mehr direkt navigieren, sondern zu Step 2
|
||||
step = 2
|
||||
}
|
||||
)
|
||||
2 -> { /* Optional: Weitere Details für den Veranstalter */ }
|
||||
2 -> Step2VeranstalterDetails(viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,16 +94,91 @@ fun VeranstalterAnlegenWizard(
|
||||
Spacer(Modifier.width(8.dp))
|
||||
if (step == 1) {
|
||||
Button(
|
||||
onClick = { onVereinCreated(selectedVereinId) },
|
||||
enabled = selectedVereinId != 0L
|
||||
onClick = { step = 2 },
|
||||
enabled = state.name.isNotBlank()
|
||||
) {
|
||||
Text("Fertigstellen")
|
||||
Text("Weiter zu den Details")
|
||||
}
|
||||
} else {
|
||||
Button(
|
||||
onClick = { viewModel.send(VeranstalterWizardIntent.Save) },
|
||||
enabled = !state.isSaving && state.name.isNotBlank()
|
||||
) {
|
||||
if (state.isSaving) {
|
||||
CircularProgressIndicator(Modifier.size(18.dp), strokeWidth = 2.dp, color = Color.White)
|
||||
} else {
|
||||
Text(if (editId == null) "Registrierung abschließen" else "Änderungen speichern")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Step2VeranstalterDetails(viewModel: VeranstalterWizardViewModel) {
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.verticalScroll(rememberScrollState())) {
|
||||
Text("Ergänzen Sie die Kontaktdaten für diesen Veranstalter.", style = MaterialTheme.typography.bodyMedium)
|
||||
|
||||
OutlinedTextField(
|
||||
value = state.name,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateName(it)) },
|
||||
label = { Text("Name des Veranstalters / Vereins") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
OutlinedTextField(
|
||||
value = state.oepsNummer,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateOeps(it)) },
|
||||
label = { Text("OEBS-Nr") },
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = state.ort,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateOrt(it)) },
|
||||
label = { Text("Ort") },
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
Text("Ansprechpartner & Kontakt", style = MaterialTheme.typography.titleSmall)
|
||||
|
||||
OutlinedTextField(
|
||||
value = state.ansprechpartner,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateAnsprechpartner(it)) },
|
||||
label = { Text("Name Ansprechpartner") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
OutlinedTextField(
|
||||
value = state.email,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateEmail(it)) },
|
||||
label = { Text("E-Mail Adresse") },
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = state.telefon,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateTelefon(it)) },
|
||||
label = { Text("Telefonnummer") },
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
value = state.adresse,
|
||||
onValueChange = { viewModel.send(VeranstalterWizardIntent.UpdateAdresse(it)) },
|
||||
label = { Text("Postanschrift") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
minLines = 2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Step1Veranstalter(
|
||||
znsState: ZnsImportState,
|
||||
|
||||
Reference in New Issue
Block a user