/* ============================================================ BAN YARO — Freunde ============================================================ */ window.Page_friends = (() => { let _container = null; let _appState = null; let _searchTimer = null; // ---------------------------------------------------------- async function init(container, appState, params = {}) { _container = container; _appState = appState; _render(params.suche || null); } function refresh() { _loadFriends(); } function onDogChange() {} // ---------------------------------------------------------- // HAUPT-RENDER // ---------------------------------------------------------- function _render(prefill = null) { const myName = _appState?.user?.name || ''; const myLink = `${location.origin}/#friends?suche=${encodeURIComponent(myName)}`; _container.innerHTML = `
Dein Freundes-Link
Teile ihn — der andere tippt drauf und findet dich sofort.
banyaro.app/#friends?suche=${_esc(encodeURIComponent(myName))}

Tipp: Lass dir den Freundes-Link einer anderen Person schicken — dann klappt die Suche automatisch.

`; // Copy-Button _container.querySelector('#fr-copy-btn')?.addEventListener('click', () => { navigator.clipboard.writeText(myLink).then(() => { UI.toast.success('Link kopiert!'); }).catch(() => { UI.toast.info('Link: ' + myLink); }); }); // Share-Button (Web Share API, Fallback: Copy) _container.querySelector('#fr-share-btn')?.addEventListener('click', async () => { if (navigator.share) { try { await navigator.share({ title: `${myName} auf Ban Yaro`, text: `Füge mich auf Ban Yaro als Freund hinzu!`, url: myLink, }); } catch { /* abgebrochen */ } } else { navigator.clipboard.writeText(myLink).then(() => { UI.toast.success('Link kopiert!'); }); } }); // Suche const searchInput = _container.querySelector('#fr-search'); searchInput.addEventListener('input', e => { clearTimeout(_searchTimer); const q = e.target.value.trim(); if (q.length < 2) { _container.querySelector('#fr-search-results').innerHTML = ''; return; } _searchTimer = setTimeout(() => _doSearch(q), 380); }); // Prefill aus URL-Parameter → sofort suchen if (prefill && prefill.length >= 2) { _doSearch(prefill); } _loadFriends(); } // ---------------------------------------------------------- // DATEN LADEN // ---------------------------------------------------------- async function _loadFriends() { try { const data = await API.friends.list(); _renderIncoming(data.incoming || []); _renderOutgoing(data.outgoing || []); _renderFriends(data.friends || []); _updateBadge((data.incoming || []).length); } catch { /* 401 wird vom Auth-Guard abgefangen */ } } function _updateBadge(count) { const el = document.getElementById('friends-badge'); if (!el) return; el.textContent = count; el.style.display = count > 0 ? '' : 'none'; } // ---------------------------------------------------------- // EINGEHENDE ANFRAGEN // ---------------------------------------------------------- function _renderIncoming(list) { const el = _container.querySelector('#fr-incoming'); if (!list.length) { el.innerHTML = ''; return; } el.innerHTML = `
Anfragen · ${list.length}
${list.map(r => `
${_userAvatar(r.requester_name, r.dogs?.[0])}
${_esc(r.requester_name)}
${_dogPills(r.dogs, 2)}
`).join('')}
`; } // ---------------------------------------------------------- // GESENDETE ANFRAGEN // ---------------------------------------------------------- function _renderOutgoing(list) { const el = _container.querySelector('#fr-outgoing'); if (!list.length) { el.innerHTML = ''; return; } el.innerHTML = `
Gesendet
${list.map(r => `
${_esc((r.addressee_name || '?')[0].toUpperCase())}
${_esc(r.addressee_name)}
Anfrage ausstehend
`).join('')}
`; } // ---------------------------------------------------------- // FREUNDESLISTE // ---------------------------------------------------------- function _renderFriends(list) { const el = _container.querySelector('#fr-list'); if (!list.length) { el.innerHTML = `

Noch keine Hundefreunde

Suche oben nach anderen Hundebesitzern und schick ihnen eine Anfrage.

`; return; } el.innerHTML = `
Freunde · ${list.length}
${list.map(f => _friendCard(f)).join('')}
`; // Klick auf Karte → Mini-Profil el.querySelectorAll('.fr-card').forEach(card => { card.addEventListener('click', e => { if (e.target.closest('button')) return; // Buttons nicht überschreiben const fid = parseInt(card.dataset.friendId); const fname = card.dataset.friendName; const fdogs = JSON.parse(card.dataset.dogs || '[]'); _showProfile(fid, fname, fdogs); }); }); } function _friendCard(f) { const dogs = f.dogs || []; return `
${_userAvatar(f.friend_name, dogs[0])}
${_esc(f.friend_name)}
${dogs.length ? `
${_dogPills(dogs, 3)}
` : `
Noch kein Hund eingetragen
` }
${_dogPhotoRow(dogs)}
`; } function _dogPhotoRow(dogs) { const withPhotos = dogs.filter(d => d.foto_url); if (withPhotos.length < 2) return ''; // 1 Foto schon im Avatar, < 2 lohnt sich nicht return `
${withPhotos.slice(0, 4).map(d => `
${_esc(d.name)}
${_esc(d.name)}
`).join('')}
`; } // ---------------------------------------------------------- // MINI-PROFIL MODAL // ---------------------------------------------------------- function _showProfile(friendId, friendName, dogs) { const dogsHTML = dogs.length ? `
${dogs.map(d => `
${d.foto_url ? `${_esc(d.name)}` : `
🐕
` }
${_esc(d.name)}
${d.rasse ? `
${_esc(d.rasse)}
` : ''}
`).join('')}
` : `

Noch kein Hund eingetragen.

`; UI.modal.open({ title: _esc(friendName), body: `
${dogs.length === 1 ? 'Hund' : 'Hunde'}
${dogsHTML}
`, footer: ` `, }); document.getElementById('modal-chat-btn')?.addEventListener('click', () => { UI.modal.close(); _openChat(friendId); }); document.getElementById('modal-remove-btn')?.addEventListener('click', async () => { UI.modal.close(); await _removeFriend(friendId, friendName); }); } // ---------------------------------------------------------- // SUCHE // ---------------------------------------------------------- async function _doSearch(q) { const el = _container.querySelector('#fr-search-results'); try { const results = await API.friends.search(q); if (!results.length) { el.innerHTML = `
Kein Nutzer gefunden.
`; return; } el.innerHTML = `
${results.map((u, i) => `
${_userAvatar(u.name, null)}
${_esc(u.name)}
${u.dogs?.length ? `
${u.dogs.map(d => _esc(d.name) + (d.rasse ? ` · ${_esc(d.rasse)}` : '')).join('  |  ')}
` : ''}
`).join('')}
`; el.querySelectorAll('.fr-add-btn').forEach(btn => { btn.addEventListener('click', () => _sendRequest(parseInt(btn.dataset.userId), btn)); }); } catch { el.innerHTML = ''; } } // ---------------------------------------------------------- // AKTIONEN // ---------------------------------------------------------- async function _sendRequest(userId, btn) { btn.disabled = true; btn.innerHTML = ``; try { await API.friends.sendRequest(userId); UI.toast.success('Freundschaftsanfrage gesendet!'); _container.querySelector('#fr-search').value = ''; _container.querySelector('#fr-search-results').innerHTML = ''; await _loadFriends(); } catch (e) { UI.toast.error(e.message || 'Fehler beim Senden.'); btn.disabled = false; btn.innerHTML = ` Anfrage`; } } async function _accept(id) { try { await API.friends.accept(id); UI.toast.success('Freundschaft angenommen!'); await _loadFriends(); } catch (e) { UI.toast.error(e.message); } } async function _decline(id) { try { await API.friends.decline(id); await _loadFriends(); } catch (e) { UI.toast.error(e.message); } } async function _cancel(id) { try { await API.friends.decline(id); await _loadFriends(); } catch (e) { UI.toast.error(e.message); } } async function _removeFriend(userId, name) { const ok = await UI.modal.confirm({ title: 'Freund entfernen?', message: `${name} wird aus deiner Freundesliste entfernt.`, confirmText: 'Entfernen', }); if (!ok) return; try { await API.friends.remove(userId); UI.toast.info('Freund entfernt.'); await _loadFriends(); } catch (e) { UI.toast.error(e.message); } } async function _openChat(userId) { try { const { conversation_id } = await API.chat.start(userId); App.navigate('chat', true, { conversation_id }); } catch (e) { UI.toast.error(e.message); } } // ---------------------------------------------------------- // RENDER-HELPERS // ---------------------------------------------------------- function _userAvatar(name, firstDog) { if (firstDog?.foto_url) { return `${_esc(firstDog.name)}`; } return `
${_esc((name || '?')[0].toUpperCase())}
`; } function _dogPills(dogs, max) { if (!dogs?.length) return ''; const visible = dogs.slice(0, max); const rest = dogs.length - max; return `
${visible.map(d => ` 🐕 ${_esc(d.name)}${d.rasse ? ` · ${_esc(d.rasse)}` : ''} `).join('')} ${rest > 0 ? `+${rest}` : ''}
`; } function _esc(s) { if (!s) return ''; return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } // ---------------------------------------------------------- return { init, refresh, onDogChange, _accept, _decline, _cancel, _removeFriend, _openChat }; })();