L'hydratation est un total, pas une jauge

Décision de l'utilisateur : pas d'objectif de boisson, juste la consommation du
jour. Le code qui attendait un objectif pour afficher une barre est retiré,
champ de snapshot compris — un conditionnel qui ne se déclenchera jamais est une
fausse promesse, et le prochain lecteur y verrait une fonctionnalité en attente.

Le widget affiche « 1,2 L bue aujourd'hui ». Seule l'énergie garde sa jauge :
elle est la seule à avoir une cible fixée (1950 kcal).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Sylvain Bettinelli
2026-08-06 13:47:05 +00:00
parent 5eafa14b99
commit b2b3c10807
2 changed files with 11 additions and 23 deletions

View File

@@ -59,12 +59,6 @@ struct CoachWidgetSnapshot: Codable {
var kcalToday: Double? var kcalToday: Double?
var kcalGoal: Double? var kcalGoal: Double?
/// Objectif d'hydratation, en millilitres. **Optionnel et sans valeur par
/// défaut** : aucun objectif d'hydratation n'est défini dans les objectifs
/// nutritionnels. Tant qu'il vaut nil, le widget affiche le volume bu sans
/// barre une jauge sur un objectif inventé donnerait un pourcentage qui ne
/// veut rien dire.
var waterGoalMl: Double?
/// Séance planifiée du jour (nil = jour OFF / pas de séance). /// Séance planifiée du jour (nil = jour OFF / pas de séance).
struct TodaySession: Codable { struct TodaySession: Codable {

View File

@@ -62,14 +62,13 @@ struct CoachQuickEntryTimeline: TimelineEntry {
let pending: Int let pending: Int
let kcal: Double? let kcal: Double?
let kcalGoal: Double? let kcalGoal: Double?
let waterGoal: Double?
} }
struct CoachQuickProvider: TimelineProvider { struct CoachQuickProvider: TimelineProvider {
func placeholder(in context: Context) -> CoachQuickEntryTimeline { func placeholder(in context: Context) -> CoachQuickEntryTimeline {
CoachQuickEntryTimeline( CoachQuickEntryTimeline(
date: Date(), waterMl: 1250, coffeeCount: 2, pending: 0, date: Date(), waterMl: 1250, coffeeCount: 2, pending: 0,
kcal: 1420, kcalGoal: 1950, waterGoal: 2000 kcal: 1420, kcalGoal: 1950
) )
} }
@@ -99,8 +98,7 @@ struct CoachQuickProvider: TimelineProvider {
coffeeCount: CoachQuickLog.todayCount(kind: "coffee", syncedCount: syncedCoffee), coffeeCount: CoachQuickLog.todayCount(kind: "coffee", syncedCount: syncedCoffee),
pending: CoachQuickLog.pending().count, pending: CoachQuickLog.pending().count,
kcal: snapshot?.kcalToday, kcal: snapshot?.kcalToday,
kcalGoal: snapshot?.kcalGoal, kcalGoal: snapshot?.kcalGoal
waterGoal: snapshot?.waterGoalMl
) )
} }
} }
@@ -126,24 +124,20 @@ struct CoachQuickWidgetView: View {
.lineLimit(1) .lineLimit(1)
.minimumScaleFactor(0.8) .minimumScaleFactor(0.8)
// Deux jauges : hydratation et énergie. La barre n'apparaît que si // Hydratation en total, énergie en jauge : seule l'énergie a un
// un objectif existe une jauge sur un objectif inventé donnerait // objectif fixé (1950 kcal). Une barre suppose une cible ; sans
// un pourcentage qui ne veut rien dire. // cible, un chiffre dit plus qu'un pourcentage inventé.
VStack(alignment: .leading, spacing: 3) { VStack(alignment: .leading, spacing: 3) {
// Hydratation : un TOTAL, pas une jauge. Décision assumée
// aucun objectif de boisson n'est fixé, et en inventer un
// donnerait un pourcentage qui n'a pas de sens.
HStack(spacing: 6) { HStack(spacing: 6) {
Text("\(litres) L") Text("\(litres) L")
.font(.system(.subheadline, design: .rounded).weight(.semibold)) .font(.system(.subheadline, design: .rounded).weight(.semibold))
.monospacedDigit() .monospacedDigit()
if let goal = entry.waterGoal, goal > 0 { Text("bue aujourd'hui")
ProgressView(value: min(entry.waterMl / goal, 1)) .font(.caption2).foregroundStyle(.secondary)
.tint(.blue) Spacer()
Text("\(Int(goal / 1000)) L")
.font(.caption2).foregroundStyle(.tertiary).monospacedDigit()
} else {
Text("bue aujourd'hui")
.font(.caption2).foregroundStyle(.secondary)
Spacer()
}
} }
if let kcal = entry.kcal { if let kcal = entry.kcal {