Feature: Übung des Tages — personalisiert aus exercise_progress, 4. Chip auf Welcome — SW by-v481, APP_VER 458
This commit is contained in:
parent
7048499624
commit
d9a0be489b
4 changed files with 36 additions and 15 deletions
|
|
@ -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,)
|
"SELECT COUNT(*) AS n FROM diary WHERE dog_id=?", (dog_id,)
|
||||||
).fetchone()["n"]
|
).fetchone()["n"]
|
||||||
|
|
||||||
# Tagesübung — stabil pro Tag, rotiert täglich
|
# Tagesübung — personalisiert aus exercise_progress, tagesstabil
|
||||||
exercise_count = conn.execute(
|
import datetime as _dt
|
||||||
"SELECT COUNT(*) AS n FROM training_exercises"
|
day_num = (_dt.date.today() - _dt.date(2024, 1, 1)).days
|
||||||
).fetchone()["n"]
|
|
||||||
|
# Ü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
|
daily_exercise = None
|
||||||
if exercise_count:
|
if in_progress:
|
||||||
import datetime as _dt
|
daily_exercise = dict(in_progress[day_num % len(in_progress)])
|
||||||
day_num = (_dt.date.today() - _dt.date(2024, 1, 1)).days
|
else:
|
||||||
offset = day_num % exercise_count
|
# Fallback: globale Rotation über alle Übungen
|
||||||
ex_row = conn.execute(
|
exercise_count = conn.execute(
|
||||||
"SELECT exercise_id, name, kategorie, schwierigkeit FROM training_exercises ORDER BY id LIMIT 1 OFFSET ?",
|
"SELECT COUNT(*) AS n FROM training_exercises"
|
||||||
(offset,)
|
).fetchone()["n"]
|
||||||
).fetchone()
|
if exercise_count:
|
||||||
daily_exercise = dict(ex_row) if ex_row else None
|
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 {
|
return {
|
||||||
"random_photo": random_photo,
|
"random_photo": random_photo,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
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 = (() => {
|
const App = (() => {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ window.Page_welcome = (() => {
|
||||||
const diaryText = diaryDate ? (_relDate(diaryDate) || diaryDate) : '—';
|
const diaryText = diaryDate ? (_relDate(diaryDate) || diaryDate) : '—';
|
||||||
const weight = dashData?.last_weight;
|
const weight = dashData?.last_weight;
|
||||||
const weightVal = weight ? `${weight.wert} ${weight.einheit}` : '—';
|
const weightVal = weight ? `${weight.wert} ${weight.einheit}` : '—';
|
||||||
|
const ex = dashData?.daily_exercise;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="wc-chips" id="wc-chips-row">
|
<div class="wc-chips" id="wc-chips-row">
|
||||||
|
|
@ -360,6 +361,12 @@ window.Page_welcome = (() => {
|
||||||
<span class="wc-chip-label">Gewicht</span>
|
<span class="wc-chip-label">Gewicht</span>
|
||||||
<span class="wc-chip-val${weight ? '' : ' wc-chip-val--empty'}">${weightVal}</span>
|
<span class="wc-chip-val${weight ? '' : ' wc-chip-val--empty'}">${weightVal}</span>
|
||||||
</div>
|
</div>
|
||||||
|
${ex ? `
|
||||||
|
<div class="wc-chip" data-nav="uebungen">
|
||||||
|
<svg class="ph-icon wc-chip-icon" aria-hidden="true"><use href="/icons/phosphor.svg#target"></use></svg>
|
||||||
|
<span class="wc-chip-label">Übung des Tages</span>
|
||||||
|
<span class="wc-chip-val">${UI.escape(ex.name)}</span>
|
||||||
|
</div>` : ''}
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications + Tile-Cache
|
Offline-Cache + Push Notifications + Tile-Cache
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v480';
|
const CACHE_VERSION = 'by-v481';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue