feat(veranstaltung): migrate event wizard to declarative orchestrator (ADR-0025). Transferred logic from EventFlowSample to EventWizardFlow. Renamed Demo* components to EventWizard*. Added OETO-compliant steps: TurnierKonfiguration, BewerbKonfiguration, AbteilungKonfiguration, Summary. Updated DSL flow to include full sequential path. --trailer "Co-authored-by: Junie <junie@jetbrains.com>"
This commit is contained in:
@@ -24,6 +24,7 @@ kotlin {
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
api(projects.core.coreDomain)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ kotlin {
|
||||
implementation(projects.frontend.core.navigation)
|
||||
implementation(projects.frontend.features.billingFeature)
|
||||
implementation(projects.frontend.features.nennungFeature)
|
||||
implementation(projects.frontend.core.wizard)
|
||||
implementation(projects.core.znsParser)
|
||||
|
||||
implementation(compose.foundation)
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package at.mocode.frontend.features.turnier.wizard
|
||||
|
||||
import at.mocode.core.domain.model.ReglementE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.core.domain.model.TurnierkategorieE
|
||||
import at.mocode.frontend.core.wizard.dsl.flow
|
||||
import at.mocode.frontend.core.wizard.runtime.StepId
|
||||
|
||||
/**
|
||||
* Definiert die Schritte für den Turnier-Anlage-Wizard.
|
||||
* Orientiert sich an der ÖTO-Logik und dem SCS-Rahmen.
|
||||
*/
|
||||
sealed interface TurnierAnlageStep : StepId {
|
||||
/** 1. Basisdaten (Name, Nummer, Datum, Sparte) */
|
||||
data object Basisdaten : TurnierAnlageStep
|
||||
/** 2. Kategorie & Reglement (CSN-C, CDN, etc. / ÖTO vs FEI) */
|
||||
data object KategorieReglement : TurnierAnlageStep
|
||||
/** 3. Funktionäre (TB, Parcoursbauer, etc.) */
|
||||
data object Funktionaere : TurnierAnlageStep
|
||||
/** 4. Nenn-Konfiguration (Nennschluss, Gebühren, Tauschbörse) */
|
||||
data object NennKonfig : TurnierAnlageStep
|
||||
/** 5. Zusammenfassung & Validierung (ÖTO-Warnungen prüfen) */
|
||||
data object Summary : TurnierAnlageStep
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulator für den Turnier-Wizard.
|
||||
* Sammelt die Daten, bevor sie als [DomTurnier] ans Backend gesendet werden.
|
||||
*/
|
||||
data class TurnierAnlageAcc(
|
||||
val name: String = "",
|
||||
val turnierNummer: String = "",
|
||||
val sparte: SparteE = SparteE.SPRINGEN,
|
||||
val kategorie: TurnierkategorieE = TurnierkategorieE.C,
|
||||
val reglement: ReglementE = ReglementE.OETO,
|
||||
val datum: String? = null, // ISO LocalDate
|
||||
val tbId: String? = null,
|
||||
val pbId: String? = null,
|
||||
val nennschluss: String? = null, // ISO Instant
|
||||
val nachnenngebuehrVerlangt: Boolean = false,
|
||||
val nenntauschboerseAktiv: Boolean = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Der Wizard-Flow für die Turnier-Anlage.
|
||||
*/
|
||||
val TurnierAnlageFlow = flow<TurnierAnlageStep, TurnierAnlageAcc>(start = TurnierAnlageStep.Basisdaten) {
|
||||
step(TurnierAnlageStep.Basisdaten) {
|
||||
otherwise(TurnierAnlageStep.KategorieReglement)
|
||||
}
|
||||
step(TurnierAnlageStep.KategorieReglement) {
|
||||
otherwise(TurnierAnlageStep.Funktionaere)
|
||||
}
|
||||
step(TurnierAnlageStep.Funktionaere) {
|
||||
otherwise(TurnierAnlageStep.NennKonfig)
|
||||
}
|
||||
step(TurnierAnlageStep.NennKonfig) {
|
||||
otherwise(TurnierAnlageStep.Summary)
|
||||
}
|
||||
}
|
||||
+73
-4
@@ -1,7 +1,76 @@
|
||||
package at.mocode.veranstaltung.feature.wizard
|
||||
|
||||
// Platzhalter für den Event-Flow.
|
||||
// Hinweis: Der echte Flow lebt zunächst als Demo in :frontend:core:wizard (samples),
|
||||
// bis die VM-Delegation hinter dem Feature-Flag integriert wird.
|
||||
import at.mocode.frontend.core.navigation.AppScreen
|
||||
import at.mocode.frontend.core.wizard.dsl.flow
|
||||
import at.mocode.frontend.core.wizard.runtime.Guard
|
||||
import at.mocode.frontend.core.wizard.runtime.StepId
|
||||
import at.mocode.frontend.core.wizard.runtime.WizardContext
|
||||
import at.mocode.frontend.core.wizard.runtime.WizardState
|
||||
|
||||
object EventWizardPlaceholder
|
||||
sealed interface EventWizardStep : StepId {
|
||||
data object ZnsCheck : EventWizardStep
|
||||
data object VeranstalterSelection : EventWizardStep
|
||||
data object AnsprechpersonMapping : EventWizardStep
|
||||
data object MetaData : EventWizardStep
|
||||
data object TurnierKonfiguration : EventWizardStep
|
||||
data object BewerbKonfiguration : EventWizardStep
|
||||
data object AbteilungKonfiguration : EventWizardStep
|
||||
data object Summary : EventWizardStep
|
||||
}
|
||||
|
||||
data class EventWizardAcc(
|
||||
val veranstalterId: String? = null,
|
||||
val veranstalterNr: String = ""
|
||||
)
|
||||
|
||||
object EventWizardGuards {
|
||||
val hasZns: Guard<EventWizardStep, EventWizardAcc> = { ctx, _ ->
|
||||
val stats = ctx.stats
|
||||
if (stats == null) false
|
||||
else {
|
||||
val hasData = stats.vereinCount > 0
|
||||
hasData && !stats.lastImport.isNullOrBlank()
|
||||
}
|
||||
}
|
||||
|
||||
val needsContactPerson: Guard<EventWizardStep, EventWizardAcc> = { _, acc ->
|
||||
acc.veranstalterId == null || acc.veranstalterNr.startsWith("ORG-")
|
||||
}
|
||||
|
||||
val hasSelectedVeranstalter: Guard<EventWizardStep, EventWizardAcc> = { _, acc ->
|
||||
!acc.veranstalterId.isNullOrBlank()
|
||||
}
|
||||
}
|
||||
|
||||
val EventWizardFlow = flow<EventWizardStep, EventWizardAcc>(start = EventWizardStep.ZnsCheck) {
|
||||
step(EventWizardStep.ZnsCheck) {
|
||||
whenGuard("hasZns", EventWizardGuards.hasZns, go = EventWizardStep.VeranstalterSelection)
|
||||
otherwise(EventWizardStep.VeranstalterSelection)
|
||||
}
|
||||
step(EventWizardStep.VeranstalterSelection) {
|
||||
whenGuard("notSelected", { ctx, acc -> !EventWizardGuards.hasSelectedVeranstalter(ctx, acc) }, go = EventWizardStep.VeranstalterSelection)
|
||||
whenGuard("needsContactPerson", EventWizardGuards.needsContactPerson, go = EventWizardStep.AnsprechpersonMapping)
|
||||
otherwise(EventWizardStep.MetaData)
|
||||
}
|
||||
step(EventWizardStep.AnsprechpersonMapping) {
|
||||
otherwise(EventWizardStep.MetaData)
|
||||
}
|
||||
step(EventWizardStep.MetaData) {
|
||||
otherwise(EventWizardStep.TurnierKonfiguration)
|
||||
}
|
||||
step(EventWizardStep.TurnierKonfiguration) {
|
||||
otherwise(EventWizardStep.BewerbKonfiguration)
|
||||
}
|
||||
step(EventWizardStep.BewerbKonfiguration) {
|
||||
otherwise(EventWizardStep.AbteilungKonfiguration)
|
||||
}
|
||||
step(EventWizardStep.AbteilungKonfiguration) {
|
||||
otherwise(EventWizardStep.Summary)
|
||||
}
|
||||
step(EventWizardStep.Summary) {
|
||||
// End-Step
|
||||
}
|
||||
}
|
||||
|
||||
fun eventWizardStartState(origin: AppScreen, acc: EventWizardAcc = EventWizardAcc()): WizardState<EventWizardStep, EventWizardAcc> =
|
||||
WizardState(current = EventWizardStep.ZnsCheck, acc = acc)
|
||||
|
||||
Reference in New Issue
Block a user