diff --git a/backend/static/css/design-system.css b/backend/static/css/design-system.css index dc1a0b2..15f8df2 100644 --- a/backend/static/css/design-system.css +++ b/backend/static/css/design-system.css @@ -115,70 +115,21 @@ --safe-right: env(safe-area-inset-right, 0px); } -/* Dark Mode — System-Präferenz (nur wenn kein manuelles Theme gesetzt) */ +/* Dark Mode — vorbereitet, nicht aktiv */ @media (prefers-color-scheme: dark) { - :root:not([data-theme="light"]):not([data-theme="dark"]) { - --c-bg: #1A1410; - --c-surface: #241C14; - --c-surface-2: #2E2418; - --c-surface-3: #3A2E20; - --c-border: #4A3C2C; - --c-border-light: #3A2E20; - - --c-primary-subtle: #2A1C0A; - --c-primary-soft: #2E1E08; - - --c-nature-subtle: #1A2214; - --c-sky-subtle: #141C22; - --c-danger-subtle: #2A100A; - --c-success-subtle: #122010; - --c-warning-subtle: #261A08; - --c-info-subtle: #10182A; - - --c-text: #F0EAE0; + :root { + --c-bg: #1A1410; + --c-surface: #241C14; + --c-surface-2: #2E2418; + --c-surface-3: #3A2E20; + --c-border: #4A3C2C; + --c-border-light: #3A2E20; + --c-text: #F0EAE0; --c-text-secondary: #C0B0A0; - --c-text-muted: #806A58; - --c-text-inverse: #2A1F14; - - --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); - --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25); - --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.40), 0 2px 4px rgba(0, 0, 0, 0.25); - --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.30); - --shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.50), 0 8px 16px rgba(0, 0, 0, 0.35); + --c-text-muted: #806A58; } } -/* Manuelles Dark-Theme via data-theme="dark" (überschreibt auch prefers-color-scheme: light) */ -:root[data-theme="dark"] { - --c-bg: #1A1410; - --c-surface: #241C14; - --c-surface-2: #2E2418; - --c-surface-3: #3A2E20; - --c-border: #4A3C2C; - --c-border-light: #3A2E20; - - --c-primary-subtle: #2A1C0A; - --c-primary-soft: #2E1E08; - - --c-nature-subtle: #1A2214; - --c-sky-subtle: #141C22; - --c-danger-subtle: #2A100A; - --c-success-subtle: #122010; - --c-warning-subtle: #261A08; - --c-info-subtle: #10182A; - - --c-text: #F0EAE0; - --c-text-secondary: #C0B0A0; - --c-text-muted: #806A58; - --c-text-inverse: #2A1F14; - - --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); - --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25); - --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.40), 0 2px 4px rgba(0, 0, 0, 0.25); - --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.30); - --shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.50), 0 8px 16px rgba(0, 0, 0, 0.35); -} - /* ------------------------------------------------------------ 2. RESET & BASE ------------------------------------------------------------ */ diff --git a/backend/static/index.html b/backend/static/index.html index a02751d..f46531d 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -170,10 +170,6 @@
-
-
-
-
diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 8ec5eb4..e36649b 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 = '179'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '175'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const App = (() => { @@ -33,7 +33,6 @@ const App = (() => { // ---------------------------------------------------------- const pages = { welcome: { title: 'Willkommen', module: null }, - onboarding: { title: 'Einrichtung', module: null, requiresAuth: true }, diary: { title: 'Tagebuch', module: null, requiresAuth: true }, health: { title: 'Gesundheit', module: null, requiresAuth: true }, 'dog-profile': { title: 'Mein Hund', module: null, requiresAuth: true }, @@ -414,9 +413,9 @@ const App = (() => { } await _loadDogs(); - // Eingeloggter User ohne Hund → Onboarding-Wizard (einmalig) - if (state.dogs.length === 0 && !localStorage.getItem('by_onboarding_done')) { - navigate('onboarding'); + // Eingeloggter User ohne Hund (z.B. nach Reload) → direkt zur Hund-Anlage + if (state.dogs.length === 0) { + navigate('dog-profile'); } _updateNotifBadge(); diff --git a/backend/static/js/pages/onboarding.js b/backend/static/js/pages/onboarding.js deleted file mode 100644 index 6cfda8b..0000000 --- a/backend/static/js/pages/onboarding.js +++ /dev/null @@ -1,461 +0,0 @@ -/* ============================================================ - BAN YARO — Onboarding-Wizard - 3-Schritt-Wizard für neue User ohne Hund. - ============================================================ */ - -window.Page_onboarding = (() => { - - let _container = null; - let _appState = null; - let _step = 1; // 1 = Willkommen, 2 = Hund anlegen, 3 = Fertig - - // ---------------------------------------------------------- - // INIT - // ---------------------------------------------------------- - async function init(container, appState) { - _container = container; - _appState = appState; - _step = 1; - _render(); - } - - function refresh() { - // Wenn User nach Abschluss zurücknavigiert und schon fertig ist → Tagebuch - if (localStorage.getItem('by_onboarding_done')) { - App.navigate('diary'); - return; - } - _render(); - } - - function onDogChange() {} - - // ---------------------------------------------------------- - // RENDER - // ---------------------------------------------------------- - function _render() { - _container.innerHTML = ` -
- - -
- ${[1, 2, 3].map(n => ` -
-
- ${n < _step - ? `` - : n} -
- ${n < 3 ? `
` : ''} -
- `).join('')} -
- - -
- ${_stepContent()} -
- -
- `; - - _bindEvents(); - } - - function _stepContent() { - if (_step === 1) return _step1(); - if (_step === 2) return _step2(); - if (_step === 3) return _step3(); - return ''; - } - - // ---------------------------------------------------------- - // SCHRITT 1 — Willkommen - // ---------------------------------------------------------- - function _step1() { - return ` -
- - -
- Ban Yaro -
- - -

- Willkommen bei Ban Yaro! -

- - -

- Ban Yaro ist dein digitaler Begleiter für alles rund um deinen Hund — - Tagebuch, Gesundheit, Karte und Community in einer App. -

-

- In nur zwei Schritten richtest du dein Profil ein und bist sofort startklar. -

- - -
- ${[ - ['book-open', 'Tagebuch', 'Momente & Fotos'], - ['syringe', 'Gesundheit', 'Impfungen & Arzt'], - ['map-trifold', 'Karte', 'Orte & Routen'], - ['users', 'Community', 'Freunde & Treffen'], - ].map(([icon, title, desc]) => ` -
-
- -
-
-
${title}
-
${desc}
-
-
- `).join('')} -
- - -
- - -
- -
- `; - } - - // ---------------------------------------------------------- - // SCHRITT 2 — Hund anlegen - // ---------------------------------------------------------- - function _step2() { - const today = new Date().toISOString().slice(0, 10); - return ` -
- - -
-
- -
-

- Dein erster Hund -

-

- Nur der Name ist Pflicht — alles andere kannst du später ergänzen. -

-
- - -
- -
- - -
- -
- - -
- -
- - -
- - -
- - - -
- -
- - -
- - -
-
- -
- -
- `; - } - - // ---------------------------------------------------------- - // SCHRITT 3 — Fertig - // ---------------------------------------------------------- - function _step3() { - const dogName = _appState.activeDog?.name; - return ` -
- - -
-
- -
-
- - -

- Dein Profil ist bereit! -

- ${dogName ? ` -

- ${_esc(dogName)} ist jetzt in Ban Yaro. - Du kannst jetzt Einträge im Tagebuch anlegen, die Gesundheit pflegen - und viele weitere Funktionen nutzen. -

- ` : ` -

- Ban Yaro ist bereit. Du kannst jetzt die Karte, das Wiki und viele - weitere Funktionen erkunden. -

- `} -

- Du kannst dein Hundeprofil jederzeit unter - Mein Hund bearbeiten und ergänzen. -

- - -
- - ${dogName ? ` - - ` : ''} -
- -
- `; - } - - // ---------------------------------------------------------- - // EVENTS - // ---------------------------------------------------------- - function _bindEvents() { - // Weiter-Button (Schritt 1) - _container.querySelector('#ob-next-btn')?.addEventListener('click', () => { - _step = 2; - _render(); - }); - - // Zurück-Button (Schritt 2) - _container.querySelector('#ob-back-btn')?.addEventListener('click', () => { - _step = 1; - _render(); - }); - - // Überspringen - _container.querySelector('#ob-skip-btn')?.addEventListener('click', () => { - _finish(); - }); - - // Foto-Vorschau - _container.querySelector('#ob-photo-input')?.addEventListener('change', e => { - const file = e.target.files?.[0]; - if (!file) return; - const url = URL.createObjectURL(file); - const preview = _container.querySelector('#ob-photo-preview'); - const img = _container.querySelector('#ob-photo-img'); - const label = _container.querySelector('#ob-photo-label'); - if (preview) preview.style.display = ''; - if (img) img.src = url; - if (label) label.textContent = file.name.length > 20 - ? file.name.slice(0, 17) + '...' - : file.name; - }); - - // Formular abschicken (Schritt 2) - _container.querySelector('#ob-dog-form')?.addEventListener('submit', async e => { - e.preventDefault(); - await _saveDog(e.target); - }); - - // Zu Tagebuch (Schritt 3) - _container.querySelector('#ob-diary-btn')?.addEventListener('click', () => { - App.navigate('diary'); - }); - - // Zu Hund-Profil (Schritt 3) - _container.querySelector('#ob-profile-btn')?.addEventListener('click', () => { - App.navigate('dog-profile'); - }); - } - - // ---------------------------------------------------------- - // HUND SPEICHERN - // ---------------------------------------------------------- - async function _saveDog(form) { - const saveBtn = _container.querySelector('#ob-save-btn'); - if (saveBtn) { - saveBtn.disabled = true; - saveBtn.innerHTML = ` - - Wird angelegt… - `; - } - - try { - const data = new FormData(form); - const payload = { - name: data.get('name')?.trim(), - rasse: data.get('rasse')?.trim() || null, - geburtstag: data.get('geburtstag') || null, - }; - - if (!payload.name) { - UI.toast.error('Bitte gib einen Namen ein.'); - return; - } - - // Hund anlegen - const dog = await API.dogs.create(payload); - - // Foto hochladen (falls vorhanden) - const fotoFile = data.get('foto'); - if (fotoFile && fotoFile.size > 0) { - try { - const fd = new FormData(); - fd.append('file', fotoFile); - await API.dogs.uploadPhoto(dog.id, fd); - } catch { - // Foto-Upload-Fehler ist nicht kritisch - UI.toast.warning('Hund angelegt, Foto konnte nicht hochgeladen werden.'); - } - } - - // State aktualisieren - const dogs = await API.dogs.list(); - _appState.dogs = dogs; - const newDog = dogs.find(d => d.id === dog.id) || dogs[0]; - _appState.activeDog = newDog; - if (newDog) { - localStorage.setItem('by_active_dog', String(newDog.id)); - } - App.renderDogSwitcher(); - - UI.toast.success(`${_esc(dog.name)} wurde angelegt!`); - - _step = 3; - _render(); - - } catch (err) { - UI.toast.error(err.message || 'Hund konnte nicht angelegt werden.'); - } finally { - if (saveBtn) { - saveBtn.disabled = false; - saveBtn.innerHTML = ` - - Hund anlegen - `; - } - } - } - - // ---------------------------------------------------------- - // ABSCHLUSS - // ---------------------------------------------------------- - function _finish() { - localStorage.setItem('by_onboarding_done', '1'); - if (_appState.dogs.length > 0) { - App.navigate('diary'); - } else { - App.navigate('map'); - } - } - - // ---------------------------------------------------------- - // HELPER - // ---------------------------------------------------------- - function _esc(s) { - return UI.escape(s || ''); - } - - // ---------------------------------------------------------- - // PUBLIC - // ---------------------------------------------------------- - return { init, refresh, onDogChange }; - -})(); diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js index 6aeb9d9..8478bca 100644 --- a/backend/static/js/pages/settings.js +++ b/backend/static/js/pages/settings.js @@ -182,32 +182,6 @@ window.Page_settings = (() => { App-Einstellungen
- - -
- -
-
Dark Mode
-
- Erscheinungsbild der App -
-
- -
-
@@ -446,24 +420,6 @@ window.Page_settings = (() => { } }); - document.getElementById('select-theme')?.addEventListener('change', e => { - const val = e.target.value; - localStorage.setItem('by_theme', val); - const html = document.documentElement; - if (val === 'dark') { - html.setAttribute('data-theme', 'dark'); - } else if (val === 'light') { - html.setAttribute('data-theme', 'light'); - } else { - html.removeAttribute('data-theme'); - } - UI.toast.info( - val === 'dark' ? 'Dark Mode aktiviert.' : - val === 'light' ? 'Hell-Modus aktiviert.' : - 'Theme folgt der Systemeinstellung.' - ); - }); - document.getElementById('toggle-pocket-mode')?.addEventListener('change', e => { localStorage.setItem('by_pocket_mode', String(e.target.checked)); UI.toast.info(e.target.checked