banyaro/backend/static/js/pages/breeder-dashboard.js
rene 487dacc7c7 Fix: /breeder/my-editor Endpoint (Crash 'Cannot destructure profile') + Läufigkeit in Züchter-Bereich
breeder-editor.js (aus 459cd42) rief /api/breeder/my-editor auf — Endpoint
existierte nie (gleicher Worktree-Verlust wie /partner/my-profile). Jetzt
gebaut: profile + litters + storage_mb/limit; ohne Profil klare 404 statt
Destrukturierungs-Crash. 3 Tests.

Läufigkeit (Rene): eigener HUND-Chip entfällt, stattdessen vierte Karte im
Züchter-Bereich (Zyklen, Progesterontests, Deckdaten). Suite: 58 passed.
2026-06-07 20:04:43 +02:00

140 lines
6.1 KiB
JavaScript

/* ============================================================
BAN YARO — Züchter-Bereich
Hub für Züchter: Profil-Status, Wurfverwaltung, Zuchtkartei.
(Läufigkeit bleibt bewusst als eigener Chip in der HUND-Welt.)
============================================================ */
window.Page_breeder_dashboard = (() => {
let _container = null;
async function init(container) {
_container = container;
_render();
await _load();
}
function refresh() { _load(); }
function onDogChange() {}
function _render() {
_container.innerHTML = `
<div style="max-width:640px;margin:0 auto;padding:var(--space-4)">
<div style="margin-bottom:var(--space-5)">
<h1 style="font-size:var(--text-xl);font-weight:800;margin:0 0 var(--space-1)">
${UI.icon('certificate')} Züchter-Bereich
</h1>
<p style="color:var(--c-text-secondary);font-size:var(--text-sm);margin:0">
Dein Zwinger, deine Würfe, deine Zuchthunde.
</p>
</div>
<div id="bd-content">
<div style="text-align:center;padding:var(--space-8);color:var(--c-text-muted)">Lade…</div>
</div>
</div>
`;
}
async function _load() {
const el = _container.querySelector('#bd-content');
try {
const [status, litters, hunde] = await Promise.all([
API.breeder.status().catch(() => null),
API.litters.myList().catch(() => []),
API.zuchthunde.list().catch(() => []),
]);
el.innerHTML = _renderHub(status, litters || [], hunde || []);
_bindEvents(el);
} catch (e) {
el.innerHTML = `<p class="text-danger">${UI.escape(e.message || 'Fehler beim Laden.')}</p>`;
}
}
function _renderHub(status, litters, hunde) {
const profile = status?.profile;
const isBreeder = status?.rolle === 'breeder' || status?.rolle === 'admin';
if (!isBreeder) {
return `
<div class="card" style="padding:var(--space-5);text-align:center">
<p class="text-sm-secondary" style="margin:0">
Der Züchter-Bereich ist für verifizierte Züchter.
Den Antrag findest du in den <a href="#settings" class="text-primary">Einstellungen</a>.
</p>
</div>`;
}
return `
<!-- Zwinger / Profil -->
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
<div style="display:flex;align-items:center;gap:var(--space-3)">
<div class="flex-1-min">
<div style="font-size:var(--text-xs);font-weight:700;text-transform:uppercase;
letter-spacing:.06em;color:var(--c-text-muted);margin-bottom:var(--space-1)">Mein Zwinger</div>
<div style="font-weight:700">${UI.escape(profile?.zwingername || 'Noch kein Profil angelegt')}</div>
${profile?.rasse_text ? `<div class="text-xs-muted">${UI.escape(profile.rasse_text)}</div>` : ''}
<span class="badge" style="background:#dcfce7;color:#16a34a;margin-top:var(--space-1)">
${UI.icon('check-circle')} Verifizierter Züchter
</span>
</div>
<button class="btn btn-sm btn-secondary" data-bd-nav="breeder-editor">
${UI.icon('pencil-simple')} Profil
</button>
</div>
</div>
<!-- Wurfverwaltung -->
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
<div style="display:flex;align-items:center;gap:var(--space-3)">
<div style="width:44px;height:44px;border-radius:var(--radius-md);background:rgba(16,185,129,.12);
display:flex;align-items:center;justify-content:center;flex-shrink:0">
<svg class="ph-icon" style="width:22px;height:22px;color:#10B981"><use href="/icons/phosphor.svg#notebook"></use></svg>
</div>
<div class="flex-1-min">
<div style="font-weight:700">Wurfverwaltung</div>
<div class="text-xs-muted">${litters.length} ${litters.length === 1 ? 'Wurf' : 'Würfe'} · Welpen, Gewichte, Kaufverträge</div>
</div>
<button class="btn btn-sm btn-secondary" data-bd-nav="litters">Öffnen</button>
</div>
</div>
<!-- Zuchtkartei -->
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
<div style="display:flex;align-items:center;gap:var(--space-3)">
<div style="width:44px;height:44px;border-radius:var(--radius-md);background:rgba(139,92,246,.12);
display:flex;align-items:center;justify-content:center;flex-shrink:0">
<svg class="ph-icon" style="width:22px;height:22px;color:#8B5CF6"><use href="/icons/phosphor.svg#tree-structure"></use></svg>
</div>
<div class="flex-1-min">
<div style="font-weight:700">Zuchtkartei</div>
<div class="text-xs-muted">${hunde.length} ${hunde.length === 1 ? 'Zuchthund' : 'Zuchthunde'} · Stammbaum, Genetik, Titel</div>
</div>
<button class="btn btn-sm btn-secondary" data-bd-nav="zuchthunde">Öffnen</button>
</div>
</div>
<!-- Läufigkeit & Trächtigkeit -->
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
<div style="display:flex;align-items:center;gap:var(--space-3)">
<div style="width:44px;height:44px;border-radius:var(--radius-md);background:rgba(236,72,153,.12);
display:flex;align-items:center;justify-content:center;flex-shrink:0">
<svg class="ph-icon" style="width:22px;height:22px;color:#EC4899"><use href="/icons/phosphor.svg#thermometer"></use></svg>
</div>
<div class="flex-1-min">
<div style="font-weight:700">Läufigkeit &amp; Trächtigkeit</div>
<div class="text-xs-muted">Zyklen, Progesterontests, Deckdaten, Meilensteine</div>
</div>
<button class="btn btn-sm btn-secondary" data-bd-nav="laeufi">Öffnen</button>
</div>
</div>
`;
}
function _bindEvents(el) {
el.querySelectorAll('[data-bd-nav]').forEach(btn => {
btn.addEventListener('click', () => App.navigate(btn.dataset.bdNav));
});
}
return { init, refresh, onDogChange };
})();