/* ============================================================ 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; // Hunde frisch laden — der appState kann veraltet sein (z.B. nach // Anlage in mobiler App). Wenn schon ein Hund da ist, Wizard // komplett überspringen. try { const dogs = await API.dogs.list(); _appState.dogs = dogs; if (dogs.length > 0) { _appState.activeDog = dogs[0]; localStorage.setItem('by_active_dog', String(dogs[0].id)); localStorage.setItem('by_onboarding_done', '1'); App.renderDogSwitcher?.(); if (window.Worlds) window.Worlds.init(_appState); else App.navigate('diary'); return; } } catch (e) { // Lieber Wizard zeigen als komplett blockieren — wenn API down ist, // landet der User halt im Standard-Flow. console.warn('Onboarding: dog-list refresh failed', e); } _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 ? `

${UI.escape(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) — direkt ins richtige Hunde-Profil, // statt eines doppelten Mini-Formulars im Wizard. Onboarding gilt // damit als erledigt, sobald der User dort angekommen ist. _container.querySelector('#ob-next-btn')?.addEventListener('click', () => { localStorage.setItem('by_onboarding_done', '1'); App.navigate('dog-profile'); }); // 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(`${UI.escape(dog.name)} wurde angelegt!`); _step = 3; _render(); } catch (err) { // 403 „schon einen Hund" → kein Stuck-State, weiter zu Schritt 3 const isAlreadyHas = err?.status === 403 || /Pro-Feature|schon|already|maximal/i.test(err?.message || ''); if (isAlreadyHas) { try { const dogs = await API.dogs.list(); _appState.dogs = dogs; if (dogs.length > 0) { _appState.activeDog = dogs[0]; localStorage.setItem('by_active_dog', String(dogs[0].id)); App.renderDogSwitcher?.(); } } catch {} UI.toast.info?.('Du hast bereits einen Hund — geht direkt weiter.'); _step = 3; _render(); return; } 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) { if (window.Worlds) window.Worlds.init(_appState); else App.navigate('diary'); } else { // Ohne Hund: Welten zeigen (HUND-Tab mit "Jetzt anlegen"-Karte) if (window.Worlds) window.Worlds.init(_appState); else App.navigate('welcome'); } } // ---------------------------------------------------------- // HELPER // ---------------------------------------------------------- // ---------------------------------------------------------- // PUBLIC // ---------------------------------------------------------- return { init, refresh, onDogChange }; })();