/* ============================================================ BAN YARO — Einstellungen / Account Login, Registrierung, Logout, Account-Info. ============================================================ */ window.Page_settings = (() => { let _container = null; let _appState = null; let _mode = 'login'; // 'login' | 'register' // ---------------------------------------------------------- // INIT / REFRESH // ---------------------------------------------------------- async function init(container, appState) { _container = container; _appState = appState; _render(); } function refresh() { _render(); } // ---------------------------------------------------------- // RENDER // ---------------------------------------------------------- function _render() { if (_appState.user) { _renderAccount(); } else { _renderAuth(_mode); } } // ---------------------------------------------------------- // EINGELOGGT — Account-Übersicht // ---------------------------------------------------------- function _renderAccount() { const u = _appState.user; // Avatar: Bild oder Buchstabe const avatarInner = u.avatar_url ? `Avatar` : _esc(u.name.charAt(0).toUpperCase()); // Mitglied seit const memberSince = (() => { if (!u.created_at) return ''; const d = new Date(u.created_at); return d.toLocaleDateString('de-DE', { month: 'long', year: 'numeric' }); })(); // Erfahrungs-Labels const erfahrungLabel = { einsteiger: 'Einsteiger (erster Hund)', erfahren: 'Erfahrener Hundehalter', trainer: 'Trainer / Ausbilder', zuechter: 'Züchter', }; _container.innerHTML = `
${avatarInner}
${_esc(u.name)}
${_esc(u.email)}
${u.is_premium ? ` Ban Yaro Plus ` : ` Kostenlos `}
Mein Profil
${memberSince ? `
Mitglied seit ${_esc(memberSince)}
` : ''} ${u.bio ? `
${_esc(u.bio)}
` : ''} ${u.wohnort ? `
📍 ${_esc(u.wohnort)}
` : ''} ${u.erfahrung && erfahrungLabel[u.erfahrung] ? `
${_esc(erfahrungLabel[u.erfahrung])}
` : ''} ${u.social_link ? `
${_esc(u.social_link)}
` : ''} ${!u.bio && !u.wohnort && !u.erfahrung && !u.social_link ? `
Noch kein Profil ausgefüllt.
` : ''}
App-Einstellungen
Pocket-Modus beim Aufzeichnen
Schwarzes Overlay hält den Bildschirm aktiv (GPS läuft) — ideal für die Hosentasche. Helligkeit auf Minimum reduzieren für optimalen Akku-Schutz.
App installieren
Ban Yaro · banyaro.app
Deine Daten liegen auf einem eigenen Server in Deutschland.
`; // Avatar-Hover-Overlay const avatarBtn = document.getElementById('settings-avatar-btn'); const avatarOverlay = avatarBtn?.querySelector('.avatar-overlay'); if (avatarBtn && avatarOverlay) { avatarBtn.addEventListener('mouseenter', () => { avatarOverlay.style.opacity = '1'; }); avatarBtn.addEventListener('mouseleave', () => { avatarOverlay.style.opacity = '0'; }); } // Avatar-Upload avatarBtn?.addEventListener('click', () => { document.getElementById('settings-avatar-input')?.click(); }); document.getElementById('settings-avatar-input')?.addEventListener('change', async e => { const file = e.target.files?.[0]; if (!file) return; try { const fd = new FormData(); fd.append('file', file); const res = await API.post('/profile/avatar', fd); _appState.user.avatar_url = res.avatar_url; UI.toast.success('Avatar aktualisiert.'); _render(); } catch { UI.toast.error('Avatar-Upload fehlgeschlagen.'); } }); // Profil bearbeiten document.getElementById('settings-profile-edit-btn')?.addEventListener('click', () => { const u = _appState.user; const inputStyle = `width:100%;box-sizing:border-box;padding:var(--space-2) var(--space-3); border:1.5px solid var(--c-border);border-radius:var(--radius-md); font-size:var(--text-sm);font-family:inherit; background:var(--c-surface);color:var(--c-text)`; const erfahrungOpts = [ ['', 'Bitte wählen...'], ['einsteiger', 'Einsteiger (erster Hund)'], ['erfahren', 'Erfahrener Hundehalter'], ['trainer', 'Trainer / Ausbilder'], ['zuechter', 'Züchter'], ].map(([val, label]) => `` ).join(''); const sichtbarkeitOpts = [ ['public', 'Öffentlich'], ['friends', 'Nur Freunde'], ['private', 'Privat'], ].map(([val, label]) => `` ).join(''); UI.modal.open({ title: 'Profil bearbeiten', body: `
`, footer: ` `, }); document.getElementById('profile-form')?.addEventListener('submit', async e => { e.preventDefault(); const btn = document.querySelector('[form="profile-form"]'); const fd = UI.formData(e.target); await UI.asyncButton(btn, async () => { const updated = await API.patch('/profile', { bio: fd.bio || '', wohnort: fd.wohnort || '', erfahrung: fd.erfahrung || '', social_link: fd.social_link || '', profil_sichtbarkeit: fd.profil_sichtbarkeit || 'public', }); Object.assign(_appState.user, updated); UI.modal.close?.(); UI.toast.success('Profil gespeichert.'); _render(); }); }); }); document.getElementById('settings-logout-btn')?.addEventListener('click', async () => { const ok = await UI.modal.confirm({ title : 'Abmelden?', message: 'Du wirst aus deinem Konto abgemeldet.', confirmText: 'Abmelden', }); if (!ok) return; try { await API.auth.logout(); } catch { /* cookie wird trotzdem gelöscht */ } _appState.user = null; _appState.dogs = []; _appState.activeDog = null; UI.toast.info('Du wurdest abgemeldet.'); _render(); }); document.getElementById('settings-install-btn')?.addEventListener('click', () => { App.navigate('welcome'); }); document.getElementById('settings-push-btn')?.addEventListener('click', async () => { try { await API.subscribeToPush(); UI.toast.success('Push-Benachrichtigungen aktiviert.'); } catch { UI.toast.warning('Push-Benachrichtigungen konnten nicht aktiviert werden.'); } }); document.getElementById('settings-calendar-btn')?.addEventListener('click', async () => { try { const { token } = await API.webcal.getToken(); const url = `webcal://${location.host}/api/webcal/${token}.ics`; const httpsUrl = `https://${location.host}/api/webcal/${token}.ics`; UI.modal.open({ title: `${UI.icon('calendar-dots')} Kalender abonnieren`, body: `

Abonniere deinen persönlichen Ban-Yaro-Kalender. Er enthält Impf-Erinnerungen, Läufigkeits-Termine, Events und Gassi-Treffen — immer aktuell.

${httpsUrl}
${UI.icon('calendar-dots')} In Kalender-App öffnen

Tipp: iOS → Einstellungen › Kalender › Accounts › Account hinzufügen › Andere › Kalenderabo

`, }); document.getElementById('cal-copy-btn')?.addEventListener('click', async () => { try { await navigator.clipboard.writeText(httpsUrl); UI.toast.success('URL kopiert.'); } catch { UI.toast.warning('Kopieren nicht möglich — URL oben manuell kopieren.'); } }); } catch(err) { console.error('Kalender-Fehler:', err); UI.toast.error('Kalender-Token konnte nicht geladen werden: ' + (err?.message || err)); } }); document.getElementById('toggle-pocket-mode')?.addEventListener('change', e => { localStorage.setItem('by_pocket_mode', String(e.target.checked)); UI.toast.info(e.target.checked ? 'Pocket-Modus aktiviert — Bildschirm bleibt bei Aufzeichnung an.' : 'Pocket-Modus deaktiviert.'); }); } // ---------------------------------------------------------- // NICHT EINGELOGGT — Login / Registrierung // ---------------------------------------------------------- function _renderAuth(mode) { _mode = mode; _container.innerHTML = `
Ban Yaro

Ban Yaro

Alles rund um deinen Hund

${mode === 'login' ? _loginFormHTML() : _registerFormHTML()}
`; document.getElementById('tab-login') ?.addEventListener('click', () => _renderAuth('login')); document.getElementById('tab-register') ?.addEventListener('click', () => _renderAuth('register')); if (mode === 'login') { _bindLoginForm(); } else { _bindRegisterForm(); } } function _loginFormHTML() { return `
`; } function _registerFormHTML() { return `

Mit der Registrierung stimmst du unseren Datenschutzhinweisen zu.
Deine Daten werden ausschließlich auf unserem Server gespeichert.

`; } function _bindLoginForm() { document.getElementById('auth-form')?.addEventListener('submit', async e => { e.preventDefault(); const btn = e.target.querySelector('[type="submit"]'); const fd = UI.formData(e.target); await UI.asyncButton(btn, async () => { const result = await API.auth.login(fd.email, fd.password); localStorage.setItem('by_token', result.token); // User-Daten laden _appState.user = await API.auth.me(); document.getElementById('sidebar-username').textContent = _appState.user.name; // Hunde laden try { _appState.dogs = await API.dogs.list(); _appState.activeDog = _appState.dogs[0] || null; } catch { /* keine Hunde = okay */ } UI.toast.success(`Willkommen zurück, ${_appState.user.name}!`); // Push-Benachrichtigungen anbieten wenn noch nicht entschieden if (typeof Notification !== 'undefined' && Notification.permission === 'default') { _offerPushNotifications(); } // Nach Login: Tagebuch oder Profil anlegen if (_appState.activeDog) { App.navigate('diary'); } else { App.navigate('dog-profile'); } }); }); } function _bindRegisterForm() { document.getElementById('auth-form')?.addEventListener('submit', async e => { e.preventDefault(); const btn = e.target.querySelector('[type="submit"]'); const fd = UI.formData(e.target); if (!fd.name?.trim()) { UI.toast.warning('Bitte einen Namen eingeben.'); return; } if ((fd.password || '').length < 8) { UI.toast.warning('Passwort muss mindestens 8 Zeichen lang sein.'); return; } await UI.asyncButton(btn, async () => { const result = await API.auth.register(fd.email, fd.password, fd.name.trim()); localStorage.setItem('by_token', result.token); _appState.user = await API.auth.me(); document.getElementById('sidebar-username').textContent = _appState.user.name; _appState.dogs = []; _appState.activeDog = null; UI.toast.success(`Willkommen bei Ban Yaro, ${_appState.user.name}!`); // Onboarding-Modal direkt zeigen (SPA — kein Reload) App.showOnboarding(); }); }); } // ---------------------------------------------------------- // PUSH-BENACHRICHTIGUNGEN ANBIETEN (nach Login) // ---------------------------------------------------------- function _offerPushNotifications() { // Kleiner Toast-Banner mit Ja-Button — nicht-invasiv const toastEl = document.createElement('div'); toastEl.id = 'push-offer-banner'; toastEl.style.cssText = [ 'position:fixed', 'bottom:calc(var(--nav-h, 64px) + var(--space-3))', 'left:50%', 'transform:translateX(-50%)', 'background:var(--c-surface)', 'border:1.5px solid var(--c-border)', 'border-radius:var(--radius-lg)', 'box-shadow:var(--shadow-lg)', 'padding:var(--space-3) var(--space-4)', 'display:flex', 'align-items:center', 'gap:var(--space-3)', 'font-size:var(--text-sm)', 'z-index:1100', 'max-width:340px', 'width:calc(100% - var(--space-8))', ].join(';'); toastEl.innerHTML = ` Push-Benachrichtigungen aktivieren? `; document.body.appendChild(toastEl); const remove = () => toastEl.remove(); document.getElementById('push-offer-yes')?.addEventListener('click', async () => { remove(); try { await API.subscribeToPush(); UI.toast.success('Push-Benachrichtigungen aktiviert.'); } catch { UI.toast.warning('Push-Benachrichtigungen konnten nicht aktiviert werden.'); } }); document.getElementById('push-offer-no')?.addEventListener('click', remove); // Automatisch ausblenden nach 12 Sekunden setTimeout(remove, 12000); } // ---------------------------------------------------------- // HELPER // ---------------------------------------------------------- function _esc(str) { if (!str) return ''; return str.replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"'); } // ---------------------------------------------------------- // PUBLIC // ---------------------------------------------------------- return { init, refresh }; })();