Passhistoriken visar passlängden i både listan och detaljvyn
All checks were successful
release / build-release (push) Successful in 5m43s
All checks were successful
release / build-release (push) Successful in 5m43s
Manuell tidsrättning (durationSecondsOverride) vinner, annars slut − start. Format: '47 min' eller '1h 12m'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kf4MAbZ3c3B4Xy5XfuGsCP
This commit is contained in:
@@ -420,7 +420,7 @@ class GymRepository(
|
||||
/** Full detalj för ett avslutat pass. */
|
||||
suspend fun fetchSessionDetail(id: Int): SessionDetail {
|
||||
val data = client.execute(
|
||||
"query(\$id:Int!){gymSession(id:\$id){id name notes date startTime estimatedCalories gymSessionExercises{order exerciseType{name} sets{order reps weight distanceMeters durationSeconds rpe isWarmup}}}}",
|
||||
"query(\$id:Int!){gymSession(id:\$id){id name notes date startTime endTime durationSecondsOverride estimatedCalories gymSessionExercises{order exerciseType{name} sets{order reps weight distanceMeters durationSeconds rpe isWarmup}}}}",
|
||||
buildJsonObject { put("id", id) },
|
||||
auth.bearerToken(),
|
||||
)
|
||||
@@ -432,6 +432,11 @@ class GymRepository(
|
||||
?: o["startTime"]?.jsonPrimitive?.contentOrNull()).orEmpty(),
|
||||
notes = o["notes"]?.jsonPrimitive?.contentOrNull(),
|
||||
calories = o["estimatedCalories"]?.jsonPrimitive?.doubleOrNull,
|
||||
durationMinutes = durationMinutes(
|
||||
o["durationSecondsOverride"]?.jsonPrimitive?.intOrNull,
|
||||
o["startTime"]?.jsonPrimitive?.contentOrNull(),
|
||||
o["endTime"]?.jsonPrimitive?.contentOrNull(),
|
||||
),
|
||||
exercises = o["gymSessionExercises"]!!.jsonArray
|
||||
.sortedBy { it.jsonObject["order"]?.jsonPrimitive?.intOrNull ?: 0 }
|
||||
.map { e ->
|
||||
@@ -621,7 +626,7 @@ class GymRepository(
|
||||
/** Historik hämtas direkt (ingen offline-garanti i v1). */
|
||||
suspend fun fetchHistory(limit: Int = 30): List<HistoryItem> {
|
||||
val data = client.execute(
|
||||
"query(\$s:String,\$l:Int){gymSessions(status:\$s,limit:\$l){id name date startTime durationSecondsOverride estimatedCalories gymSessionExercises{id sets{id weight reps}}}}",
|
||||
"query(\$s:String,\$l:Int){gymSessions(status:\$s,limit:\$l){id name date startTime endTime durationSecondsOverride estimatedCalories gymSessionExercises{id sets{id weight reps}}}}",
|
||||
buildJsonObject { put("s", "completed"); put("l", limit) },
|
||||
auth.bearerToken(),
|
||||
)
|
||||
@@ -641,9 +646,25 @@ class GymRepository(
|
||||
setCount = sets.size,
|
||||
volumeKg = volume,
|
||||
calories = o["estimatedCalories"]?.jsonPrimitive?.doubleOrNull,
|
||||
durationMinutes = durationMinutes(
|
||||
o["durationSecondsOverride"]?.jsonPrimitive?.intOrNull,
|
||||
o["startTime"]?.jsonPrimitive?.contentOrNull(),
|
||||
o["endTime"]?.jsonPrimitive?.contentOrNull(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Passlängd i minuter: manuell rättning vinner, annars slut − start. */
|
||||
private fun durationMinutes(overrideSeconds: Int?, start: String?, end: String?): Int? {
|
||||
overrideSeconds?.let { return it / 60 }
|
||||
if (start == null || end == null) return null
|
||||
return runCatching {
|
||||
val s = java.time.OffsetDateTime.parse(start)
|
||||
val e = java.time.OffsetDateTime.parse(end)
|
||||
java.time.Duration.between(s, e).toMinutes().toInt().takeIf { it >= 0 }
|
||||
}.getOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
data class HistoryItem(
|
||||
@@ -654,6 +675,7 @@ data class HistoryItem(
|
||||
val setCount: Int,
|
||||
val volumeKg: Double,
|
||||
val calories: Double?,
|
||||
val durationMinutes: Int? = null,
|
||||
)
|
||||
|
||||
data class HistorySet(
|
||||
@@ -672,6 +694,7 @@ data class SessionDetail(
|
||||
val date: String,
|
||||
val notes: String?,
|
||||
val calories: Double?,
|
||||
val durationMinutes: Int? = null,
|
||||
val exercises: List<SessionDetailExercise>,
|
||||
)
|
||||
|
||||
|
||||
@@ -162,7 +162,10 @@ fun HistoryDetailScreen(
|
||||
Text(
|
||||
buildString {
|
||||
append(d.date.take(10))
|
||||
stats?.durationMinutes?.let { append(" · $it min") }
|
||||
(d.durationMinutes ?: stats?.durationMinutes)?.let {
|
||||
append(" · ")
|
||||
append(if (it >= 60) "${it / 60}h ${it % 60}m" else "$it min")
|
||||
}
|
||||
if (stats != null) {
|
||||
append(" · ${stats.totalSets} set · ${stats.totalVolumeKg.toInt()} kg volym")
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ fun HistoryScreen(
|
||||
}
|
||||
Text(
|
||||
buildString {
|
||||
item.durationMinutes?.let {
|
||||
append(if (it >= 60) "${it / 60}h ${it % 60}m" else "$it min")
|
||||
append(" · ")
|
||||
}
|
||||
append("${item.exerciseCount} övningar · ${item.setCount} set")
|
||||
if (item.volumeKg > 0) append(" · ${item.volumeKg.toInt()} kg volym")
|
||||
item.calories?.let { append(" · ${it.toInt()} kcal") }
|
||||
|
||||
Reference in New Issue
Block a user