Passhistoriken visar passlängden i både listan och detaljvyn
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:
2026-07-25 17:00:23 +02:00
parent 34c2a6c4da
commit bb3502ed26
3 changed files with 33 additions and 3 deletions

View File

@@ -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>,
)

View File

@@ -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")
}

View File

@@ -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") }