feat: redesign EventCard with color border, type badge, leading icons

- 4dp colored border from event.color (fallback primary)
- AssistChip badge: Match (teal) vs Entraînement (slate)
- Opponent line only for games, 'Entraînement' for practices
- Place and Schedule icons leading info lines
- Condensed time range via formatEventTimeRange
This commit is contained in:
2026-08-06 17:07:11 +02:00
parent 06d2eceba3
commit e5c0a1183d
@@ -17,24 +17,33 @@
package ch.parano.myicek.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Place
import androidx.compose.material.icons.filled.Schedule
import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
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
import ch.parano.myicek.models.Event
import ch.parano.myicek.util.formatEventDateTime
import ch.parano.myicek.ui.theme.Dimens
import ch.parano.myicek.util.formatEventTimeRange
@Composable
fun EventCard(
@@ -42,6 +51,7 @@ fun EventCard(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val isGame = event.eventType == "Jeu"
val stripeColor = event.color?.let { parseHexColor(it) }
?: MaterialTheme.colorScheme.primary
@@ -49,44 +59,93 @@ fun EventCard(
onClick = onClick,
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
.padding(horizontal = Dimens.lg, vertical = Dimens.sm),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp),
) {
Row {
Box(
Row(
modifier = Modifier
.width(4.dp)
.fillMaxHeight()
.background(stripeColor),
)
.fillMaxWidth()
.border(width = 4.dp, color = stripeColor),
) {
Column(
modifier = Modifier
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
.fillMaxWidth()
.padding(Dimens.lg),
verticalArrangement = Arrangement.spacedBy(Dimens.xs),
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "${event.agegroup} - ${event.name}",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.weight(1f),
)
AssistChip(
onClick = {},
label = {
Text(
text = event.title,
if (isGame) "Match" else "Entraînement",
style = MaterialTheme.typography.labelMedium,
)
},
colors = if (isGame) {
AssistChipDefaults.assistChipColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
labelColor = MaterialTheme.colorScheme.onPrimaryContainer,
)
} else {
AssistChipDefaults.assistChipColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
labelColor = MaterialTheme.colorScheme.onSecondaryContainer,
)
},
)
}
Text(
text = if (isGame) "Match vs ${event.opponent}" else "Entraînement",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Spacer(Modifier.height(Dimens.xs))
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Dimens.xs),
) {
Icon(
imageVector = Icons.Filled.Place,
contentDescription = null,
modifier = Modifier.width(18.dp).height(18.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
text = "Adversaire: ${event.opponent}",
style = MaterialTheme.typography.bodySmall,
text = event.place,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Dimens.xs),
) {
Icon(
imageVector = Icons.Filled.Schedule,
contentDescription = null,
modifier = Modifier.width(18.dp).height(18.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
text = "Lieu: ${event.place}",
style = MaterialTheme.typography.bodySmall,
)
Text(
text = "Date: ${formatEventDateTime(event.start, event.end)}",
text = formatEventTimeRange(event.start, event.end),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
}
}
private fun parseHexColor(hex: String): Color? {
val value = hex.removePrefix("#").toLongOrNull(16) ?: return null