Add audit logging for Zeitplan updates, implement conflict validation for overlapping schedules and judge assignments, and enhance frontend with detailed warning visualizations in Zeitplan tab.

This commit is contained in:
2026-04-11 21:00:14 +02:00
parent bc46054412
commit 3515d40fcb
11 changed files with 176 additions and 9 deletions
@@ -1,9 +1,11 @@
package at.mocode.turnier.feature.data.mapper
import at.mocode.turnier.feature.data.remote.dto.AbteilungDto
import at.mocode.turnier.feature.data.remote.dto.AbteilungsWarnungDto
import at.mocode.turnier.feature.data.remote.dto.BewerbDto
import at.mocode.turnier.feature.data.remote.dto.TurnierDto
import at.mocode.turnier.feature.domain.Abteilung
import at.mocode.turnier.feature.domain.AbteilungsWarnung
import at.mocode.turnier.feature.domain.Bewerb
import at.mocode.turnier.feature.domain.Turnier
@@ -25,6 +27,7 @@ fun BewerbDto.toDomain(): Bewerb = Bewerb(
umbauMinuten = umbauMinuten,
besichtigungMinuten = besichtigungMinuten,
austragungsplatzId = austragungsplatzId,
warnungen = warnungen.map { AbteilungsWarnung(it.code, it.nachricht, it.oetoParagraph) }
)
fun Bewerb.toDto(): BewerbDto = BewerbDto(
@@ -42,6 +45,7 @@ fun Bewerb.toDto(): BewerbDto = BewerbDto(
umbauMinuten = umbauMinuten,
besichtigungMinuten = besichtigungMinuten,
austragungsplatzId = austragungsplatzId,
warnungen = warnungen.map { AbteilungsWarnungDto(it.code, it.nachricht, it.oetoParagraph) }
)
fun AbteilungDto.toDomain(): Abteilung = Abteilung(id = id, bewerbId = bewerbId, name = name)
@@ -24,6 +24,14 @@ data class BewerbDto(
val umbauMinuten: Int? = null,
val besichtigungMinuten: Int? = null,
val austragungsplatzId: String? = null,
val warnungen: List<AbteilungsWarnungDto> = emptyList(),
)
@Serializable
data class AbteilungsWarnungDto(
val code: String,
val nachricht: String,
val oetoParagraph: String? = null,
)
@Serializable
@@ -1,6 +1,5 @@
package at.mocode.turnier.feature.presentation
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -11,7 +10,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.koin.compose.koinInject
import org.koin.core.parameter.parametersOf
@@ -61,7 +61,8 @@ fun ZeitplanTabContent(
"SPRINGEN" -> Color(0xFF059669)
else -> ZeitplanBlue
},
hasConflict = bewerb.warnungen.isNotEmpty()
hasConflict = bewerb.warnungen.isNotEmpty(),
conflictMessage = bewerb.warnungen.joinToString("\n") { it.nachricht }
)
}
@@ -246,7 +247,13 @@ private fun DraggableBewerbBox(
) {
Text("⚠️", fontSize = 12.sp)
Spacer(Modifier.width(4.dp))
Text("Konflikt", fontSize = 10.sp, color = Color.Red, fontWeight = FontWeight.Bold)
Text(
text = item.conflictMessage.ifEmpty { "Konflikt" },
fontSize = 10.sp,
color = Color.Red,
fontWeight = FontWeight.Bold,
maxLines = 1
)
}
}
}
@@ -260,7 +267,8 @@ data class ZeitplanItemUi(
val startMinutes: Int, // Minuten seit 00:00
val durationMinutes: Int,
val color: Color = ZeitplanBlue,
val hasConflict: Boolean = false
val hasConflict: Boolean = false,
val conflictMessage: String = ""
) {
val timeString: String
get() {