/* ============================================================ BAN YARO — Adoption (Tierheim-Hunde in der Nähe) Seiten-Modul: Hunde aus deutschen Tierheimen finden. ============================================================ */ window.Page_adoption = (() => { // ---------------------------------------------------------- // MODUL-STATE // ---------------------------------------------------------- let _container = null; let _appState = null; let _lat = null; let _lon = null; let _radius = 50; let _rasseFilter = ''; let _activeTab = 'hunde'; let _data = null; // { animals, shelters, has_petfinder } let _loading = false; // ---------------------------------------------------------- // INIT // ---------------------------------------------------------- async function init(container, appState) { _container = container; _appState = appState; _render(); // Standort automatisch versuchen _tryAutoLocate(); } // ---------------------------------------------------------- // REFRESH // ---------------------------------------------------------- async function refresh() { if (_lat && _lon) { await _loadData(); } } // ---------------------------------------------------------- // RENDER — Grundstruktur // ---------------------------------------------------------- function _render() { _container.innerHTML = `
${UI.skeleton(4)}
`; // Events _container.querySelector('#adp-radius') ?.addEventListener('change', e => { _radius = parseInt(e.target.value); if (_lat && _lon) _loadData(); }); _container.querySelector('#adp-rasse') ?.addEventListener('input', e => { _rasseFilter = e.target.value.trim().toLowerCase(); _renderContent(); }); _container.querySelector('#adp-btn-locate') ?.addEventListener('click', _locateUser); _container.querySelector('#adp-btn-geocode') ?.addEventListener('click', _geocodePLZ); _container.querySelector('#adp-plz') ?.addEventListener('keydown', e => { if (e.key === 'Enter') _geocodePLZ(); }); _container.querySelectorAll('.adp-tab').forEach(btn => { btn.addEventListener('click', () => { _activeTab = btn.dataset.tab; _container.querySelectorAll('.adp-tab').forEach(b => { const isActive = b.dataset.tab === _activeTab; b.style.color = isActive ? 'var(--c-primary)' : 'var(--c-text-secondary)'; b.style.fontWeight = isActive ? '600' : 'normal'; b.style.borderBottom = isActive ? '2px solid var(--c-primary)' : '2px solid transparent'; }); _renderContent(); }); }); } // ---------------------------------------------------------- // STANDORT AUTOMATISCH ERMITTELN // ---------------------------------------------------------- async function _tryAutoLocate() { try { const pos = await API.getLocation({ timeout: 6000, maximumAge: 300_000 }); _lat = pos.lat; _lon = pos.lon; await _loadData(); } catch { // Standort nicht verfügbar → PLZ-Eingabe zeigen document.getElementById('adp-plz-row')?.style.setProperty('display', 'flex', 'important'); document.getElementById('adp-plz-row').style.display = 'flex'; _showNoLocation(); } } async function _locateUser() { const btn = _container.querySelector('#adp-btn-locate'); if (btn) btn.disabled = true; try { const pos = await API.getLocation({ timeout: 10000 }); _lat = pos.lat; _lon = pos.lon; document.getElementById('adp-plz-row').style.display = 'none'; await _loadData(); } catch { UI.toast.error('Standort konnte nicht ermittelt werden. Bitte PLZ eingeben.'); document.getElementById('adp-plz-row').style.display = 'flex'; } finally { if (btn) btn.disabled = false; } } async function _geocodePLZ() { const plz = (_container.querySelector('#adp-plz')?.value || '').trim(); if (!plz) return; const btn = _container.querySelector('#adp-btn-geocode'); if (btn) btn.disabled = true; try { const geo = await API.get(`/adoption/geocode?plz=${encodeURIComponent(plz)}`); if (geo.lat && geo.lon) { _lat = geo.lat; _lon = geo.lon; await _loadData(); } else { UI.toast.error(`PLZ "${plz}" nicht gefunden.`); } } catch { UI.toast.error('Geocoding fehlgeschlagen. Bitte erneut versuchen.'); } finally { if (btn) btn.disabled = false; } } // ---------------------------------------------------------- // DATEN LADEN // ---------------------------------------------------------- async function _loadData() { if (_loading || !_lat || !_lon) return; _loading = true; const content = _container.querySelector('#adp-content'); if (content) content.innerHTML = UI.skeleton(4); try { _data = await API.get(`/adoption/nearby?lat=${_lat}&lon=${_lon}&radius=${_radius}`); _renderContent(); } catch { if (content) content.innerHTML = UI.emptyState({ icon: 'warning', title: 'Daten konnten nicht geladen werden', text: 'Bitte versuche es erneut.', }); } finally { _loading = false; } } // ---------------------------------------------------------- // INHALT RENDERN (je nach Tab) // ---------------------------------------------------------- function _renderContent() { const content = _container.querySelector('#adp-content'); if (!content) return; if (!_data) { _showNoLocation(); return; } if (_activeTab === 'hunde') _renderHunde(content); else _renderTierheime(content); } function _showNoLocation() { const content = _container.querySelector('#adp-content'); if (!content) return; content.innerHTML = `
🐾

Finde Hunde in deiner Nähe

Erlaube den Zugriff auf deinen Standort oder gib eine PLZ ein, um Tierheim-Hunde in deiner Umgebung zu finden.

${UI.icon('arrow-square-out')} Alle Hunde auf Tierheimhelden.de
`; } // ------------------------------------------------------------------ // TAB: HUNDE // ------------------------------------------------------------------ function _renderHunde(content) { let animals = (_data?.animals || []); // Rasse-Filter if (_rasseFilter) { animals = animals.filter(a => (a.rasse || '').toLowerCase().includes(_rasseFilter) || (a.name || '').toLowerCase().includes(_rasseFilter) ); } const hasPetFinder = _data?.has_petfinder; const infoText = hasPetFinder ? `${animals.length} Hunde im Umkreis von ${_radius} km (via PetFinder)` : ''; if (!animals.length) { content.innerHTML = `

${_rasseFilter ? `Keine Hunde gefunden für "${_esc(_rasseFilter)}"` : `Keine Hunde im Umkreis von ${_radius} km gefunden.`}

${UI.icon('arrow-square-out')} Hunde auf Tierheimhelden.de suchen ${UI.icon('magnifying-glass')} Tierheimsuche auf tierschutz.com

Tipp: Schau auch im Tab „Tierheime" nach lokalen Tierheimen direkt.

`; return; } content.innerHTML = ` ${infoText ? `

${infoText}

` : ''}
${animals.map(a => _animalCard(a)).join('')}

Mehr Hunde finden:

${UI.icon('arrow-square-out')} Tierheimhelden.de — alle Hunde
`; // Klick-Events content.querySelectorAll('[data-adp-url]').forEach(card => { card.addEventListener('click', () => { window.open(card.dataset.adpUrl, '_blank', 'noopener,noreferrer'); }); }); } function _animalCard(a) { const foto = a.foto_url ? `${_esc(a.name)}` : '
🐶
'; const distTxt = a.distanz_km != null ? `${a.distanz_km} km` : ''; const alterTxt = a.alter_jahre != null ? `${_formatAlter(a.alter_jahre)}` : ''; const rasseTxt = a.rasse || ''; const tierheim = a.tierheim || ''; return `
${foto}
${_esc(a.name)}
${rasseTxt ? `
${_esc(rasseTxt)}
` : ''}
${alterTxt ? ` ${_esc(alterTxt)} ` : ''} ${a.geschlecht ? ` ${a.geschlecht === 'männlich' ? '♂' : '♀'} ` : ''} ${distTxt ? ` ${_esc(distTxt)} ` : ''}
${tierheim ? `
${UI.icon('house-line')} ${_esc(tierheim)}
` : ''}
`; } // ------------------------------------------------------------------ // TAB: TIERHEIME // ------------------------------------------------------------------ function _renderTierheime(content) { const shelters = _data?.shelters || []; if (!shelters.length) { content.innerHTML = `

Keine Tierheime im Umkreis von ${_radius} km gefunden.

${UI.icon('arrow-square-out')} Tierheimhelden.de
`; return; } content.innerHTML = `

${shelters.length} Tierheim${shelters.length !== 1 ? 'e' : ''} im Umkreis von ${_radius} km

${shelters.map(s => _shelterRow(s)).join('')}

Noch mehr Tierheime:

${UI.icon('arrow-square-out')} Tierheimhelden.de ${UI.icon('magnifying-glass')} tierschutz.com
`; } function _shelterRow(s) { return `
🏠
${_esc(s.name)}
${_esc(s.plz)} ${_esc(s.stadt)}
${s.distanz_km} km Hunde ansehen ${UI.icon('arrow-right')}
`; } // ---------------------------------------------------------- // HILFSFUNKTIONEN // ---------------------------------------------------------- function _formatAlter(jahre) { if (jahre < 0.5) return 'Welpe'; if (jahre < 1) return 'Jungtier'; if (jahre < 2) return `${Math.round(jahre)} Jahr`; if (jahre < 10) return `${Math.round(jahre)} Jahre`; return 'Senior'; } function _esc(s) { if (s == null) return ''; return String(s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } // ---------------------------------------------------------- // PUBLIC API // ---------------------------------------------------------- return { init, refresh }; })();