/* ============================================================
BAN YARO — Öffentliches Züchter-Profil (Visitenkarte)
============================================================ */
window.Page_breeder = (() => {
let _container = null;
let _appState = null;
// ----------------------------------------------------------
// 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)}
`;
// FAB an document.body hängen damit position:fixed zuverlässig funktioniert
// und destroy() der einzige Lifecycle-Kontrollpunkt bleibt
const fab = document.createElement('button');
fab.id = 'breeder-back-fab';
fab.setAttribute('aria-label', 'Zurück zur Wurfbörse');
fab.style.cssText = 'position:fixed;bottom:calc(var(--safe-bottom,0px) + 20px);right:20px;' +
'width:54px;height:54px;border-radius:50%;background:var(--c-primary);' +
'border:none;color:#fff;cursor:pointer;z-index:200;' +
'display:flex;align-items:center;justify-content:center;' +
'box-shadow:0 4px 18px rgba(196,132,58,.45);transition:transform .12s,box-shadow .12s;' +
'-webkit-tap-highlight-color:transparent';
fab.innerHTML = '';
fab.addEventListener('click', () => App.navigate('wurfboerse'));
document.body.appendChild(fab);
try {
const p = await API.breeder.profile(zwingername);
_render(p);
} catch (e) {
document.getElementById('breeder-profile-body').innerHTML =
`
${UI.icon('magnifying-glass')} ${UI.escape(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
${UI.escape(p.zwingername)}
${p.rasse_text ? `${UI.escape(p.rasse_text)}` : ''}
${p.vdh_mitglied ? `${UI.icon('certificate')} VDH` : ''}
${p.stadt ? `${UI.icon('map-pin')} ${UI.escape(p.stadt)}` : ''}
${seit ? `Züchter seit ${UI.escape(seit)}` : ''}
${p.logo_url
? `
})
`
: `
`
}
${!isOwnProfile ? `
` : ''}
${p.beschreibung ? `
${UI.escape(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 ? `
` : ''}
${seit ? _dl('Züchter seit', seit) : ''}
${p.fotos?.length ? `
${UI.icon('images')} Galerie
${p.fotos.length} Fotos
` : ''}
`;
// 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 ${UI.escape(hdTest.ergebnis)}` : '',
edTest ? `ED ${UI.escape(edTest.ergebnis)}` : '',
augeTest ? `Augen ✓` : '',
].filter(Boolean).join('');
const titlePills = (h.titel || []).map(t =>
`${UI.escape(t)}`
).join('');
const genBadge = h.gentests_total > 0
? `
${h.gentests_clear}/${h.gentests_total} Gentests frei
`
: '';
return `
${gIcon}
${UI.escape(h.name)}
${h.rufname ? `"${UI.escape(h.rufname)}"` : ''}
${alter !== null ? `${alter} J.` : ''}
${h.farbe ? `
${UI.escape(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 `
${UI.escape(eltern)}
${sl}
${datum ? `${UI.icon('calendar-dots')} ${UI.escape(datum)}` : ''}
${w.welpen_gesamt ? `${UI.icon('dog')} ${w.welpen_verfuegbar ?? '?'}/${w.welpen_gesamt} verfügbar` : ''}
${w.preis_spanne ? `${UI.icon('currency-eur')} ${UI.escape(w.preis_spanne)}` : ''}
${w.beschreibung ? `
${UI.escape(w.beschreibung)}
` : ''}
`;
}
// ----------------------------------------------------------
// Statistik-Sektion
// ----------------------------------------------------------
function _statsSection(label, stats) {
if (!stats?.length) return '';
const total = stats.reduce((s, r) => s + r.cnt, 0);
return `
${UI.escape(label)}
${stats.map(r => `
${UI.escape(r.ergebnis || '—')}
${r.cnt}×
`).join('')}
`;
}
// ----------------------------------------------------------
// Hilfsfunktionen
// ----------------------------------------------------------
function _dl(label, value) {
if (!value) return '';
return `
${UI.escape(label)}
${UI.escape(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 => `
`).join('')}
`;
section.classList.remove('hidden'); // Template startet mit .hidden (!important)
} 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 };
})();