Feature: Hilfe/FAQ, Übungen-Content, Navigation-Fixes (SW by-v727)
Hilfe & FAQ:
- Neue Seite /hilfe mit Akkordeon + Live-Suche (6 Kategorien, 25 Artikel)
- DB-Tabelle help_articles — Inhalte admin-seitig ohne Deploy änderbar
- Admin-Tab Hilfe/FAQ zum Bearbeiten aller Artikel
- Link in Einstellungen (unter Welten einrichten, über Abmelden)
- routes/help.py: GET (public), POST/PATCH/DELETE (Admin)
Übungen:
- 110 Übungen: beschreibung (kurz), schritte (JSON 4-6 Schritte), tipp — gutes Deutsch mit Umlauten
- Admin-Tab Übungen: Inline-Editor für alle drei Felder
- PUT /training/exercises/{id} (Admin) neu
- Übung-des-Tages Chip → scrollt jetzt korrekt zur Übung (exercise_id-Feldname-Fix)
Welten-Navigation:
- hide() stellt app-header + bottom-nav wieder her (worlds-hidden wurde nie entfernt)
- init() mit _setupDone-Guard (keine doppelten Event-Listener)
- Login ruft Worlds.init(_appState) statt show() — _state war null → falscher Render
- X-Button in Welten-Konfiguration: 30×30px, Icon 17px, besser sichtbar
Wetter:
- Motivation bei blockiertem Standort: 6-Schritte-iOS-Anleitung + Flugmodus-Tipp
- Auto-locate bleibt (kein Button-Only mehr)
achievements.py:
- my_achievements(): d.user_id → JOIN dogs (zweite Funktion war noch kaputt)
This commit is contained in:
parent
55069d246b
commit
05ecf3b94a
13 changed files with 1158 additions and 43 deletions
|
|
@ -14,6 +14,7 @@ window.Worlds = (() => {
|
|||
let _dogs = []; // gecachte Hundesliste
|
||||
let _dogIdx = 0; // aktuell angezeigter Hund
|
||||
let _hasBgPhoto = false; // Hintergrund-Foto vorhanden?
|
||||
let _setupDone = false; // Swipe/Button-Listener nur einmal registrieren
|
||||
|
||||
// Touch-Tracking
|
||||
const _t = { x:0, y:0, active:false, vert:null, moved:0 };
|
||||
|
|
@ -44,13 +45,17 @@ window.Worlds = (() => {
|
|||
// ── PUBLIC ──────────────────────────────────────────────────
|
||||
|
||||
async function init(appState) {
|
||||
_state = appState;
|
||||
_cur = 1; // immer HUND als Start
|
||||
_setupSwipe();
|
||||
_setupButtons();
|
||||
_state = appState;
|
||||
_lastUserId = undefined; // Neurender erzwingen
|
||||
_cur = 1;
|
||||
if (!_setupDone) {
|
||||
_setupDone = true;
|
||||
_setupSwipe();
|
||||
_setupButtons();
|
||||
_showSwipeHints();
|
||||
}
|
||||
_goTo(_cur, false);
|
||||
show();
|
||||
_showSwipeHints();
|
||||
}
|
||||
|
||||
function _showSwipeHints() {
|
||||
|
|
@ -133,6 +138,8 @@ window.Worlds = (() => {
|
|||
ov.classList.remove('worlds-visible');
|
||||
ov.style.display = 'none';
|
||||
_visible = false;
|
||||
document.getElementById('app-header')?.classList.remove('worlds-hidden');
|
||||
document.getElementById('bottom-nav')?.classList.remove('worlds-hidden');
|
||||
document.getElementById('worlds-back')?.classList.add('worlds-back-visible');
|
||||
}
|
||||
|
||||
|
|
@ -665,11 +672,11 @@ window.Worlds = (() => {
|
|||
user-select:none;-webkit-tap-highlight-color:transparent;touch-action:none">
|
||||
${!c.pinned ? `
|
||||
<button class="wc-remove" data-page="${c.page}" data-zone="${w}"
|
||||
style="position:absolute;top:-8px;right:-8px;width:24px;height:24px;
|
||||
border-radius:50%;background:#EF4444;border:2px solid rgba(18,22,32,0.9);
|
||||
style="position:absolute;top:-10px;right:-10px;width:30px;height:30px;
|
||||
border-radius:50%;background:#EF4444;border:3px solid rgba(18,22,32,0.95);
|
||||
cursor:pointer;display:flex;align-items:center;justify-content:center;
|
||||
z-index:2;box-shadow:0 2px 6px rgba(0,0,0,0.5)">
|
||||
<svg class="ph-icon" style="width:13px;height:13px;color:white">
|
||||
z-index:2;box-shadow:0 2px 8px rgba(0,0,0,0.7)">
|
||||
<svg class="ph-icon" style="width:17px;height:17px;color:white;stroke:white;stroke-width:1.5">
|
||||
<use href="/icons/phosphor.svg#x"></use>
|
||||
</svg>
|
||||
</button>` : `
|
||||
|
|
@ -1001,7 +1008,7 @@ window.Worlds = (() => {
|
|||
<span class="wj-chip-val" id="wj-route-val">…</span>
|
||||
${totalKm != null ? `<span style="font-size:9px;color:rgba(255,255,255,0.4);margin-top:1px">∑ ${totalKm} km</span>` : ''}
|
||||
</div>
|
||||
<div class="wj-chip" data-wnav="uebungen">
|
||||
<div class="wj-chip" id="wj-exercise-chip">
|
||||
<svg class="ph-icon" style="width:1.2rem;height:1.2rem;color:var(--c-primary)">
|
||||
<use href="/icons/phosphor.svg#barbell"></use></svg>
|
||||
<span class="wj-chip-label">Übung</span>
|
||||
|
|
@ -1034,6 +1041,17 @@ window.Worlds = (() => {
|
|||
const res = await _cachedGet(`dash_${dog.id}`, `/dogs/${dog.id}/welcome-dashboard`);
|
||||
const ex = res.data?.daily_exercise;
|
||||
valEl.textContent = ex?.name || '—';
|
||||
// Chip-Klick mit exercise_id/name damit übungen.js direkt dorthin scrollt
|
||||
const chip = document.getElementById('wj-exercise-chip');
|
||||
if (chip) {
|
||||
chip.style.cursor = 'pointer';
|
||||
chip.onclick = () => {
|
||||
hide();
|
||||
if (window.App) window.App.navigate('uebungen', true,
|
||||
ex ? { exercise_id: ex.exercise_id || '', name: ex.name || '' } : {}
|
||||
);
|
||||
};
|
||||
}
|
||||
} catch { valEl.textContent = '—'; }
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue