diff --git a/sharedUI/src/commonMain/kotlin/com/livrets/ui/HistoryScreen.kt b/sharedUI/src/commonMain/kotlin/com/livrets/ui/HistoryScreen.kt index 6d47275..f8a7a36 100644 --- a/sharedUI/src/commonMain/kotlin/com/livrets/ui/HistoryScreen.kt +++ b/sharedUI/src/commonMain/kotlin/com/livrets/ui/HistoryScreen.kt @@ -1,14 +1,138 @@ package com.livrets.ui +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.WindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.livrets.data.HistoryRepository +import com.livrets.game.GameResult +import com.livrets.game.TableStats +import com.livrets.game.tableStats +import kotlin.time.Instant @Composable -fun HistoryScreen(history: HistoryRepository, onBack: () -> Unit) { - Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Historique") } +fun HistoryScreen( + history: HistoryRepository, + onBack: () -> Unit, +) { + var tab by remember { mutableIntStateOf(0) } + var games by remember { mutableStateOf>(emptyList()) } + + LaunchedEffect(Unit) { games = history.load() } + + Column( + modifier = Modifier + .fillMaxSize() + .windowInsetsPadding(WindowInsets.safeDrawing) + .padding(24.dp), + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + TextButton(onClick = onBack) { Text("←") } + Text("Historique", style = MaterialTheme.typography.headlineSmall) + } + + TabRow(selectedTabIndex = tab) { + Tab(selected = tab == 0, onClick = { tab = 0 }, text = { Text("Parties") }) + Tab(selected = tab == 1, onClick = { tab = 1 }, text = { Text("Tables") }) + } + + when (tab) { + 0 -> Box(Modifier.weight(1f)) { GamesTab(games) } + else -> Box(Modifier.weight(1f)) { TablesTab(games.tableStats()) } + } + } +} + +private fun formatDate(date: Instant): String = + date.toString().take(16).replace('T', ' ') + +@Composable +private fun GamesTab(games: List) { + if (games.isEmpty()) { + Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Aucune partie enregistrée") + } + return + } + LazyColumn { + items(games.asReversed()) { game -> + Column(Modifier.fillMaxWidth().padding(vertical = 8.dp)) { + Text( + text = "${game.correctCount} / ${game.records.size}", + style = MaterialTheme.typography.titleLarge, + ) + Text( + text = formatDate(game.date), + style = MaterialTheme.typography.bodySmall, + ) + Text( + text = "${game.config.questionCount} questions · ${game.config.secondsPerQuestion} s par question · jusqu'à la table de ${game.config.maxTable}", + style = MaterialTheme.typography.bodySmall, + ) + HorizontalDivider(modifier = Modifier.padding(top = 8.dp)) + } + } + } +} + +@Composable +private fun TablesTab(stats: List) { + LazyColumn { + items(stats) { stat -> + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = "Table de ${stat.table}", + modifier = Modifier.width(110.dp), + style = MaterialTheme.typography.bodyMedium, + ) + if (stat.attempts == 0) { + LinearProgressIndicator( + progress = { 0f }, + modifier = Modifier.weight(1f), + ) + Text("—", modifier = Modifier.padding(start = 8.dp)) + } else { + LinearProgressIndicator( + progress = { stat.successRate.toFloat() }, + modifier = Modifier.weight(1f), + color = if (stat.successRate < 0.6) MaterialTheme.colorScheme.error + else MaterialTheme.colorScheme.primary, + ) + Text( + text = "${(stat.successRate * 100).toInt()} %", + modifier = Modifier.padding(start = 8.dp), + ) + } + } + } + } }