### feat: verbessere Validierungs- und Draft-Funktionalität im Wizard

- Entferne `onNavigateToVeranstalterNeu` aus `EventWizardScreen` und zugehörigen Komponenten.
- Füge persistente Speicherung für Drafts über `DraftStore` hinzu (JSON für JVM, No-op für Wasm).
- Ergänze WizardScaffold um `errorSummary` zur Anzeige von Validierungsfehlern.
- Bereinige und optimiere Schritt-Logik in `EventWizardViewModel`.
This commit is contained in:
2026-04-21 20:12:46 +02:00
parent 148b71db48
commit bdb45eefe4
10 changed files with 150 additions and 48 deletions
+3
View File
@@ -13,6 +13,9 @@ group = "at.mocode.frontend.core"
version = "1.0.0"
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}
jvm()
wasmJs {
@@ -1,15 +1,14 @@
package at.mocode.frontend.core.wizard.draft
import kotlinx.serialization.Serializable
@Serializable
data class DraftEntry(val version: Int, val stepId: String)
/**
* Minimaler DraftStore (MVP): inMemory, versioniert per Key. Persistenz folgt später.
* Persistenter DraftStore.
*/
object DraftStoreMemory {
private data class Entry(val version: Int, val stepId: String)
private val store = mutableMapOf<String, Entry>()
fun save(flowKey: String, version: Int, stepId: String) {
store[flowKey] = Entry(version, stepId)
}
fun load(flowKey: String): Pair<Int, String>? = store[flowKey]?.let { it.version to it.stepId }
expect object DraftStore {
fun save(flowKey: String, version: Int, stepId: String)
fun load(flowKey: String): Pair<Int, String>?
}
@@ -27,6 +27,7 @@ fun WizardScaffold(
onBack: () -> Unit,
onNext: () -> Unit,
onSaveDraft: (() -> Unit)? = null,
errorSummary: String? = null,
nextLabel: String = "Weiter",
backLabel: String = "Zurück",
finishLabel: String = "Fertig",
@@ -80,6 +81,21 @@ fun WizardScaffold(
Spacer(Modifier.height(12.dp))
if (errorSummary != null) {
Surface(
color = MaterialTheme.colorScheme.errorContainer,
shape = MaterialTheme.shapes.small,
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
) {
Text(
text = errorSummary,
color = MaterialTheme.colorScheme.onErrorContainer,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(8.dp)
)
}
}
// Footer: Actions
Row(
modifier = Modifier.fillMaxWidth(),
@@ -0,0 +1,31 @@
package at.mocode.frontend.core.wizard.draft
import kotlinx.serialization.json.Json
import java.io.File
actual object DraftStore {
private val draftDir = File("drafts").apply { if (!exists()) mkdirs() }
private val json = Json { prettyPrint = true; ignoreUnknownKeys = true }
actual fun save(flowKey: String, version: Int, stepId: String) {
try {
val file = File(draftDir, "${flowKey}.json")
val entry = DraftEntry(version, stepId)
file.writeText(json.encodeToString(entry))
} catch (e: Exception) {
println("DraftStore: Error saving draft for $flowKey: ${e.message}")
}
}
actual fun load(flowKey: String): Pair<Int, String>? {
val file = File(draftDir, "${flowKey}.json")
if (!file.exists()) return null
return try {
val entry = json.decodeFromString<DraftEntry>(file.readText())
entry.version to entry.stepId
} catch (e: Exception) {
println("DraftStore: Error loading draft for $flowKey: ${e.message}")
null
}
}
}
@@ -18,6 +18,7 @@ fun WizardScaffoldWithHotkeys(
onBack: () -> Unit,
onNext: () -> Unit,
onSaveDraft: (() -> Unit)? = null,
errorSummary: String? = null,
nextLabel: String = "Weiter",
backLabel: String = "Zurück",
finishLabel: String = "Fertig",
@@ -54,6 +55,7 @@ fun WizardScaffoldWithHotkeys(
onBack = onBack,
onNext = onNext,
onSaveDraft = onSaveDraft,
errorSummary = errorSummary,
nextLabel = nextLabel,
backLabel = backLabel,
finishLabel = finishLabel,
@@ -0,0 +1,9 @@
package at.mocode.frontend.core.wizard.draft
actual object DraftStore {
actual fun save(flowKey: String, version: Int, stepId: String) {
// No-op for WasmJs MVP
}
actual fun load(flowKey: String): Pair<Int, String>? = null
}