diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 482c19c..f74e65e 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 = '390'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '391'; // ← 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 388172c..040d21c 100644 --- a/backend/static/js/pages/welcome.js +++ b/backend/static/js/pages/welcome.js @@ -1,6 +1,5 @@ /* ============================================================ BAN YARO — Willkommensseite - Über die App, Features, Installations-Anleitung. ============================================================ */ window.Page_welcome = (() => { @@ -8,9 +7,6 @@ window.Page_welcome = (() => { let _container = null; let _appState = null; - // ---------------------------------------------------------- - // INIT - // ---------------------------------------------------------- async function init(container, appState) { _container = container; _appState = appState; @@ -20,144 +16,208 @@ window.Page_welcome = (() => { function refresh() { _render(); } function onDogChange() {} + // ---------------------------------------------------------- + // FEATURES — Icon, Titel, Beschreibung, Zielseite + // ---------------------------------------------------------- + const FEATURES = [ + { icon: 'book-open', label: 'Tagebuch', page: 'diary' }, + { icon: 'first-aid', label: 'Gesundheit', page: 'health' }, + { icon: 'map-trifold', label: 'Karte', page: 'map' }, + { icon: 'path', label: 'Routen', page: 'routes' }, + { icon: 'target', label: 'Training', page: 'uebungen' }, + { icon: 'warning-octagon', label: 'Giftköder', page: 'poison' }, + { icon: 'users', label: 'Freunde', page: 'friends' }, + { icon: 'chat-circle-dots', label: 'Nachrichten', page: 'chat' }, + { icon: 'paw-print', label: 'Gassi-Treffen', page: 'walks' }, + { icon: 'house-line', label: 'Sitting', page: 'sitting' }, + { icon: 'push-pin', label: 'Forum', page: 'forum' }, + { icon: 'books', label: 'Rassen-Wiki', page: 'wiki' }, + { icon: 'calendar-dots', label: 'Events', page: 'events' }, + { icon: 'bell', label: 'Neuigkeiten', page: 'notifications' }, + { icon: 'handshake', label: 'Knigge', page: 'knigge' }, + { icon: 'magnifying-glass', label: 'Vermisste', page: 'lost' }, + ]; + // ---------------------------------------------------------- // RENDER // ---------------------------------------------------------- function _render() { const isInstalled = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; + const user = _appState?.user; _container.innerHTML = ` -
+
- -
- Ban Yaro -

Ban Yaro

-

- Die Plattform für Hundebesitzer —
Tagebuch, Gesundheit, Community und mehr. + +

+ Ban Yaro +

Ban Yaro

+

+ ${user + ? `Schön, dass du wieder da bist${user.name ? ', ' + UI.escape(user.name) + '' : ''}! 🐾` + : 'Die Community für Hundebesitzer — Tagebuch, Gesundheit, Karte und mehr.'}

-
- - - +
-
- Tippe auf das ☰-Symbol für Karte, Routen, Giftköder-Alarm, Forum und vieles mehr. + ` : ''} +
+ + +
+ +

Was Ban Yaro kann

+ +
+ ${FEATURES.map(f => ` + + `).join('')} +
+ + + ${!isInstalled ? ` +
+
+ + App installieren +
+
+ ${_installHTML()} +
-
- + ` : ''} - -
- - ${_featureCard('Mein Hund', [ - ['book-open', 'Tagebuch', 'Momente, Fotos und Meilensteine festhalten', 'diary'], - ['first-aid', 'Gesundheit', 'Impfungen, Tierarztbesuche & Medikamente', 'health'], - ['target', 'Übungen', 'Trainingsübungen mit KI-Unterstützung', 'uebungen'], - ['clipboard-text', 'Trainingspläne', 'Strukturierte Pläne für jedes Lernziel', 'trainingsplaene'], - ])} - - ${_featureCard('Entdecken', [ - ['map-trifold', 'Karte', 'Orte, Routen und Meldungen in der Nähe', 'map'], - ['path', 'Routen', 'GPS-Routen aufzeichnen und bewerten', 'routes'], - ['calendar-dots', 'Events', 'Turniere und Veranstaltungen', 'events'], - ])} - - ${_featureCard('Soziales', [ - ['users', 'Freunde', 'Verbinde dich mit anderen Hundebesitzern', 'friends'], - ['chat-circle-dots', 'Nachrichten', 'Private Chats mit deinen Freunden', 'chat'], - ['bell', 'Aktuelles', 'Benachrichtigungen und Neuigkeiten', 'notifications'], - ])} - - ${_featureCard('Community', [ - ['warning-octagon', 'Giftköder-Alarm', 'Warnungen sofort melden und empfangen', 'poison'], - ['paw-print', 'Gassi-Treffen', 'Hunde-Dates mit anderen Besitzern', 'walks'], - ['house-line', 'Sitting', 'Sitter finden oder selbst anbieten', 'sitting'], - ['push-pin', 'Forum', 'Diskussionen, Tipps und Austausch', 'forum'], - ['magnifying-glass', 'Verlorene Hunde', 'Hilf vermisste Hunde zu finden', 'lost'], - ])} - - ${_featureCard('Wissen', [ - ['books', 'Wiki', 'Rassendatenbank, Gesundheits-Wiki, Quiz', 'wiki'], - ['handshake', 'Knigge', 'Regeln, Begegnungen, Leinenpflicht', 'knigge'], - ['film-slate', 'Filme', 'Stirbt der Hund? Die wichtigste Frage', 'movies'], - ['first-aid', 'Erste Hilfe','Notfallratgeber für häufige Situationen', 'erste-hilfe'], - ])} + +
- - -
-
- App installieren -
-
- ${isInstalled - ? `
- - - Ban Yaro ist bereits installiert. - -
` - : _installHTML() - } -
-
- - - ${!_appState.user ? ` -
- - -
- ` : ''} - - -

- Ban Yaro · Deine Daten auf eigenem Server in Deutschland. -

-
`; + _injectStyles(); _bindEvents(); + _pulseMenuBtn(); } // ---------------------------------------------------------- - // INSTALLATIONS-ANLEITUNG (plattformabhängig) + // STYLES (einmalig injizieren) + // ---------------------------------------------------------- + function _injectStyles() { + if (document.getElementById('wc-styles')) return; + const s = document.createElement('style'); + s.id = 'wc-styles'; + s.textContent = ` + /* Hero */ + .wc-hero { + background: linear-gradient(160deg, var(--c-primary-subtle) 0%, var(--c-bg) 70%); + text-align: center; + padding: var(--space-8) var(--space-4) var(--space-6); + border-bottom: 1px solid var(--c-border-light); + } + .wc-hero-icon { + width: 96px; height: 96px; + border-radius: 22px; + box-shadow: 0 8px 28px rgba(0,0,0,0.15); + display: block; margin: 0 auto var(--space-4); + } + .wc-hero-title { + font-size: var(--text-2xl); font-weight: var(--weight-bold); + color: var(--c-text); margin: 0 0 var(--space-2); + } + .wc-hero-sub { + font-size: var(--text-base); color: var(--c-text-secondary); + margin: 0; line-height: 1.6; max-width: 420px; margin: 0 auto; + } + .wc-hero-cta { + display: flex; gap: var(--space-3); justify-content: center; + flex-wrap: wrap; margin-top: var(--space-5); + } + + /* Section title */ + .wc-section-title { + font-size: var(--text-sm); font-weight: var(--weight-semibold); + color: var(--c-text-secondary); text-transform: uppercase; + letter-spacing: 0.06em; margin: 0 0 var(--space-4); + } + + /* Feature Grid */ + .wc-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-3); + margin-bottom: var(--space-6); + } + .wc-tile { + display: flex; flex-direction: column; + align-items: center; gap: var(--space-2); + padding: var(--space-4) var(--space-2); + background: var(--c-surface); + border: 1px solid var(--c-border-light); + border-radius: var(--radius-lg); + cursor: pointer; transition: background var(--transition-fast), transform 0.1s; + } + .wc-tile:hover { background: var(--c-surface-2); } + .wc-tile:active { transform: scale(0.96); } + .wc-tile-icon { + width: 44px; height: 44px; border-radius: var(--radius-md); + background: var(--c-primary-subtle); + display: flex; align-items: center; justify-content: center; + } + .wc-tile-icon .ph-icon { + width: 22px; height: 22px; color: var(--c-primary); + } + .wc-tile-label { + font-size: var(--text-xs); font-weight: var(--weight-semibold); + color: var(--c-text); text-align: center; line-height: 1.3; + } + + /* Install card */ + .wc-install-card { margin-bottom: var(--space-5); } + .wc-install-header { + display: flex; align-items: center; gap: var(--space-2); + padding: var(--space-3) var(--space-4); + font-size: var(--text-xs); font-weight: 600; + color: var(--c-text-secondary); text-transform: uppercase; + letter-spacing: 0.05em; border-bottom: 1px solid var(--c-border); + } + .wc-install-header .ph-icon { width: 14px; height: 14px; } + + /* Footer */ + .wc-footer { + text-align: center; font-size: var(--text-xs); + color: var(--c-text-muted); margin: 0; + } + + /* Desktop: 8-spaltig */ + @media (min-width: 1024px) { + .wc-grid { grid-template-columns: repeat(8, 1fr); } + } + + /* Pulse animation */ + @keyframes wc-pulse { + 0%,100% { transform: scale(1); box-shadow: none; } + 50% { transform: scale(1.25); box-shadow: 0 0 0 6px var(--c-primary-subtle); } + } + .wc-pulsing { animation: wc-pulse 0.6s ease-in-out 3; border-radius: var(--radius-md); } + `; + document.head.appendChild(s); + } + + // ---------------------------------------------------------- + // INSTALLATIONS-ANLEITUNG // ---------------------------------------------------------- function _installHTML() { const ua = navigator.userAgent; @@ -166,117 +226,63 @@ window.Page_welcome = (() => { const isAndroid = /android/i.test(ua); const hasPrompt = !!App.getInstallPrompt(); - // Android/Chrome mit nativem Prompt if ((isAndroid || hasPrompt) && hasPrompt) { return ` -

- Installiere Ban Yaro direkt auf deinem Gerät — kein App Store nötig. - Die App verhält sich wie eine native App und funktioniert auch offline. +

+ Kein App Store nötig — direkt installieren.

- `; + `; } - // iOS Safari if (isIOS && isSafari) { return ` -

- Installiere Ban Yaro auf deinem iPhone oder iPad: +

+ Auf iPhone/iPad installieren:

${_steps([ - ['share', 'Tippe auf das Teilen-Symbol in Safari (Rechteck mit Pfeil nach oben)'], - ['plus', 'Scrolle nach unten und tippe auf „Zum Home-Bildschirm"'], - ['check', 'Tippe rechts oben auf „Hinzufügen" — fertig!'], + ['1', 'Teilen-Symbol in Safari tippen'], + ['2', '„Zum Home-Bildschirm" wählen'], + ['3', 'Rechts oben „Hinzufügen" tippen'], ])}

- Funktioniert nur in Safari, nicht in anderen Browsern auf iOS. -

- `; + Nur in Safari verfügbar, nicht in anderen Browsern. +

`; } - // Desktop oder andere Browser return ` -

- Ban Yaro lässt sich in Chrome, Edge und anderen modernen Browsern installieren: +

+ In Chrome oder Edge installieren:

${_steps([ - ['globe', 'Öffne Ban Yaro in Chrome oder Edge'], - ['download-simple','Klicke in der Adressleiste auf das Installieren-Symbol (↓ mit Kreis)'], - ['check', 'Bestätige die Installation — Ban Yaro öffnet sich dann wie eine Desktop-App'], - ])} -

- Auf Android: Menü (⋮) → „App installieren" oder - „Zum Startbildschirm hinzufügen". -

- `; - } - - function _featureCard(heading, items) { - return ` -
-
- ${heading} -
-
- ${items.map(([icon, title, desc, page], i) => ` - - `).join('')} -
-
`; + ['1', 'Seite in Chrome oder Edge öffnen'], + ['2', 'Installations-Symbol in der Adressleiste klicken'], + ['3', 'Bestätigen — fertig!'], + ])}`; } function _steps(list) { return `
    - ${list.map(([icon, text], i) => ` + ${list.map(([num, text]) => `
  1. -
    - ${i + 1} +
    + ${num}
    - ${text} + ${text}
  2. `).join('')} -
- `; + `; } // ---------------------------------------------------------- // EVENTS // ---------------------------------------------------------- function _bindEvents() { - // Android-Install-Button _container.querySelector('#install-android-btn')?.addEventListener('click', async () => { const prompt = App.getInstallPrompt(); if (!prompt) return; @@ -284,58 +290,27 @@ window.Page_welcome = (() => { const { outcome } = await prompt.userChoice; if (outcome === 'accepted') { UI.toast.success('Ban Yaro wird installiert!'); - _render(); // zeigt "bereits installiert" + _render(); } }); - // CTAs für nicht-eingeloggte User - _container.querySelector('#welcome-register-btn')?.addEventListener('click', () => { - App.navigate('settings'); - }); - _container.querySelector('#welcome-login-btn')?.addEventListener('click', () => { - App.navigate('settings'); - }); + _container.querySelector('#welcome-register-btn')?.addEventListener('click', () => App.navigate('settings')); + _container.querySelector('#welcome-login-btn')?.addEventListener('click', () => App.navigate('settings')); - // Feature-Kacheln → navigieren _container.querySelectorAll('[data-nav]').forEach(btn => { btn.addEventListener('click', () => App.navigate(btn.dataset.nav)); - btn.addEventListener('mouseenter', () => btn.style.background = 'var(--c-surface-2)'); - btn.addEventListener('mouseleave', () => btn.style.background = ''); }); - - // Burger-Menü-Hinweis öffnet die Sidebar - _container.querySelector('#welcome-menu-hint')?.addEventListener('click', () => { - document.getElementById('header-menu-btn')?.click(); - }); - - // Hamburger-Button 3× kurz pulsieren lassen - _pulseMenuBtn(); } function _pulseMenuBtn() { const btn = document.getElementById('header-menu-btn'); if (!btn) return; - if (!document.getElementById('welcome-pulse-style')) { - const s = document.createElement('style'); - s.id = 'welcome-pulse-style'; - s.textContent = ` - @keyframes wc-pulse { - 0%,100% { transform: scale(1); box-shadow: none; } - 50% { transform: scale(1.25); box-shadow: 0 0 0 6px var(--c-primary-subtle); } - } - .wc-pulsing { animation: wc-pulse 0.6s ease-in-out 3; border-radius: var(--radius-md); } - `; - document.head.appendChild(s); - } setTimeout(() => { btn.classList.add('wc-pulsing'); btn.addEventListener('animationend', () => btn.classList.remove('wc-pulsing'), { once: true }); }, 800); } - // ---------------------------------------------------------- - // PUBLIC - // ---------------------------------------------------------- return { init, refresh, onDogChange }; })(); diff --git a/backend/static/sw.js b/backend/static/sw.js index 318b535..0ea787f 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-v410'; +const CACHE_VERSION = 'by-v411'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten