diff --git a/backend/routes/dogs.py b/backend/routes/dogs.py index 9c414d8..1c37b99 100644 --- a/backend/routes/dogs.py +++ b/backend/routes/dogs.py @@ -232,42 +232,15 @@ async def get_welcome_dashboard(dog_id: int, user=Depends(get_current_user)): ORDER BY d.datum DESC, d.id DESC, dm.id ASC""", (dog_id,) ).fetchall() - # Cross-Plattform-stabiles Tagesfoto: einmal pro Tag pro Hund festgelegt - # und in daily_photo_cache persistiert. Sobald ein Client (PWA oder - # iOS) zum ersten Mal heute zugreift, wird die Wahl gespeichert; alle - # weiteren Clients liefern dasselbe Bild. - import datetime as _dt2 - conn.execute(""" - CREATE TABLE IF NOT EXISTS daily_photo_cache ( - dog_id INTEGER NOT NULL, - datum TEXT NOT NULL, - photo_url TEXT NOT NULL, - PRIMARY KEY (dog_id, datum) - ) - """) - today_iso = _dt2.date.today().isoformat() - cached = conn.execute( - "SELECT photo_url FROM daily_photo_cache WHERE dog_id=? AND datum=?", - (dog_id, today_iso) - ).fetchone() - random_photo = None - if cached and cached["photo_url"]: - random_photo = { - "url": cached["photo_url"], - "preview_url": preview_url_from(cached["photo_url"]), - } - elif photos: + if photos: + import datetime as _dt2 tick = (_dt2.date.today() - _dt2.date(2024, 1, 1)).days chosen_url = photos[tick % len(photos)]["url"] random_photo = { "url": chosen_url, "preview_url": preview_url_from(chosen_url), } - conn.execute( - "INSERT OR IGNORE INTO daily_photo_cache (dog_id, datum, photo_url) VALUES (?, ?, ?)", - (dog_id, today_iso, chosen_url) - ) # Neuester Tagebucheintrag last_diary_row = conn.execute( diff --git a/backend/routes/expenses.py b/backend/routes/expenses.py index 9e32e43..9a34f27 100644 --- a/backend/routes/expenses.py +++ b/backend/routes/expenses.py @@ -12,15 +12,7 @@ from auth import get_current_user router = APIRouter() logger = logging.getLogger(__name__) -KATEGORIE_META = { - "futter": {"label": "Futter", "color": "#f59e0b"}, - "tierarzt": {"label": "Tierarzt", "color": "#ef4444"}, - "zubehoer": {"label": "Zubehör", "color": "#8b5cf6"}, - "versicherung": {"label": "Versicherung", "color": "#3b82f6"}, - "sitter": {"label": "Sitter", "color": "#10b981"}, - "sonstiges": {"label": "Sonstiges", "color": "#6b7280"}, -} -KATEGORIEN = set(KATEGORIE_META.keys()) +KATEGORIEN = {"tierarzt", "futter", "zubehoer", "versicherung", "sitter", "sonstiges"} # ------------------------------------------------------------------ @@ -83,18 +75,6 @@ def _serialize(row) -> dict: return dict(row) -# ------------------------------------------------------------------ -# GET /api/expenses/categories — gültige Kategorien (id + label + color) -# Single source of truth für PWA und mobile Clients. -# ------------------------------------------------------------------ -@router.get("/categories") -async def list_categories(): - return [ - {"id": key, **meta} - for key, meta in KATEGORIE_META.items() - ] - - # ------------------------------------------------------------------ # GET /api/expenses/summary — Monats- und Jahressummen # WICHTIG: Diese Route muss VOR /{id} stehen! diff --git a/backend/static/js/pages/onboarding.js b/backend/static/js/pages/onboarding.js index 5ba7638..c292f03 100644 --- a/backend/static/js/pages/onboarding.js +++ b/backend/static/js/pages/onboarding.js @@ -15,28 +15,6 @@ window.Page_onboarding = (() => { async function init(container, appState) { _container = container; _appState = appState; - - // Hunde frisch laden — der appState kann veraltet sein (z.B. nach - // Anlage in mobiler App). Wenn schon ein Hund da ist, Wizard - // komplett überspringen. - try { - const dogs = await API.dogs.list(); - _appState.dogs = dogs; - if (dogs.length > 0) { - _appState.activeDog = dogs[0]; - localStorage.setItem('by_active_dog', String(dogs[0].id)); - localStorage.setItem('by_onboarding_done', '1'); - App.renderDogSwitcher?.(); - if (window.Worlds) window.Worlds.init(_appState); - else App.navigate('diary'); - return; - } - } catch (e) { - // Lieber Wizard zeigen als komplett blockieren — wenn API down ist, - // landet der User halt im Standard-Flow. - console.warn('Onboarding: dog-list refresh failed', e); - } - _step = 1; _render(); } @@ -337,12 +315,10 @@ window.Page_onboarding = (() => { // EVENTS // ---------------------------------------------------------- function _bindEvents() { - // Weiter-Button (Schritt 1) — direkt ins richtige Hunde-Profil, - // statt eines doppelten Mini-Formulars im Wizard. Onboarding gilt - // damit als erledigt, sobald der User dort angekommen ist. + // Weiter-Button (Schritt 1) _container.querySelector('#ob-next-btn')?.addEventListener('click', () => { - localStorage.setItem('by_onboarding_done', '1'); - App.navigate('dog-profile'); + _step = 2; + _render(); }); // Zurück-Button (Schritt 2) @@ -446,24 +422,6 @@ window.Page_onboarding = (() => { _render(); } catch (err) { - // 403 „schon einen Hund" → kein Stuck-State, weiter zu Schritt 3 - const isAlreadyHas = err?.status === 403 - || /Pro-Feature|schon|already|maximal/i.test(err?.message || ''); - if (isAlreadyHas) { - try { - const dogs = await API.dogs.list(); - _appState.dogs = dogs; - if (dogs.length > 0) { - _appState.activeDog = dogs[0]; - localStorage.setItem('by_active_dog', String(dogs[0].id)); - App.renderDogSwitcher?.(); - } - } catch {} - UI.toast.info?.('Du hast bereits einen Hund — geht direkt weiter.'); - _step = 3; - _render(); - return; - } UI.toast.error(err.message || 'Hund konnte nicht angelegt werden.'); } finally { if (saveBtn) { diff --git a/backend/static/js/worlds.js b/backend/static/js/worlds.js index 52f3baa..c6e05eb 100644 --- a/backend/static/js/worlds.js +++ b/backend/static/js/worlds.js @@ -1425,7 +1425,7 @@ window.Worlds = (() => {
Lege ein Profil an und schalte alle Features frei
- @@ -1444,7 +1444,6 @@ window.Worlds = (() => { `; el.querySelectorAll('[data-wnav]').forEach(e => e.addEventListener('click', () => navigateTo(e.dataset.wnav))); - el.querySelector('#welcome-add-dog-btn')?.addEventListener('click', () => navigateTo('dog-profile')); return; } diff --git a/backend/static/manifest.json b/backend/static/manifest.json index 48386cb..05cf86f 100644 --- a/backend/static/manifest.json +++ b/backend/static/manifest.json @@ -1,6 +1,6 @@ { "id": "/", - "version": "1.6.0", + "version": "1.5.0", "name": "Ban Yaro — Die Hunde-Plattform", "short_name": "Ban Yaro", "description": "Alles rund um deinen Hund. Von Welpe bis Opa.",