@@ -129,10 +151,74 @@ window.Page_breeder_dashboard = (() => {
`;
}
+ // KI-Toggle-Zeile (aus settings.js umgezogen — Zustand kommt aus _appState.user)
+ function _kiToggleRow(key, label) {
+ const user = _appState?.user || {};
+ const active = user[key] !== 0;
+ return `
+
+ ${UI.escape(label)}
+
+
+
+
`;
+ }
+
function _bindEvents(el) {
el.querySelectorAll('[data-bd-nav]').forEach(btn => {
btn.addEventListener('click', () => App.navigate(btn.dataset.bdNav));
});
+
+ // Admin ohne Profil: Züchterprofil anlegen
+ el.querySelector('#bd-admin-create')?.addEventListener('click', async e => {
+ const btn = e.currentTarget;
+ btn.disabled = true;
+ btn.textContent = 'Wird angelegt…';
+ try {
+ await API.breeder.adminCreateProfile();
+ UI.toast.success('Admin-Züchterprofil angelegt.');
+ await _load();
+ } catch (err) {
+ UI.toast.error(err.message || 'Fehler beim Anlegen.');
+ btn.disabled = false;
+ btn.innerHTML = `${UI.icon('plus')} Profil anlegen`;
+ }
+ });
+
+ // KI-Toggles — optimistisches Update mit Revert bei Fehler
+ el.querySelectorAll('.bd-ki-toggle').forEach(btn => {
+ btn.addEventListener('click', async () => {
+ const key = btn.dataset.key;
+ const active = btn.dataset.active === '1';
+ const newVal = active ? 0 : 1;
+ const thumb = btn.querySelector('.by-toggle-thumb');
+
+ btn.dataset.active = newVal ? '1' : '0';
+ btn.style.background = newVal ? 'var(--c-primary)' : 'var(--c-border)';
+ if (thumb) thumb.style.left = newVal ? '22px' : '2px';
+
+ try {
+ await API.patch('/profile', { [key]: newVal });
+ if (_appState?.user) _appState.user[key] = newVal;
+ UI.toast.success(newVal ? 'KI-Feature aktiviert.' : 'KI-Feature deaktiviert.');
+ } catch (err) {
+ btn.dataset.active = active ? '1' : '0';
+ btn.style.background = active ? 'var(--c-primary)' : 'var(--c-border)';
+ if (thumb) thumb.style.left = active ? '22px' : '2px';
+ UI.toast.error(err?.message || 'Einstellung konnte nicht gespeichert werden.');
+ }
+ });
+ });
}
return { init, refresh, onDogChange };
diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js
index f4bc01d..6a36d26 100644
--- a/backend/static/js/pages/settings.js
+++ b/backend/static/js/pages/settings.js
@@ -1664,29 +1664,6 @@ window.Page_settings = (() => {
}
- // ----------------------------------------------------------
- // KI-Toggle-Zeile (Hilfsfunktion für Züchter-Card)
- // ----------------------------------------------------------
- function _kiToggleRow(key, label, user) {
- const active = user[key] !== 0;
- return `
-
- ${UI.escape(label)}
-
-
-
-
`;
- }
// ----------------------------------------------------------
// ZÜCHTER-CARD — asynchron laden und in Slot rendern
@@ -1714,41 +1691,10 @@ window.Page_settings = (() => {
let actionBlock = '';
if (rolle === 'breeder' || rolle === 'admin') {
- statusBadge = `
- ${UI.icon('check-circle')} ${rolle === 'admin' ? 'Admin — alle Züchter-Features verfügbar' : 'Verifizierter Züchter'}
- `;
- actionBlock = `
-
- ${profile?.zwingername ? `
Zwinger: ${UI.escape(profile.zwingername)}
` : ''}
- ${profile?.rasse_text ? `
Rasse: ${UI.escape(profile.rasse_text)}
` : ''}
-
- ${rolle === 'breeder' && profile ? `
-
- ${UI.icon('pencil-simple')} Profil bearbeiten
- ` : ''}
- ${rolle === 'admin' && !profile ? `
-
- ${UI.icon('plus')} Admin-Züchterprofil anlegen
- ` : ''}
- ${rolle === 'admin' && profile ? `
-
- ${UI.icon('pencil-simple')} Profil bearbeiten
- ` : ''}
- ${profile ? `
-
-
- KI-Züchter-Assistenz
-
- ${_kiToggleRow('ki_zucht_wurfankuendigung', 'Wurfankündigungen schreiben', _appState.user || {})}
- ${_kiToggleRow('ki_zucht_genetik', 'Genetik-Erklärung für Käufer', _appState.user || {})}
- ${_kiToggleRow('ki_zucht_paarung', 'Paarungsanalyse', _appState.user || {})}
- ${_kiToggleRow('ki_zucht_beschreibung', 'Hunde-Beschreibungen', _appState.user || {})}
- ${_kiToggleRow('ki_zucht_jahresbericht', 'Jahresauswertung', _appState.user || {})}
-
- ${UI.icon('info')} Der Tierschutz-Check läuft immer automatisch und ist nicht abschaltbar.
-
-
` : ''}`;
+ // Verifizierte Züchter/Admins: alles Inhaltliche (Profil, KI-Assistenz,
+ // Würfe, Zuchtkartei) lebt im Züchter-Bereich — hier nur der Verweis.
+ slot.innerHTML = '';
+ return;
} else if (breeder_status === 'pending') {
statusBadge = `
${UI.icon('hourglass')} Antrag wird geprüft
@@ -1784,221 +1730,7 @@ window.Page_settings = (() => {
// Button-Handler binden
slot.querySelector('#breeder-reapply-btn')?.addEventListener('click', () => _showUpgradeModal('breeder'));
- slot.querySelector('#breeder-edit-profile-btn')?.addEventListener('click', () =>
- _openBreederEditModal(profile)
- );
- slot.querySelector('#breeder-admin-create-btn')?.addEventListener('click', async (e) => {
- const btn = e.currentTarget;
- btn.disabled = true;
- btn.textContent = 'Wird angelegt…';
- try {
- await API.breeder.adminCreateProfile();
- UI.toast.success('Admin-Züchterprofil angelegt. Bitte Seite neu laden.');
- _loadBreederCard();
- } catch (err) {
- UI.toast.error(err.message || 'Fehler beim Anlegen.');
- btn.disabled = false;
- btn.innerHTML = `${UI.icon('plus')} Admin-Züchterprofil anlegen`;
- }
- });
-
- // KI-Toggle-Handler
- slot.querySelectorAll('.ki-toggle-btn').forEach(btn => {
- btn.addEventListener('click', async () => {
- const key = btn.dataset.key;
- const active = btn.dataset.active === '1';
- const newVal = active ? 0 : 1;
-
- // Optimistisches UI-Update
- btn.dataset.active = newVal ? '1' : '0';
- btn.style.background = newVal ? 'var(--c-primary)' : 'var(--c-border)';
- const thumb = btn.querySelector('.by-toggle-thumb');
- if (thumb) thumb.style.left = newVal ? '22px' : '2px';
-
- try {
- const updated = await API.patch('/profile', { [key]: newVal });
- if (_appState?.user) _appState.user[key] = newVal;
- UI.toast.success(newVal ? 'KI-Feature aktiviert.' : 'KI-Feature deaktiviert.');
- } catch (err) {
- // Revert
- btn.dataset.active = active ? '1' : '0';
- btn.style.background = active ? 'var(--c-primary)' : 'var(--c-border)';
- if (thumb) thumb.style.left = active ? '22px' : '2px';
- UI.toast.error(err?.message || 'Einstellung konnte nicht gespeichert werden.');
- }
- });
- });
- }
-
- // ----------------------------------------------------------
- // ZÜCHTER-PROFIL BEARBEITEN MODAL
- // ----------------------------------------------------------
- function _openBreederEditModal(profile) {
- const inputStyle = `width:100%;box-sizing:border-box;padding:var(--space-2) var(--space-3);
- border:1.5px solid var(--c-border);border-radius:var(--radius-md);
- font-size:var(--text-sm);font-family:inherit;
- background:var(--c-surface);color:var(--c-text)`;
-
- UI.modal.open({
- title: `${UI.icon('pencil-simple')} Züchter-Profil bearbeiten`,
- body: `
- `,
- footer: `
-
- Speichern
- Abbrechen
-
`,
- });
-
- document.getElementById('breeder-edit-form')?.addEventListener('submit', async e => {
- e.preventDefault();
- const btn = document.getElementById('breeder-edit-submit');
- await UI.asyncButton(btn, async () => {
- const form = e.target;
- const data = {
- zwingername: form.zwingername.value.trim() || undefined,
- rasse_text: form.rasse_text.value.trim() || undefined,
- verein: form.verein.value.trim() || undefined,
- stadt: form.stadt.value.trim() || undefined,
- vdh_mitglied: form.vdh_mitglied.checked ? 1 : 0,
- website: form.website.value.trim() || undefined,
- beschreibung: form.beschreibung.value.trim() || undefined,
- };
- await API.breeder.updateProfile(data);
- UI.modal.close?.();
- UI.toast.success('Profil aktualisiert.');
- _loadBreederCard();
- });
- });
- }
-
- // ----------------------------------------------------------
- // ZÜCHTER-ANTRAG MODAL
- // ----------------------------------------------------------
- function _openBreederApplyModal() {
- const inputStyle = `width:100%;box-sizing:border-box;padding:var(--space-2) var(--space-3);
- border:1.5px solid var(--c-border);border-radius:var(--radius-md);
- font-size:var(--text-sm);font-family:inherit;
- background:var(--c-surface);color:var(--c-text)`;
-
- UI.modal.open({
- title: `${UI.icon('certificate')} Züchter-Antrag stellen`,
- body: `
-
-
-
- Zwingername *
-
-
-
-
-
- Rasse *
-
-
-
-
-
- Zuchtverein *
-
-
-
-
-
- Stadt *
-
-
-
-
-
-
- VDH-Mitglied
-
-
-
-
- Website (optional)
-
-
-
-
-
- Beschreibung (optional)
-
-
-
-
-
- Dokument hochladen *
-
-
-
- Zuchtbuch-Eintrag, Vereinsmitgliedschaft o.ä. (PDF, JPG, PNG, WebP)
-
-
-
- `,
- footer: `
-
- Antrag einreichen
- Abbrechen
-
- `,
- });
document.getElementById('breeder-apply-form')?.addEventListener('submit', async e => {
e.preventDefault();
diff --git a/backend/static/landing.html b/backend/static/landing.html
index fc24dda..891c8f2 100644
--- a/backend/static/landing.html
+++ b/backend/static/landing.html
@@ -4,7 +4,7 @@
-
+
Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz
diff --git a/backend/static/sw.js b/backend/static/sw.js
index e299457..fd4c73b 100644
--- a/backend/static/sw.js
+++ b/backend/static/sw.js
@@ -4,7 +4,7 @@
============================================================ */
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
-const VER = '1268';
+const VER = '1269';
const CACHE_VERSION = `by-v${VER}`;
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten