/* ============================================================ BAN YARO — Öffentliches Züchter-Profil (Visitenkarte) ============================================================ */ window.Page_breeder = (() => { let _container = null; let _appState = null; const _esc = s => UI.esc ? UI.esc(s) : String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); // ---------------------------------------------------------- // INIT // ---------------------------------------------------------- async function init(container, appState, params = {}) { _container = container; _appState = appState; const zwingername = params?.zwingername || decodeURIComponent((window.location.pathname.split('/breeder/')[1] || '').replace(/\/$/, '')); if (!zwingername) { container.innerHTML = '
Kein Zwingername angegeben.
'; return; } container.innerHTML = `
${UI.skeleton(5)}
`; document.getElementById('breeder-back-fab') ?.addEventListener('click', () => App.navigate('wurfboerse')); try { const p = await API.breeder.profile(zwingername); _render(p); } catch (e) { document.getElementById('breeder-profile-body').innerHTML = `
${UI.icon('magnifying-glass')} ${_esc(e.message || 'Züchter nicht gefunden.')}
`; } } // ---------------------------------------------------------- // RENDER // ---------------------------------------------------------- function _render(p) { const body = document.getElementById('breeder-profile-body') || _container; const seit = p.verified_at ? new Date(p.verified_at).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' }) : null; const isLoggedIn = !!_appState?.user; const isOwnProfile = _appState?.user?.id === p.zuechter_user_id; body.innerHTML = `

${UI.icon('seal-check')} Verifizierter Züchter

${_esc(p.zwingername)}

${p.rasse_text ? `${_esc(p.rasse_text)}` : ''} ${p.vdh_mitglied ? `${UI.icon('certificate')} VDH` : ''} ${p.stadt ? `${UI.icon('map-pin')} ${_esc(p.stadt)}` : ''} ${seit ? `Züchter seit ${_esc(seit)}` : ''}
${p.logo_url ? `Zwinger-Logo` : `
` }
${!isOwnProfile ? `
${isLoggedIn ? `` : `` } ${p.website ? ` ${UI.icon('arrow-square-out')} Website ` : ''}
` : ''}
${p.beschreibung ? `

${_esc(p.beschreibung)}

` : ''} ${p.hunde?.length ? `

${UI.icon('dog')} Unsere Zuchthunde ${p.hunde.length} Hunde

${p.hunde.map(h => _hundCard(h)).join('')}
` : ''} ${p.wuerfe?.length ? `

${UI.icon('baby')} Aktuelle Würfe

${p.wuerfe.map(w => _wurfCard(w)).join('')}
` : ''} ${(p.hd_stats?.length || p.ed_stats?.length) ? `

${UI.icon('heartbeat')} Gesundheits-Transparenz

${_statsSection('HD-Ergebnisse', p.hd_stats)} ${p.hd_stats?.length && p.ed_stats?.length ? '
' : ''} ${_statsSection('ED-Ergebnisse', p.ed_stats)}
` : ''}

${UI.icon('info')} Über den Züchter

${_dl('Züchter', p.zuechter_name)} ${_dl('Rasse(n)', p.rasse_text)} ${_dl('Verein', p.verein)} ${_dl('VDH-Mitglied', p.vdh_mitglied ? '✓ Ja' : 'Nein')} ${_dl('Stadt', p.stadt)} ${p.website ? `
Website
${_esc(p.website)}
` : ''} ${seit ? _dl('Züchter seit', seit) : ''}
${p.fotos?.length ? `

${UI.icon('images')} Galerie ${p.fotos.length} Fotos

${p.fotos.map((ph, i) => ` ${_esc(ph.caption)} ${ph.primary ? `Logo` : ''} ${ph.caption ? `
${_esc(ph.caption)}
` : ''}
`).join('')}
` : ''}
`; // Events body.querySelector('.breeder-chat-btn')?.addEventListener('click', () => _contactBreeder(p.zuechter_user_id)); body.querySelector('.breeder-login-btn')?.addEventListener('click', () => App.navigate('settings')); _loadBreederPhotos(p.id); } // ---------------------------------------------------------- // Hund-Karte // ---------------------------------------------------------- function _hundCard(h) { const alter = h.geburtsdatum ? Math.floor((Date.now() - new Date(h.geburtsdatum)) / 31557600000) : null; const gIcon = h.geschlecht === 'maennlich' ? UI.icon('gender-male') : UI.icon('gender-female'); const hdTest = h.health_tests?.find(t => t.test_typ === 'HD'); const edTest = h.health_tests?.find(t => t.test_typ === 'ED'); const augeTest = h.health_tests?.find(t => t.test_typ === 'augen'); const testPills = [ hdTest ? `HD ${_esc(hdTest.ergebnis)}` : '', edTest ? `ED ${_esc(edTest.ergebnis)}` : '', augeTest ? `Augen ✓` : '', ].filter(Boolean).join(''); const titlePills = (h.titel || []).map(t => `${_esc(t)}` ).join(''); const genBadge = h.gentests_total > 0 ? ` ${h.gentests_clear}/${h.gentests_total} Gentests frei ` : ''; return `
${gIcon} ${_esc(h.name)} ${h.rufname ? `"${_esc(h.rufname)}"` : ''} ${alter !== null ? `${alter} J.` : ''}
${h.farbe ? `

${_esc(h.farbe)}

` : ''} ${testPills ? `
${testPills}
` : ''} ${titlePills ? `
${titlePills}
` : ''} ${genBadge}
`; } function _testPillStyle(ergebnis, typ) { const e = (ergebnis || '').toUpperCase(); let bg = '#6b72801a', color = '#6b7280', border = '#6b728040'; if (typ === 'HD') { if (['A','A1','A2'].includes(e)) { bg='#16a34a1a';color='#16a34a';border='#16a34a40'; } else if (e === 'B' || e === 'B1' || e === 'B2') { bg='#86efac1a';color='#15803d';border='#86efac40'; } else if (e === 'C') { bg='#eab3081a';color='#a16207';border='#eab30840'; } else if (e === 'D' || e === 'E') { bg='#ef44441a';color='#dc2626';border='#ef444440'; } } else if (typ === 'ED') { if (e === '0' || e === 'ED 0') { bg='#16a34a1a';color='#16a34a';border='#16a34a40'; } else if (e === '1') { bg='#eab3081a';color='#a16207';border='#eab30840'; } else if (e === '2' || e === '3') { bg='#ef44441a';color='#dc2626';border='#ef444440'; } } else if (typ === 'augen' || ergebnis === 'clear') { bg='#16a34a1a';color='#16a34a';border='#16a34a40'; } return `background:${bg};color:${color};border:1px solid ${border};border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600`; } // ---------------------------------------------------------- // Wurf-Karte // ---------------------------------------------------------- const _STATUS_LABEL = { geplant: 'Geplant', geboren: 'Geboren', verfuegbar: 'Verfügbar', abgeschlossen: 'Abgeschlossen' }; const _STATUS_COLOR = { geplant: '#6b7280', geboren: '#3b82f6', verfuegbar: '#16a34a', abgeschlossen: '#9ca3af' }; function _wurfCard(w) { const eltern = [w.vater_name, w.mutter_name].filter(Boolean).join(' × ') || '—'; const datum = w.geburt_datum ? `Geburt: ${_fmtDate(w.geburt_datum)}` : w.erwartetes_datum ? `Erwartet: ${_fmtDate(w.erwartetes_datum)}` : ''; const sc = _STATUS_COLOR[w.status] || '#6b7280'; const sl = _STATUS_LABEL[w.status] || w.status; return `
${_esc(eltern)} ${sl}
${datum ? `${UI.icon('calendar-dots')} ${_esc(datum)}` : ''} ${w.welpen_gesamt ? `${UI.icon('dog')} ${w.welpen_verfuegbar ?? '?'}/${w.welpen_gesamt} verfügbar` : ''} ${w.preis_spanne ? `${UI.icon('currency-eur')} ${_esc(w.preis_spanne)}` : ''}
${w.beschreibung ? `

${_esc(w.beschreibung)}

` : ''}
`; } // ---------------------------------------------------------- // Statistik-Sektion // ---------------------------------------------------------- function _statsSection(label, stats) { if (!stats?.length) return ''; const total = stats.reduce((s, r) => s + r.cnt, 0); return `

${_esc(label)}

${stats.map(r => `
${_esc(r.ergebnis || '—')} ${r.cnt}×
`).join('')}
`; } // ---------------------------------------------------------- // Hilfsfunktionen // ---------------------------------------------------------- function _dl(label, value) { if (!value) return ''; return `
${_esc(label)}
${_esc(String(value))}
`; } function _fmtDate(iso) { if (!iso) return '—'; const [y,m,d] = iso.slice(0,10).split('-'); return `${d}.${m}.${y}`; } async function _loadBreederPhotos(breederId) { const section = document.getElementById('breeder-photos-section'); if (!section) return; try { const photos = await API.breederPhotos.list('breeder', breederId); if (!photos?.length) return; section.innerHTML = `

${UI.icon('images')} Fotos

${photos.map(ph => ` ${_esc(ph.caption||'')} `).join('')}
`; } catch (_) {} } async function _contactBreeder(userId) { if (!_appState?.user) { App.navigate('settings'); return; } try { await API.chat.start(userId); App.navigate('chat'); } catch (e) { UI.toast.error(e.message || 'Chat konnte nicht geöffnet werden.'); } } function refresh() {} function onDogChange() {} function destroy() { document.getElementById('breeder-back-fab')?.remove(); } return { init, refresh, onDogChange, destroy }; })();