/* ============================================================ BAN YARO — Willkommensseite ============================================================ */ window.Page_welcome = (() => { let _container = null; let _appState = null; let _showInstall = false; let _heroInterval = null; // ---------------------------------------------------------- // HERO-SLIDES — rotieren alle 4 Sekunden // ---------------------------------------------------------- const HERO_SLIDES = [ { headline: 'Jeder Moment zählt.', sub: 'Fotos, Notizen, Stimmungen — das Tagebuch deines Hundes.' }, { headline: 'Deine Gegend. Sein Revier.', sub: 'Hundeparks, Gassi-Spots und mehr — alles auf der Karte.' }, { headline: 'Kein Termin verpasst.', sub: 'Impfungen, Gewicht, Tierarzt — mit KI, individuell auf deinen Hund angepasst.' }, { headline: 'Wir achten auf deinen Hund.', sub: 'Gefahren in deiner Nähe — damit ihr gezielt aus dem Weg gehen könnt.' }, { headline: 'Wie eine App. Nur ohne App Store.', sub: 'Einmal auf „Zum Homescreen" — fertig. Kein Store, keine Updates, kein Stress.' }, { headline: 'Lieblingsrouten für immer.', sub: 'Speichere eure besten Strecken — und entdecke neue in der Nähe.' }, { headline: 'Gassi ist kein Solosport.', sub: 'Triff andere Hundebesitzer — spontan, in deiner Umgebung.' }, { headline: 'Dein virtueller Trainer.', sub: '100+ Übungen, Schritt für Schritt — individuell auf deinen Hund abgestimmt.' }, { headline: 'Frag nach. Du bist nicht allein.', sub: 'Erfahrungen, Tipps, Hilfe — von Hundebesitzern für Hundebesitzer.' }, ]; async function init(container, appState, params = {}) { _container = container; _appState = appState; _showInstall = !!params.install; _render(); if (_showInstall) { setTimeout(() => { _container.querySelector('.wc-install-card')?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 100); } } 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() { if (_heroInterval) { clearInterval(_heroInterval); _heroInterval = null; } const isInstalled = window.matchMedia('(display-mode: standalone)').matches || 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

${HERO_SLIDES[0].headline}

${HERO_SLIDES[0].sub}

${HERO_SLIDES.map((_, i) => ``).join('')}
${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.

${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

Schön, dass du wieder da bist${_appState?.user?.name ? ', ' + UI.escape(_appState.user.name) + '' : ''}!

Was Ban Yaro kann

${FEATURES.map(f => ` `).join('')}
${(!isInstalled || _showInstall) ? `
App installieren
${_installHTML()}
` : ''}
`; } // ---------------------------------------------------------- // 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; transition: opacity 0.4s ease; } .wc-lhero-sub { font-size: var(--text-base); color: rgba(255,255,255,0.88); line-height: 1.6; margin: 0 0 var(--space-3); position: relative; transition: opacity 0.4s ease; } .wc-hero-dots { display: flex; justify-content: center; gap: 6px; margin-bottom: var(--space-6); position: relative; } .wc-hero-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,0.35); transition: background 0.3s, transform 0.3s; } .wc-hero-dot--active { background: rgba(255,255,255,0.9); transform: scale(1.3); } .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-4) var(--space-4); background: var(--c-bg); border-top: 1px solid var(--c-border-light); } .wc-more-toggle { display: flex; align-items: center; justify-content: center; gap: var(--space-2); width: 100%; background: none; border: none; cursor: pointer; font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--c-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; padding: var(--space-2) 0; margin-bottom: var(--space-3); } .wc-more-chevron { width: 14px; height: 14px; transition: transform 0.25s ease; } .wc-grid.wc-grid--collapsed { display: none; } /* 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; 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 auto; line-height: 1.6; max-width: 420px; } /* ── Shared ────────────────────────────────────────────── */ .wc-section-title { 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; } .wc-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); 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; } .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: 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: 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; } .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; } .wc-footer { text-align: center; font-size: var(--text-xs); color: var(--c-text-muted); padding: var(--space-4); } @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); } } @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); } // ---------------------------------------------------------- // HERO-ROTATION // ---------------------------------------------------------- function _startHeroRotation() { let idx = 0; const headline = _container.querySelector('#wc-hero-headline'); const sub = _container.querySelector('#wc-hero-sub'); const dots = _container.querySelectorAll('.wc-hero-dot'); if (!headline || !sub) return; _heroInterval = setInterval(() => { headline.style.opacity = '0'; sub.style.opacity = '0'; setTimeout(() => { idx = (idx + 1) % HERO_SLIDES.length; headline.textContent = HERO_SLIDES[idx].headline; sub.textContent = HERO_SLIDES[idx].sub; headline.style.opacity = '1'; sub.style.opacity = '1'; dots.forEach((d, i) => d.classList.toggle('wc-hero-dot--active', i === idx)); }, 400); }, 6000); } // ---------------------------------------------------------- // INSTALLATIONS-ANLEITUNG // ---------------------------------------------------------- function _installHTML() { const ua = navigator.userAgent; const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; const isSafari = /^((?!chrome|android).)*safari/i.test(ua); const isAndroid = /android/i.test(ua); const hasPrompt = !!App.getInstallPrompt(); if (hasPrompt) { return `

Kein App Store nötig — direkt auf den Home-Bildschirm.

`; } if (isIOS && isSafari) { return `

So kommt Ban Yaro auf deinen Home-Bildschirm:

${_steps([ ['share', 'Tippe unten in Safari auf das Teilen-Symbol '], ['rows-plus-top', 'Wähle „Zum Home-Bildschirm" aus der Liste'], ['check', 'Tippe oben rechts auf „Hinzufügen"'], ])}

Funktioniert nur in Safari — nicht in Chrome oder Firefox auf iOS.

`; } if (isIOS && !isSafari) { return `

Auf dem iPhone geht die Installation nur über Safari.

${_steps([ ['safari-logo', 'Öffne Safari auf deinem iPhone'], ['arrow-square-in','Gib banyaro.app in die Adressleiste ein'], ['share', 'Tippe auf das Teilen-Symbol und wähle „Zum Home-Bildschirm"'], ])} `; } if (isAndroid) { return `

Am einfachsten geht es mit Chrome:

${_steps([ ['arrow-square-in', 'Öffne banyaro.app in Chrome'], ['dots-three-circle','Tippe auf das Menü ⋮ oben rechts'], ['download-simple', 'Wähle „App installieren" oder
„Zum Startbildschirm hinzufügen"'], ])} `; } 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!'], ])}
`; } function _steps(list) { return `
    ${list.map(([icon, text]) => `
  1. ${text}
  2. `).join('')}
`; } // ---------------------------------------------------------- // EVENTS // ---------------------------------------------------------- function _bindEvents() { // Install-Prompt Buttons const installBtn = async () => { const prompt = App.getInstallPrompt(); if (!prompt) return; prompt.prompt(); const { outcome } = await prompt.userChoice; if (outcome === 'accepted') { UI.toast.success('Ban Yaro wird installiert!'); _render(); } }; _container.querySelector('#install-android-btn')?.addEventListener('click', installBtn); _container.querySelector('#welcome-install-hero-btn')?.addEventListener('click', installBtn); _container.querySelector('#welcome-install-hero-btn2')?.addEventListener('click', installBtn); // Register / Login const toSettings = () => App.navigate('settings'); _container.querySelector('#welcome-register-btn')?.addEventListener('click', toSettings); _container.querySelector('#welcome-register-btn2')?.addEventListener('click', toSettings); _container.querySelector('#welcome-login-btn')?.addEventListener('click', toSettings); // Installationsanleitung Link _container.querySelector('#welcome-install-link')?.addEventListener('click', () => { App.navigate('welcome', true, { install: true }); }); // Link kopieren _container.querySelector('#install-copy-btn')?.addEventListener('click', async () => { await navigator.clipboard.writeText('https://banyaro.app'); UI.toast.success('Link kopiert!'); }); // Desktop-Tabs Android / iOS _container.querySelector('#inst-tab-android')?.addEventListener('click', () => { _container.querySelector('#inst-panel-android').style.display = ''; _container.querySelector('#inst-panel-ios').style.display = 'none'; _container.querySelector('#inst-tab-android').style.cssText += ';background:var(--c-primary);color:#fff;border:none'; _container.querySelector('#inst-tab-ios').className = 'btn btn-sm btn-ghost'; _container.querySelector('#inst-tab-ios').style.cssText = 'flex:1'; }); _container.querySelector('#inst-tab-ios')?.addEventListener('click', () => { _container.querySelector('#inst-panel-android').style.display = 'none'; _container.querySelector('#inst-panel-ios').style.display = ''; _container.querySelector('#inst-tab-ios').style.cssText += ';background:var(--c-primary);color:#fff;border:none'; _container.querySelector('#inst-tab-android').className = 'btn btn-sm btn-ghost'; _container.querySelector('#inst-tab-android').style.cssText = 'flex:1'; }); // "Und noch mehr"-Toggle const moreToggle = _container.querySelector('#wc-more-toggle'); const moreGrid = _container.querySelector('#wc-more-grid'); moreToggle?.addEventListener('click', () => { const open = moreToggle.getAttribute('aria-expanded') === 'true'; moreToggle.setAttribute('aria-expanded', String(!open)); moreGrid.classList.toggle('wc-grid--collapsed', open); moreToggle.querySelector('.wc-more-chevron').style.transform = open ? '' : 'rotate(180deg)'; }); // Feature-Tiles (nur eingeloggte Ansicht) _container.querySelectorAll('[data-nav]').forEach(btn => { btn.addEventListener('click', () => App.navigate(btn.dataset.nav)); }); // Hero-Rotation starten (nur Landing) if (!_appState?.user) _startHeroRotation(); } function _pulseMenuBtn() { const btn = document.getElementById('header-menu-btn'); if (!btn) return; setTimeout(() => { btn.classList.add('wc-pulsing'); btn.addEventListener('animationend', () => btn.classList.remove('wc-pulsing'), { once: true }); }, 1200); } return { init, refresh, onDogChange }; })();