feat: integriere WizardRuntime in EventWizardViewModel und erweitere Schritt-Logik
Some checks failed
Desktop CI — Headless Tests & Build / Compose Desktop — Tests (headless) & Build (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Has been cancelled

Signed-off-by: StefanMoCoAt <stefan.mo.co@gmail.com>
This commit is contained in:
Stefan Mogeritsch 2026-04-21 17:44:27 +02:00
parent 9556e0ac67
commit 19ba044ec0
3 changed files with 105 additions and 36 deletions

View File

@ -23,24 +23,30 @@ kotlin {
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.domain)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
}
commonMain.dependencies {
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.domain)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
}
val commonTest by getting {
dependencies {
implementation(libs.kotlin.test)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
val jvmMain by getting
val wasmJsMain by getting {
dependencies {
implementation(libs.kotlin.stdlib.wasm.js)
}
jvmMain.dependencies {
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.domain)
}
jvmTest.dependencies {
implementation(libs.kotlin.test)
}
}
sourceSets.commonTest.dependencies {
implementation(kotlin("test"))
}
}

View File

@ -30,7 +30,8 @@ kotlin {
implementation(projects.frontend.core.designSystem)
implementation(projects.frontend.core.network)
implementation(projects.frontend.core.domain)
implementation(project(":frontend:core:wizard"))
implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.wizard)
implementation(projects.core.coreDomain)
implementation(projects.frontend.core.auth)
implementation(projects.frontend.features.vereinFeature)

View File

@ -7,11 +7,18 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import at.mocode.core.domain.serialization.UuidSerializer
import at.mocode.frontend.core.auth.data.local.AuthTokenManager
import at.mocode.frontend.core.domain.config.WizardFeatureFlags
import at.mocode.frontend.core.domain.repository.MasterdataRepository
import at.mocode.frontend.core.domain.repository.MasterdataStats
import at.mocode.frontend.core.domain.zns.ZnsImportProvider
import at.mocode.frontend.core.domain.zns.ZnsRemoteVerein
import at.mocode.frontend.core.navigation.AppScreen
import at.mocode.frontend.core.network.NetworkConfig
import at.mocode.frontend.core.wizard.runtime.WizardContext
import at.mocode.frontend.core.wizard.runtime.WizardState
import at.mocode.frontend.core.wizard.samples.DemoEventAcc
import at.mocode.frontend.core.wizard.samples.DemoEventFlow
import at.mocode.frontend.core.wizard.samples.DemoEventStep
import at.mocode.frontend.features.turnier.presentation.TurnierWizardViewModel
import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository
import at.mocode.frontend.features.verein.domain.VereinRepository
@ -78,6 +85,9 @@ class EventWizardViewModel(
var state by mutableStateOf(VeranstaltungWizardState())
private set
// --- Orchestrator-Integration (minimal, 2 Steps) ---
private var wizardState: WizardState<DemoEventStep, DemoEventAcc>? = null
init {
checkZnsAvailability()
checkStammdatenStatus()
@ -87,6 +97,12 @@ class EventWizardViewModel(
if (veranstalterIdParam != null) {
loadVeranstalterContext(veranstalterIdParam)
}
// Initialisiere WizardRuntime-State (hinter Feature-Flag nutzbar)
if (WizardFeatureFlags.WizardRuntimeEnabled) {
@Suppress("UNCHECKED_CAST")
wizardState = WizardState(current = (DemoEventStep.ZnsCheck as DemoEventStep), acc = DemoEventAcc())
}
}
private fun loadVeranstalterContext(id: Long) {
@ -94,7 +110,7 @@ class EventWizardViewModel(
val result = veranstalterRepository.getById(id)
result.onSuccess { v ->
setVeranstalter(
id = Uuid.random(), // Hier müsste eigentlich die Verein-UUID rein, falls vorhanden, sonst random für Neu-Anlage
id = Uuid.random(), // Hier müsste eigentlich die Vereins-UUID rein, falls vorhanden, sonst random für Neu-Anlage
nummer = v.oepsNummer,
name = v.name,
standardOrt = v.ort,
@ -168,29 +184,75 @@ class EventWizardViewModel(
}
fun nextStep() {
state = state.copy(
currentStep = when (state.currentStep) {
WizardStep.ZNS_CHECK -> WizardStep.VERANSTALTER_SELECTION
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ANSPRECHPERSON_MAPPING
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.META_DATA
WizardStep.META_DATA -> WizardStep.TURNIER_ANLAGE
WizardStep.TURNIER_ANLAGE -> WizardStep.SUMMARY
WizardStep.SUMMARY -> WizardStep.SUMMARY
if (WizardFeatureFlags.WizardRuntimeEnabled && isHandledByRuntime(state.currentStep)) {
val ctx = buildWizardContext()
val currentRuntimeState = ensureWizardStateInitialized()
val next = DemoEventFlow.next(ctx, currentRuntimeState)
wizardState = next
val mapped = mapToWizardStep(next.current)
if (mapped != null) {
state = state.copy(currentStep = mapped)
return
}
)
// Fallback, sollte eigentlich nicht eintreten
}
state = state.copy(currentStep = when (state.currentStep) {
WizardStep.ZNS_CHECK -> WizardStep.VERANSTALTER_SELECTION
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ANSPRECHPERSON_MAPPING
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.META_DATA
WizardStep.META_DATA -> WizardStep.TURNIER_ANLAGE
WizardStep.TURNIER_ANLAGE -> WizardStep.SUMMARY
WizardStep.SUMMARY -> WizardStep.SUMMARY
})
}
fun previousStep() {
state = state.copy(
currentStep = when (state.currentStep) {
WizardStep.ZNS_CHECK -> WizardStep.ZNS_CHECK
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ZNS_CHECK
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.VERANSTALTER_SELECTION
WizardStep.META_DATA -> WizardStep.ANSPRECHPERSON_MAPPING
WizardStep.TURNIER_ANLAGE -> WizardStep.META_DATA
WizardStep.SUMMARY -> WizardStep.TURNIER_ANLAGE
if (WizardFeatureFlags.WizardRuntimeEnabled && isHandledByRuntime(state.currentStep)) {
val currentRuntimeState = ensureWizardStateInitialized()
val prev = DemoEventFlow.back(currentRuntimeState)
wizardState = prev
val mapped = mapToWizardStep(prev.current)
if (mapped != null) {
state = state.copy(currentStep = mapped)
return
}
)
}
state = state.copy(currentStep = when (state.currentStep) {
WizardStep.ZNS_CHECK -> WizardStep.ZNS_CHECK
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ZNS_CHECK
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.VERANSTALTER_SELECTION
WizardStep.META_DATA -> WizardStep.ANSPRECHPERSON_MAPPING
WizardStep.TURNIER_ANLAGE -> WizardStep.META_DATA
WizardStep.SUMMARY -> WizardStep.TURNIER_ANLAGE
})
}
private fun buildWizardContext(): WizardContext = WizardContext(
origin = AppScreen.EventVerwaltung, // Platzhalter; kann später aus echtem Einstieg befüllt werden
role = null,
isOnline = true,
stats = state.stammdatenStats
)
private fun ensureWizardStateInitialized(): WizardState<DemoEventStep, DemoEventAcc> {
val existing = wizardState
if (existing != null) return existing
@Suppress("UNCHECKED_CAST")
val initial = WizardState(current = (DemoEventStep.ZnsCheck as DemoEventStep), acc = DemoEventAcc())
wizardState = initial
return initial
}
private fun isHandledByRuntime(step: WizardStep): Boolean = when (step) {
WizardStep.ZNS_CHECK, WizardStep.VERANSTALTER_SELECTION -> true
else -> false
}
private fun mapToWizardStep(step: DemoEventStep): WizardStep? = when (step) {
DemoEventStep.ZnsCheck -> WizardStep.ZNS_CHECK
DemoEventStep.VeranstalterSelection -> WizardStep.VERANSTALTER_SELECTION
}
fun setVeranstalter(id: Uuid, nummer: String, name: String, standardOrt: String, logo: String?) {