feat: integriere WizardRuntime in EventWizardViewModel und erweitere Schritt-Logik
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:
2026-04-21 17:44:27 +02:00
parent 9556e0ac67
commit 19ba044ec0
3 changed files with 105 additions and 36 deletions
+22 -16
View File
@@ -23,24 +23,30 @@ kotlin {
} }
sourceSets { sourceSets {
val commonMain by getting {
dependencies { commonMain.dependencies {
implementation(projects.frontend.core.navigation) implementation(projects.frontend.core.navigation)
implementation(projects.frontend.core.domain) implementation(projects.frontend.core.domain)
implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)
}
} }
val commonTest by getting {
dependencies { commonTest.dependencies {
implementation(libs.kotlin.test) implementation(libs.kotlin.test)
}
} }
val jvmMain by getting
val wasmJsMain by getting { jvmMain.dependencies {
dependencies { implementation(projects.frontend.core.navigation)
implementation(libs.kotlin.stdlib.wasm.js) implementation(projects.frontend.core.domain)
}
} }
jvmTest.dependencies {
implementation(libs.kotlin.test)
}
}
sourceSets.commonTest.dependencies {
implementation(kotlin("test"))
} }
} }
@@ -30,7 +30,8 @@ kotlin {
implementation(projects.frontend.core.designSystem) implementation(projects.frontend.core.designSystem)
implementation(projects.frontend.core.network) implementation(projects.frontend.core.network)
implementation(projects.frontend.core.domain) 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.core.coreDomain)
implementation(projects.frontend.core.auth) implementation(projects.frontend.core.auth)
implementation(projects.frontend.features.vereinFeature) implementation(projects.frontend.features.vereinFeature)
@@ -7,11 +7,18 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import at.mocode.core.domain.serialization.UuidSerializer import at.mocode.core.domain.serialization.UuidSerializer
import at.mocode.frontend.core.auth.data.local.AuthTokenManager 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.MasterdataRepository
import at.mocode.frontend.core.domain.repository.MasterdataStats import at.mocode.frontend.core.domain.repository.MasterdataStats
import at.mocode.frontend.core.domain.zns.ZnsImportProvider import at.mocode.frontend.core.domain.zns.ZnsImportProvider
import at.mocode.frontend.core.domain.zns.ZnsRemoteVerein 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.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.turnier.presentation.TurnierWizardViewModel
import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository import at.mocode.frontend.features.veranstalter.domain.VeranstalterRepository
import at.mocode.frontend.features.verein.domain.VereinRepository import at.mocode.frontend.features.verein.domain.VereinRepository
@@ -78,6 +85,9 @@ class EventWizardViewModel(
var state by mutableStateOf(VeranstaltungWizardState()) var state by mutableStateOf(VeranstaltungWizardState())
private set private set
// --- Orchestrator-Integration (minimal, 2 Steps) ---
private var wizardState: WizardState<DemoEventStep, DemoEventAcc>? = null
init { init {
checkZnsAvailability() checkZnsAvailability()
checkStammdatenStatus() checkStammdatenStatus()
@@ -87,6 +97,12 @@ class EventWizardViewModel(
if (veranstalterIdParam != null) { if (veranstalterIdParam != null) {
loadVeranstalterContext(veranstalterIdParam) 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) { private fun loadVeranstalterContext(id: Long) {
@@ -94,7 +110,7 @@ class EventWizardViewModel(
val result = veranstalterRepository.getById(id) val result = veranstalterRepository.getById(id)
result.onSuccess { v -> result.onSuccess { v ->
setVeranstalter( 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, nummer = v.oepsNummer,
name = v.name, name = v.name,
standardOrt = v.ort, standardOrt = v.ort,
@@ -168,29 +184,75 @@ class EventWizardViewModel(
} }
fun nextStep() { fun nextStep() {
state = state.copy( if (WizardFeatureFlags.WizardRuntimeEnabled && isHandledByRuntime(state.currentStep)) {
currentStep = when (state.currentStep) { val ctx = buildWizardContext()
WizardStep.ZNS_CHECK -> WizardStep.VERANSTALTER_SELECTION val currentRuntimeState = ensureWizardStateInitialized()
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ANSPRECHPERSON_MAPPING val next = DemoEventFlow.next(ctx, currentRuntimeState)
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.META_DATA wizardState = next
WizardStep.META_DATA -> WizardStep.TURNIER_ANLAGE val mapped = mapToWizardStep(next.current)
WizardStep.TURNIER_ANLAGE -> WizardStep.SUMMARY if (mapped != null) {
WizardStep.SUMMARY -> WizardStep.SUMMARY 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() { fun previousStep() {
state = state.copy( if (WizardFeatureFlags.WizardRuntimeEnabled && isHandledByRuntime(state.currentStep)) {
currentStep = when (state.currentStep) { val currentRuntimeState = ensureWizardStateInitialized()
WizardStep.ZNS_CHECK -> WizardStep.ZNS_CHECK val prev = DemoEventFlow.back(currentRuntimeState)
WizardStep.VERANSTALTER_SELECTION -> WizardStep.ZNS_CHECK wizardState = prev
WizardStep.ANSPRECHPERSON_MAPPING -> WizardStep.VERANSTALTER_SELECTION val mapped = mapToWizardStep(prev.current)
WizardStep.META_DATA -> WizardStep.ANSPRECHPERSON_MAPPING if (mapped != null) {
WizardStep.TURNIER_ANLAGE -> WizardStep.META_DATA state = state.copy(currentStep = mapped)
WizardStep.SUMMARY -> WizardStep.TURNIER_ANLAGE 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?) { fun setVeranstalter(id: Uuid, nummer: String, name: String, standardOrt: String, logo: String?) {