From d9a0be489b1d7ffafe97bc30c3c7956f41081088 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 29 Apr 2026 09:26:41 +0200 Subject: [PATCH] =?UTF-8?q?Feature:=20=C3=9Cbung=20des=20Tages=20=E2=80=94?= =?UTF-8?q?=20personalisiert=20aus=20exercise=5Fprogress,=204.=20Chip=20au?= =?UTF-8?q?f=20Welcome=20=E2=80=94=20SW=20by-v481,=20APP=5FVER=20458?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/routes/dogs.py | 40 ++++++++++++++++++++---------- backend/static/js/app.js | 2 +- backend/static/js/pages/welcome.js | 7 ++++++ backend/static/sw.js | 2 +- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/backend/routes/dogs.py b/backend/routes/dogs.py index db0da2e..9fb6b2c 100644 --- a/backend/routes/dogs.py +++ b/backend/routes/dogs.py @@ -157,20 +157,34 @@ async def get_welcome_dashboard(dog_id: int, user=Depends(get_current_user)): "SELECT COUNT(*) AS n FROM diary WHERE dog_id=?", (dog_id,) ).fetchone()["n"] - # Tagesübung — stabil pro Tag, rotiert täglich - exercise_count = conn.execute( - "SELECT COUNT(*) AS n FROM training_exercises" - ).fetchone()["n"] + # Tagesübung — personalisiert aus exercise_progress, tagesstabil + import datetime as _dt + day_num = (_dt.date.today() - _dt.date(2024, 1, 1)).days + + # Übungen in Bearbeitung (noch-nicht / manchmal / meistens), älteste zuerst + in_progress = conn.execute( + """SELECT ep.exercise_id, te.name, te.kategorie, te.schwierigkeit + FROM exercise_progress ep + JOIN training_exercises te ON te.exercise_id = ep.exercise_id + WHERE ep.user_id = ? AND ep.status IN ('noch-nicht', 'manchmal', 'meistens') + ORDER BY ep.updated_at ASC LIMIT 20""", + (user["id"],) + ).fetchall() + daily_exercise = None - if exercise_count: - import datetime as _dt - day_num = (_dt.date.today() - _dt.date(2024, 1, 1)).days - offset = day_num % exercise_count - ex_row = conn.execute( - "SELECT exercise_id, name, kategorie, schwierigkeit FROM training_exercises ORDER BY id LIMIT 1 OFFSET ?", - (offset,) - ).fetchone() - daily_exercise = dict(ex_row) if ex_row else None + if in_progress: + daily_exercise = dict(in_progress[day_num % len(in_progress)]) + else: + # Fallback: globale Rotation über alle Übungen + exercise_count = conn.execute( + "SELECT COUNT(*) AS n FROM training_exercises" + ).fetchone()["n"] + if exercise_count: + ex_row = conn.execute( + "SELECT exercise_id, name, kategorie, schwierigkeit FROM training_exercises ORDER BY id LIMIT 1 OFFSET ?", + (day_num % exercise_count,) + ).fetchone() + daily_exercise = dict(ex_row) if ex_row else None return { "random_photo": random_photo, diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 8c3b3a2..0255aa4 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '457'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '458'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const App = (() => { diff --git a/backend/static/js/pages/welcome.js b/backend/static/js/pages/welcome.js index 1300d55..875fbec 100644 --- a/backend/static/js/pages/welcome.js +++ b/backend/static/js/pages/welcome.js @@ -346,6 +346,7 @@ window.Page_welcome = (() => { const diaryText = diaryDate ? (_relDate(diaryDate) || diaryDate) : '—'; const weight = dashData?.last_weight; const weightVal = weight ? `${weight.wert} ${weight.einheit}` : '—'; + const ex = dashData?.daily_exercise; return `
@@ -360,6 +361,12 @@ window.Page_welcome = (() => { Gewicht ${weightVal}
+ ${ex ? ` +
+ + Übung des Tages + ${UI.escape(ex.name)} +
` : ''} `; } diff --git a/backend/static/sw.js b/backend/static/sw.js index d2486a9..3da4473 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v480'; +const CACHE_VERSION = 'by-v481'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten