feat: historique des parties et statistiques de réussite par table
This commit is contained in:
1 file changed
+126
-2
@@ -1,14 +1,138 @@
|
|||||||
package com.livrets.ui
|
package com.livrets.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
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.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.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import com.livrets.data.HistoryRepository
|
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
|
@Composable
|
||||||
fun HistoryScreen(history: HistoryRepository, onBack: () -> Unit) {
|
fun HistoryScreen(
|
||||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Historique") }
|
history: HistoryRepository,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
) {
|
||||||
|
var tab by remember { mutableIntStateOf(0) }
|
||||||
|
var games by remember { mutableStateOf<List<GameResult>>(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<GameResult>) {
|
||||||
|
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<TableStats>) {
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user