Etapp 4: mål & progress-mätare på hemskärmen
All checks were successful
release / build-release (push) Successful in 6m52s

- Målkort på Hem: alla mål med progress-bars (aktuellt/mål), tryck →
  målskärmen med sätt/uppdatera/ta bort (metrik × period × värde)
- Metriker: aktiva kalorier, gympass, aktiviteter, distans km, steg
  (stegdata kommer i etapp 5); perioder: dag/vecka/månad
- GymApi: goalsWithProgress (lokala periodstarter som instants) + setGoal
- Version 0.9.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C2GA94E1f3cmrvdQLQhYdg
This commit is contained in:
2026-08-26 11:56:05 +02:00
parent 53e4f14b67
commit 49da9190b6
7 changed files with 379 additions and 3 deletions

View File

@@ -47,6 +47,15 @@ data class DailySummary(
val steps: Int? = null,
)
@Serializable
data class GoalProgress(
val id: Int,
val metric: String,
val period: String,
val targetValue: Double,
val currentValue: Double,
)
@Serializable
data class Profile(
val username: String,
@@ -196,6 +205,33 @@ class GymApi(
return client.json.decodeFromJsonElement(data["dailySummary"]!!)
}
/* ---------- Mål ---------- */
/** Mål med progress; klienten skickar sina lokala periodstarter som instants. */
suspend fun goalsWithProgress(
dayStartIso: String,
weekStartIso: String,
monthStartIso: String,
): List<GoalProgress> {
val data = client.execute(
"query(\$d:DateTime!,\$w:DateTime!,\$m:DateTime!){goalsWithProgress(dayStart:\$d,weekStart:\$w,monthStart:\$m){id metric period targetValue currentValue}}",
buildJsonObject {
put("d", dayStartIso); put("w", weekStartIso); put("m", monthStartIso)
},
auth.bearerToken(),
)
return data["goalsWithProgress"]!!.jsonArray.map { client.json.decodeFromJsonElement<GoalProgress>(it) }
}
/** targetValue <= 0 tar bort målet. */
suspend fun setGoal(metric: String, period: String, targetValue: Double) {
client.execute(
"mutation(\$m:String!,\$p:String!,\$t:Float!){setGoal(metric:\$m,period:\$p,targetValue:\$t)}",
buildJsonObject { put("m", metric); put("p", period); put("t", targetValue) },
auth.bearerToken(),
)
}
companion object {
private const val ACTIVITY_FIELDS =
"id startedAt durationSeconds distanceMeters elevationGainMeters estimatedKcal rpe source notes " +