diff --git a/backend/static/js/app.js b/backend/static/js/app.js index d7180a4..2f96495 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 = '422'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '423'; // ← 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 d857361..53f744a 100644 --- a/backend/static/js/pages/welcome.js +++ b/backend/static/js/pages/welcome.js @@ -53,34 +53,200 @@ window.Page_welcome = (() => { || window.navigator.standalone === true; const user = _appState?.user; + _injectStyles(); + + if (user) { + _renderLoggedIn(isInstalled); + } else { + _renderLanding(isInstalled); + } + + _bindEvents(); + _pulseMenuBtn(); + } + + // ---------------------------------------------------------- + // LANDING PAGE — nicht eingeloggte Besucher + // ---------------------------------------------------------- + function _renderLanding(isInstalled) { + const hasPrompt = !!App.getInstallPrompt(); + + _container.innerHTML = ` +
+ + +
+ Ban Yaro +

Alles für
deinen Hund.

+

+ Tagebuch, Gesundheit, Karte, Community —
+ auf einem Server in Deutschland. Kostenlos. +

+ +
+ ${hasPrompt ? ` + + ` : ` + + `} + +
+ +
+ + + Kostenlos + + + + Kein App Store + + + + Daten in Deutschland + +
+
+ + +
+
+ +
+
+

Tagebuch & Erinnerungen

+

Halte jeden gemeinsamen Moment fest — Fotos, Einträge, Stimmungen. Nur für dich, privat und sicher.

+
+
+ + +
+
+ +
+
+

Gesundheit im Blick

+

Impfungen, Gewicht, Tierarzttermine — alles an einem Ort. Du siehst immer, wann was ansteht.

+
+
+ + +
+
+ +
+
+

Community vor Ort

+

Giftköder-Warnungen, Gassi-Treffen, Events — was in deiner Gegend gerade passiert.

+
+
+ + +
+
+ +
+
+

Training & KI-Trainer

+

Über 100 Übungen mit Schritt-für-Schritt-Anleitungen. Mit KI-Unterstützung, die deinen Hund kennt.

+
+
+ + +
+
+ +
+

Deine Daten gehören dir.

+

+ Kein Facebook. Kein Google. Keine Werbung.
+ Ban Yaro läuft auf einem eigenen Server in Deutschland — + dein Tagebuch, deine Routen, deine Gesundheitsdaten + bleiben privat. +

+
+ + +
+

Und noch viel mehr

+
+ ${FEATURES.map(f => ` +
+
+ +
+ ${f.label} +
+ `).join('')} +
+
+ + +
+ ${hasPrompt ? ` + + ` : ` + + `} +

Kein App Store · Direkt auf den Home-Bildschirm

+ + ${!isInstalled ? ` + + ` : ''} +
+ + + ${_showInstall ? ` +
+
+
+ + App installieren +
+
${_installHTML()}
+
+
+ ` : ''} + + +
+ `; + } + + // ---------------------------------------------------------- + // EINGELOGGTE ANSICHT — kompakter Überblick + // ---------------------------------------------------------- + function _renderLoggedIn(isInstalled) { _container.innerHTML = `
-
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.'} + Schön, dass du wieder da bist${_appState?.user?.name ? ', ' + UI.escape(_appState.user.name) + '' : ''}!

- ${!user ? ` -
- - -
- ` : ''}
-
-

Was Ban Yaro kann

-
${FEATURES.map(f => `
- ${(!isInstalled || _showInstall) ? `
App installieren
-
- ${_installHTML()} -
+
${_installHTML()}
` : ''} - - - +
`; - - _injectStyles(); - _bindEvents(); - _pulseMenuBtn(); } // ---------------------------------------------------------- - // STYLES (einmalig injizieren) + // STYLES // ---------------------------------------------------------- function _injectStyles() { if (document.getElementById('wc-styles')) return; const s = document.createElement('style'); s.id = 'wc-styles'; s.textContent = ` + /* ── Landing Page ──────────────────────────────────────── */ + .wc-landing { display: flex; flex-direction: column; } + /* Hero */ + .wc-lhero { + background: linear-gradient(160deg, var(--c-primary) 0%, color-mix(in srgb, var(--c-primary) 70%, transparent) 60%, var(--c-bg) 100%); + text-align: center; + padding: var(--space-8) var(--space-5) var(--space-8); + position: relative; + overflow: hidden; + } + .wc-lhero::before { + content: ''; + position: absolute; inset: 0; + background: radial-gradient(ellipse at 50% 0%, rgba(255,255,255,0.18) 0%, transparent 65%); + pointer-events: none; + } + .wc-lhero-icon { + width: 80px; height: 80px; + border-radius: 20px; + box-shadow: 0 8px 32px rgba(0,0,0,0.25); + display: block; margin: 0 auto var(--space-5); + position: relative; + } + .wc-lhero-headline { + font-size: 2.6rem; font-weight: 800; line-height: 1.1; + color: #fff; + margin: 0 0 var(--space-4); + text-shadow: 0 2px 12px rgba(0,0,0,0.15); + letter-spacing: -0.02em; + position: relative; + } + .wc-lhero-sub { + font-size: var(--text-base); color: rgba(255,255,255,0.88); + line-height: 1.6; margin: 0 0 var(--space-6); + position: relative; + } + .wc-lhero-cta { + display: flex; flex-direction: column; + align-items: center; gap: var(--space-3); + margin-bottom: var(--space-6); + position: relative; + } + .wc-btn-hero { + background: #fff; color: var(--c-primary); + font-size: var(--text-base); font-weight: var(--weight-bold); + padding: 14px var(--space-6); border-radius: 100px; + border: none; width: 100%; max-width: 320px; + box-shadow: 0 4px 20px rgba(0,0,0,0.2); + display: flex; align-items: center; justify-content: center; gap: var(--space-2); + transition: transform 0.1s, box-shadow 0.1s; + } + .wc-btn-hero:active { transform: scale(0.97); box-shadow: 0 2px 10px rgba(0,0,0,0.15); } + .wc-btn-login { + color: rgba(255,255,255,0.9) !important; + font-size: var(--text-sm); + padding: var(--space-2) var(--space-4); + border-color: rgba(255,255,255,0.35) !important; + } + .wc-trust-strip { + display: flex; justify-content: center; + gap: var(--space-4); flex-wrap: wrap; + position: relative; + } + .wc-trust-strip span { + display: flex; align-items: center; gap: 5px; + font-size: var(--text-xs); color: rgba(255,255,255,0.8); + font-weight: var(--weight-semibold); + } + .wc-trust-strip .ph-icon { width: 13px; height: 13px; } + + /* Feature Cards */ + .wc-feature { + display: flex; align-items: flex-start; gap: var(--space-4); + padding: var(--space-6) var(--space-5); + border-bottom: 1px solid var(--c-border-light); + } + .wc-feature--a { background: var(--c-bg); } + .wc-feature--b { background: var(--c-surface); } + .wc-feature--c { background: var(--c-bg); } + .wc-feature--d { background: var(--c-surface); } + .wc-feature-icon { + width: 52px; height: 52px; border-radius: var(--radius-lg); flex-shrink: 0; + background: var(--c-primary-subtle); + display: flex; align-items: center; justify-content: center; + } + .wc-feature-icon .ph-icon { width: 26px; height: 26px; color: var(--c-primary); } + .wc-feature-text h2 { + font-size: var(--text-base); font-weight: var(--weight-bold); + color: var(--c-text); margin: 0 0 var(--space-1); + } + .wc-feature-text p { + font-size: var(--text-sm); color: var(--c-text-secondary); + line-height: 1.6; margin: 0; + } + + /* Privacy Block */ + .wc-privacy { + background: var(--c-primary); + padding: var(--space-8) var(--space-5); + text-align: center; + } + .wc-privacy-icon { + width: 56px; height: 56px; border-radius: 50%; + background: rgba(255,255,255,0.2); + display: flex; align-items: center; justify-content: center; + margin: 0 auto var(--space-4); + } + .wc-privacy-icon .ph-icon { width: 28px; height: 28px; color: #fff; } + .wc-privacy-title { + font-size: var(--text-xl); font-weight: var(--weight-bold); + color: #fff; margin: 0 0 var(--space-3); + } + .wc-privacy-sub { + font-size: var(--text-sm); color: rgba(255,255,255,0.85); + line-height: 1.7; margin: 0; max-width: 360px; margin: 0 auto; + } + + /* Und noch mehr */ + .wc-more { + padding: var(--space-6) var(--space-4); + background: var(--c-bg); + border-top: 1px solid var(--c-border-light); + } + .wc-more-label { + font-size: var(--text-xs); font-weight: var(--weight-semibold); + color: var(--c-text-secondary); text-transform: uppercase; + letter-spacing: 0.07em; margin: 0 0 var(--space-4); text-align: center; + } + + /* Bottom CTA */ + .wc-bottom-cta { + padding: var(--space-8) var(--space-5) var(--space-6); + display: flex; flex-direction: column; align-items: center; + gap: var(--space-3); background: var(--c-bg); + border-top: 1px solid var(--c-border-light); + } + .wc-bottom-hint { + font-size: var(--text-xs); color: var(--c-text-muted); margin: 0; + } + .wc-install-link { + background: none; border: none; cursor: pointer; + font-size: var(--text-xs); color: var(--c-text-secondary); + display: flex; align-items: center; gap: 4px; + padding: var(--space-2); margin-top: var(--space-1); + } + .wc-install-link .ph-icon { width: 12px; height: 12px; } + + /* ── Logged-in Hero (kompakt) ──────────────────────────── */ .wc-hero { background: linear-gradient(160deg, var(--c-primary-subtle) 0%, var(--c-bg) 70%); text-align: center; @@ -135,8 +438,7 @@ window.Page_welcome = (() => { border-bottom: 1px solid var(--c-border-light); } .wc-hero-icon { - width: 96px; height: 96px; - border-radius: 22px; + 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); } @@ -146,52 +448,43 @@ window.Page_welcome = (() => { } .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); + margin: 0 auto; line-height: 1.6; max-width: 420px; } - /* Section title */ + /* ── Shared ────────────────────────────────────────────── */ .wc-section-title { - font-size: var(--text-sm); font-weight: var(--weight-semibold); + font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--c-text-secondary); text-transform: uppercase; - letter-spacing: 0.06em; margin: 0 0 var(--space-4); + letter-spacing: 0.07em; margin: 0 0 var(--space-4); text-align: center; } - - /* Feature Grid */ .wc-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); - margin-bottom: var(--space-6); + margin-bottom: var(--space-4); } .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; + 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--static { cursor: default; } + .wc-tile--static:hover { background: var(--c-surface); } + .wc-tile--static:active { transform: none; } .wc-tile-icon { - width: 44px; height: 44px; border-radius: var(--radius-md); + width: 40px; height: 40px; 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-icon .ph-icon { width: 20px; height: 20px; 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); @@ -201,19 +494,23 @@ window.Page_welcome = (() => { 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; + color: var(--c-text-muted); padding: var(--space-4); } - /* Desktop: 8-spaltig */ + @media (min-width: 640px) { + .wc-lhero-headline { font-size: 3.2rem; } + .wc-lhero-cta { flex-direction: row; justify-content: center; } + .wc-btn-hero { width: auto; } + .wc-grid { grid-template-columns: repeat(4, 1fr); } + } @media (min-width: 1024px) { + .wc-lhero { padding: var(--space-8) var(--space-4) var(--space-10); } + .wc-feature { max-width: 680px; margin: 0 auto; } .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); } @@ -231,10 +528,8 @@ window.Page_welcome = (() => { const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; const isSafari = /^((?!chrome|android).)*safari/i.test(ua); const isAndroid = /android/i.test(ua); - const isMobile = isIOS || isAndroid; const hasPrompt = !!App.getInstallPrompt(); - // Android: Browser hat Install-Prompt bereit (Chrome, Edge, Samsung Internet neu) if (hasPrompt) { return `

@@ -246,7 +541,6 @@ window.Page_welcome = (() => { `; } - // iOS Safari: Teilen-Menü if (isIOS && isSafari) { return `

@@ -262,7 +556,6 @@ window.Page_welcome = (() => {

`; } - // iOS, aber nicht Safari (Chrome, Firefox, etc.) if (isIOS && !isSafari) { return `

@@ -280,7 +573,6 @@ window.Page_welcome = (() => { `; } - // Android ohne Prompt (Firefox, älterer Samsung Browser, etc.) if (isAndroid) { return `

@@ -298,7 +590,6 @@ window.Page_welcome = (() => { `; } - // Desktop — beide Plattformen zeigen return `

${_steps([ - ['arrow-square-in', 'Öffne banyaro.app in Chrome oder Edge'], - ['monitor', 'Klicke auf das Installations-Symbol in der Adressleiste'], - ['check', 'Bestätigen — fertig!'], + ['arrow-square-in', 'Öffne banyaro.app in Chrome oder Edge'], + ['monitor', 'Klicke auf das Installations-Symbol in der Adressleiste'], + ['check', 'Bestätigen — fertig!'], ])}