feat(design-system): add MsValidationWrapper component and update roadmap

- Introduced `MsValidationWrapper` for consistent display of validation messages (errors, warnings, info) in input components.
- Updated `Frontend_Komponenten_Roadmap.md` to mark this component as complete in Phase 3.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-03-31 10:42:36 +02:00
parent 340f341594
commit 442caa59ff
2 changed files with 95 additions and 1 deletions
@@ -0,0 +1,94 @@
package at.mocode.frontend.core.designsystem.components
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ErrorOutline
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.WarningAmber
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
/**
* Die Schwere einer Validierungsmeldung.
*/
enum class ValidationSeverity {
ERROR, // Blokierend (z.B. fehlende Pflichtfelder)
WARNING, // Hinweisend (z.B. § 39 ÖTO - Abteilungstrennung steht bevor)
INFO // Informativ (z.B. Reiter hat heute Geburtstag)
}
/**
* Eine einzelne Validierungsmeldung.
*/
data class ValidationMessage(
val message: String,
val severity: ValidationSeverity = ValidationSeverity.ERROR
)
/**
* Ein Wrapper für Eingabekomponenten, um Validierungsergebnisse (ÖTO-Regeln) anzuzeigen.
*
* @param messages Liste der anzuzeigenden Meldungen.
* @param modifier Der Modifier für den äußeren Container.
* @param content Die Eingabekomponente (z.B. MsTextField, MsEnumDropdown).
*/
@Composable
fun MsValidationWrapper(
messages: List<ValidationMessage>,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Column(modifier = modifier) {
// Die eigentliche Eingabekomponente
content()
// Validierungsmeldungen unterhalb
if (messages.isNotEmpty()) {
Column(
modifier = Modifier
.padding(top = 4.dp, start = 12.dp)
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
messages.forEach { msg ->
ValidationRow(msg)
}
}
}
}
}
/**
* Eine einzelne Zeile für eine Validierungsmeldung mit passendem Icon und Farbe.
*/
@Composable
private fun ValidationRow(msg: ValidationMessage) {
val (color, icon) = when (msg.severity) {
ValidationSeverity.ERROR -> MaterialTheme.colorScheme.error to Icons.Default.ErrorOutline
ValidationSeverity.WARNING -> Color(0xFFEF6C00) to Icons.Default.WarningAmber // Warmer Orange-Ton
ValidationSeverity.INFO -> MaterialTheme.colorScheme.primary to Icons.Default.Info
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.size(14.dp),
tint = color
)
Text(
text = msg.message,
style = MaterialTheme.typography.labelSmall,
color = color
)
}
}