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 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.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row 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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width 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.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ch.parano.myicek.models.Event 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 @Composable
fun EventCard( fun EventCard(
@@ -42,6 +51,7 @@ fun EventCard(
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val isGame = event.eventType == "Jeu"
val stripeColor = event.color?.let { parseHexColor(it) } val stripeColor = event.color?.let { parseHexColor(it) }
?: MaterialTheme.colorScheme.primary ?: MaterialTheme.colorScheme.primary
@@ -49,44 +59,93 @@ fun EventCard(
onClick = onClick, onClick = onClick,
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = Dimens.lg, vertical = Dimens.sm),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp),
) { ) {
Row { Row(
Box(
modifier = Modifier modifier = Modifier
.width(4.dp) .fillMaxWidth()
.fillMaxHeight() .border(width = 4.dp, color = stripeColor),
.background(stripeColor), ) {
)
Column( Column(
modifier = Modifier modifier = Modifier
.padding(16.dp), .fillMaxWidth()
verticalArrangement = Arrangement.spacedBy(4.dp), .padding(Dimens.lg),
verticalArrangement = Arrangement.spacedBy(Dimens.xs),
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = "${event.agegroup} - ${event.name}", text = "${event.agegroup} - ${event.name}",
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
modifier = Modifier.weight(1f),
) )
AssistChip(
onClick = {},
label = {
Text( 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, 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(
text = "Adversaire: ${event.opponent}", text = event.place,
style = MaterialTheme.typography.bodySmall, 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(
text = "Lieu: ${event.place}", text = formatEventTimeRange(event.start, event.end),
style = MaterialTheme.typography.bodySmall,
)
Text(
text = "Date: ${formatEventDateTime(event.start, event.end)}",
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
} }
} }
} }
} }
}
private fun parseHexColor(hex: String): Color? { private fun parseHexColor(hex: String): Color? {
val value = hex.removePrefix("#").toLongOrNull(16) ?: return null val value = hex.removePrefix("#").toLongOrNull(16) ?: return null