feat(management-feature): add centralized administration screens and back-navigation support

- Introduced comprehensive management screens for horses, riders, clubs, and officials.
- Integrated reusable `ManagementTableScreen` component for standardized layouts and operations.
- Added back-navigation support in `DesktopNavigationPort` with a stack-based implementation.
- Refined `DesktopMainLayout` with enhanced routing and dynamic placeholders for in-development screens.
- Updated roadmap to reflect completion of Phase 7: "Zentrale Verwaltung".

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-04-01 17:26:44 +02:00
parent 09debdef86
commit 6fc6c8fc79
17 changed files with 1019 additions and 121 deletions
@@ -18,7 +18,25 @@ sealed class AppScreen(val route: String) {
data object Nennung : AppScreen("/nennung")
// --- Desktop-Navigation (Vision_03) ---
data object Veranstaltungen : AppScreen("/veranstaltungen")
data object VeranstaltungVerwaltung : AppScreen("/verwaltung") // Gesamtübersicht
// Profile
data object PferdVerwaltung : AppScreen("/pferde/verwaltung")
data class PferdProfil(val id: Long) : AppScreen("/pferde/profil/$id")
data object ReiterVerwaltung : AppScreen("/reiter/verwaltung")
data class ReiterProfil(val id: Long) : AppScreen("/reiter/profil/$id")
data object VereinVerwaltung : AppScreen("/vereine/verwaltung")
data class VereinProfil(val id: Long) : AppScreen("/vereine/profil/$id")
data object FunktionaerVerwaltung : AppScreen("/funktionaere/verwaltung")
data class FunktionaerProfil(val id: Long) : AppScreen("/funktionaere/profil/$id")
data object VeranstalterVerwaltung : AppScreen("/veranstalter/verwaltung")
data class VeranstalterProfil(val id: Long) : AppScreen("/veranstalter/profil/$id")
// data class VeranstaltungProfil(val id: Long) : AppScreen("/veranstaltung/profil/$id")
// Neuer Flow: + Neue Veranstaltung → Veranstalter auswählen → Veranstalter-Detail → Veranstaltung-Übersicht
data object VeranstalterAuswahl : AppScreen("/veranstalter/auswahl")
@@ -28,7 +46,7 @@ sealed class AppScreen(val route: String) {
// Neue Veranstaltungs-Konfig-Seite (aus Veranstalter-Detail oder direkt aus Cockpit)
data class VeranstaltungKonfig(val veranstalterId: Long = 0) :
AppScreen("/veranstalter/$veranstalterId/veranstaltung/neu")
data class VeranstaltungUebersicht(val veranstalterId: Long, val veranstaltungId: Long) :
data class VeranstaltungProfil(val veranstalterId: Long, val veranstaltungId: Long) :
AppScreen("/veranstalter/$veranstalterId/veranstaltung/$veranstaltungId")
data class VeranstaltungDetail(val id: Long) : AppScreen("/veranstaltung/$id")
@@ -51,7 +69,14 @@ sealed class AppScreen(val route: String) {
private val TURNIER_NEU = Regex("/veranstaltung/(\\d+)/turnier/neu$")
private val VERANSTALTER_DETAIL = Regex("/veranstalter/(\\d+)$")
private val VERANSTALTUNG_KONFIG = Regex("/veranstalter/(\\d+)/veranstaltung/neu$")
private val VERANSTALTUNG_UEBERSICHT = Regex("/veranstalter/(\\d+)/veranstaltung/(\\d+)$")
private val VERANSTALTUNG_PROFIL = Regex("/veranstalter/(\\d+)/veranstaltung/(\\d+)$")
private val PFERD_PROFIL = Regex("/pferde/profil/(\\d+)$")
private val REITER_PROFIL = Regex("/reiter/profil/(\\d+)$")
private val VEREIN_PROFIL = Regex("/vereine/profil/(\\d+)$")
private val FUNKTIONAER_PROFIL = Regex("/funktionaere/profil/(\\d+)$")
private val VERANSTALTER_PROFIL = Regex("/veranstalter/profil/(\\d+)$")
// private val VERANSTALTUNG_PROFIL_LEGACY = Regex("/veranstaltung/profil/(\\d+)$")
fun fromRoute(route: String): AppScreen {
return when (route) {
@@ -66,17 +91,27 @@ sealed class AppScreen(val route: String) {
"/organizer/profile" -> OrganizerProfile
"/auth/callback" -> AuthCallback
"/nennung" -> Nennung
"/veranstaltungen" -> Veranstaltungen
"/verwaltung" -> VeranstaltungVerwaltung
"/pferde/verwaltung" -> PferdVerwaltung
"/reiter/verwaltung" -> ReiterVerwaltung
"/vereine/verwaltung" -> VereinVerwaltung
"/funktionaere/verwaltung" -> FunktionaerVerwaltung
"/veranstalter/verwaltung" -> VeranstalterVerwaltung
"/veranstalter/auswahl" -> VeranstalterAuswahl
"/veranstaltung/neu" -> VeranstaltungNeu
"/reiter" -> Reiter
"/pferde" -> Pferde
"/vereine" -> Vereine
"/funktionaere" -> Funktionaere
"/meisterschaften" -> Meisterschaften
"/cups" -> Cups
"/stammdaten/import" -> StammdatenImport
else -> {
PFERD_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return PferdProfil(id.toLong()) }
REITER_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return ReiterProfil(id.toLong()) }
VEREIN_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return VereinProfil(id.toLong()) }
FUNKTIONAER_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return FunktionaerProfil(id.toLong()) }
VERANSTALTER_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return VeranstalterProfil(id.toLong()) }
/*
VERANSTALTUNG_PROFIL.matchEntire(route)?.destructured?.let { (id) -> return VeranstaltungProfil(id.toLong()) }
*/
TURNIER_DETAIL.matchEntire(route)?.destructured?.let { (vId, tId) ->
return TurnierDetail(vId.toLong(), tId.toLong())
}
@@ -92,8 +127,8 @@ sealed class AppScreen(val route: String) {
VERANSTALTUNG_KONFIG.matchEntire(route)?.destructured?.let { (vId) ->
return VeranstaltungKonfig(vId.toLong())
}
VERANSTALTUNG_UEBERSICHT.matchEntire(route)?.destructured?.let { (verId, vId) ->
return VeranstaltungUebersicht(verId.toLong(), vId.toLong())
VERANSTALTUNG_PROFIL.matchEntire(route)?.destructured?.let { (verId, vId) ->
return VeranstaltungProfil(verId.toLong(), vId.toLong())
}
Landing // Default fallback
}
@@ -15,4 +15,7 @@ interface NavigationPort {
/** Typsichere Navigation direkt via AppScreen-Objekt. */
fun navigateToScreen(screen: AppScreen)
/** Gehe einen Schritt zurück im Verlauf. */
fun navigateBack()
}