Statistik: favoritövningar överst i PB-listan (stjärna på korten, återanvänder toggleFavoriteExercise)
All checks were successful
release / build-release (push) Successful in 4m31s
All checks were successful
release / build-release (push) Successful in 4m31s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFvSx1pF9pymyEuK7MFkEG
This commit is contained in:
@@ -302,7 +302,7 @@ class GymRepository(
|
||||
/** PB-lista med detaljer per rekord. mode: all | competition | training. */
|
||||
suspend fun personalBestsDetailed(mode: String = "all"): List<PbEntry> {
|
||||
val pb = client.execute(
|
||||
"query(\$m:String){personalBests(mode:\$m){exerciseTypeId exerciseTypeName repRecords{reps weight date liftId notes status statusNote sessionName estimated1Rm}}}",
|
||||
"query(\$m:String){personalBests(mode:\$m){exerciseTypeId exerciseTypeName isFavorite repRecords{reps weight date liftId notes status statusNote sessionName estimated1Rm}}}",
|
||||
buildJsonObject { put("m", mode) },
|
||||
auth.bearerToken(),
|
||||
)
|
||||
@@ -311,6 +311,7 @@ class GymRepository(
|
||||
PbEntry(
|
||||
exerciseName = po["exerciseTypeName"]?.jsonPrimitive?.contentOrNull() ?: "Övning",
|
||||
exerciseTypeId = po["exerciseTypeId"]?.jsonPrimitive?.intOrNull ?: 0,
|
||||
isFavorite = po["isFavorite"]?.jsonPrimitive?.booleanOrNull ?: false,
|
||||
records = po["repRecords"]!!.jsonArray.mapNotNull { r ->
|
||||
val ro = r.jsonObject
|
||||
PbRecord(
|
||||
@@ -326,7 +327,7 @@ class GymRepository(
|
||||
)
|
||||
}.sortedBy { it.reps },
|
||||
)
|
||||
}.sortedBy { it.exerciseName }
|
||||
}.sortedWith(compareByDescending<PbEntry> { it.isFavorite }.thenBy { it.exerciseName })
|
||||
}
|
||||
|
||||
/** Topplista för övning × reps, alla statusar (så bortplockade kan återställas). */
|
||||
@@ -944,7 +945,13 @@ data class PbRecord(
|
||||
val sessionName: String? = null,
|
||||
val est1Rm: Double = 0.0,
|
||||
)
|
||||
data class PbEntry(val exerciseName: String, val records: List<PbRecord>, val exerciseTypeId: Int = 0)
|
||||
data class PbEntry(
|
||||
val exerciseName: String,
|
||||
val records: List<PbRecord>,
|
||||
val exerciseTypeId: Int = 0,
|
||||
/** Favoritövning (samma FavoriteExercise som övningsväljaren) – ligger överst i PB-listan. */
|
||||
val isFavorite: Boolean = false,
|
||||
)
|
||||
|
||||
/** Ett lyft med allt PB-arket behöver (pbCandidates / liftDetail). */
|
||||
data class LiftDetail(
|
||||
|
||||
@@ -5,6 +5,8 @@ import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material.icons.outlined.StarOutline
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -145,6 +147,15 @@ class StatsViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
/** Favorit av/på för en övning: optimistisk omsortering, servern uppdateras i bakgrunden. */
|
||||
fun togglePbFavorite(entry: eu.brassepc.fitnessdroid.data.PbEntry) {
|
||||
val next = !entry.isFavorite
|
||||
pbs.value = pbs.value
|
||||
.map { if (it.exerciseTypeId == entry.exerciseTypeId) it.copy(isFavorite = next) else it }
|
||||
.sortedWith(compareByDescending<eu.brassepc.fitnessdroid.data.PbEntry> { it.isFavorite }.thenBy { it.exerciseName })
|
||||
repo.toggleFavoriteExercise(entry.exerciseTypeId, next)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||
initializer {
|
||||
@@ -408,8 +419,18 @@ fun StatsScreen(viewModel: StatsViewModel = viewModel(factory = StatsViewModel.F
|
||||
}
|
||||
items(pbs, key = { "${it.exerciseTypeId}-${it.exerciseName}" }) { pb ->
|
||||
Card(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(modifier = Modifier.padding(14.dp)) {
|
||||
Text(pb.exerciseName, style = MaterialTheme.typography.titleSmall)
|
||||
Column(modifier = Modifier.padding(start = 14.dp, end = 6.dp, top = 4.dp, bottom = 14.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(pb.exerciseName, style = MaterialTheme.typography.titleSmall, modifier = Modifier.weight(1f))
|
||||
// Favorit = ligger överst (samma favoriter som övningsväljaren)
|
||||
androidx.compose.material3.IconButton(onClick = { viewModel.togglePbFavorite(pb) }) {
|
||||
androidx.compose.material3.Icon(
|
||||
if (pb.isFavorite) Icons.Filled.Star else Icons.Outlined.StarOutline,
|
||||
contentDescription = if (pb.isFavorite) "Ta bort favorit" else "Gör till favorit",
|
||||
tint = if (pb.isFavorite) MaterialTheme.colorScheme.tertiary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = 6.dp)
|
||||
|
||||
Reference in New Issue
Block a user