Feature: Vollständige Züchter-Rolle — Antrag, Würfe, Stammbaum, Genetik

Basis-Features (Schritte 1–11):
- Züchter-Antrag mit Dokument-Upload, Admin-Prüfung, E-Mail-Benachrichtigungen
- Öffentliches Züchter-Profil + Karten-Marker (lila, certificate-Icon)
- Wurfverwaltung: Würfe, Welpen, Gewichtsverlauf, Foto-System
- Wurfbörse (öffentlich) mit Filtersuche nach Rasse/Status
- Läufigkeits-Tracker: Deckdatum + Wurftermin (+63 Tage, nur für Züchter)
- Interessenten-Chat: Kontakt-Button in Wurfbörse und Züchter-Profil
- Sidebar-Einträge: Zuchtkartei + Wurfverwaltung für Züchter/Admin

Stammbaum & Genetik (Schritte 1–8):
- Zuchtkartei: Hunde-Stammdaten mit Vater/Mutter-Verknüpfung
- Stammbaum-Visualisierung: 4 Generationen, horizontales CSS-Grid
- Gesundheitstests (HD, ED, OCD, Augen…) mit farbigen Ergebnis-Badges
- Genetische Tests (MDR1, PRA, DM…): clear/carrier/affected
- Titel & Auszeichnungen (CAC, CACIB, IPO…)
- Probeverpaarung: IK-Berechnung nach Wright + Ampel-Bewertung
- Teilen-Link für öffentliche Hunde-Profile
- Kaufvertrag: druckbares HTML-Dokument pro Welpe

Technisch: 4 neue Route-Dateien, 5 neue Page-Module, 11 neue DB-Tabellen,
icons shield-check + certificate + tree-structure im Sprite — SW by-v465, APP_VER 444
This commit is contained in:
rene 2026-04-28 18:25:21 +02:00
parent 58cb2b4ad3
commit 91340be5a3
24 changed files with 6660 additions and 27 deletions

View file

@ -606,12 +606,90 @@ const API = (() => {
return new Date().toLocaleString('sv').replace(' ', 'T');
}
// ----------------------------------------------------------
// ZÜCHTER
// ----------------------------------------------------------
const breeder = {
status() { return get('/breeder/status'); },
apply(form) { return upload('/breeder/apply', form); },
profile(zwingername) { return get(`/breeder/profil/${encodeURIComponent(zwingername)}`); },
mapMarkers() { return get('/breeder/map'); },
updateProfile(data) { return put('/breeder/profile', data); },
pendingList() { return get('/admin/breeders/pending'); },
documents(userId) { return get(`/admin/breeder/${userId}/documents`); },
documentUrl(userId, docId) { return `/api/admin/breeder/${userId}/document/${docId}`; },
approve(userId) { return post(`/admin/breeder/${userId}/approve`, {}); },
reject(userId, grund) { return post(`/admin/breeder/${userId}/reject`, { grund }); },
};
// ----------------------------------------------------------
// WÜRFE (Züchter-Wurf-Verwaltung)
// ----------------------------------------------------------
const litters = {
// Züchter: eigene Würfe
myList() { return get('/litters/my'); },
create(data) { return post('/litters', data); },
update(id, data) { return put(`/litters/${id}`, data); },
remove(id) { return del(`/litters/${id}`); },
// Welpen
puppies(id) { return get(`/litters/${id}/puppies`); },
addPuppy(id, data) { return post(`/litters/${id}/puppies`, data); },
updatePuppy(id, data) { return put(`/litters/puppies/${id}`, data); },
addWeight(id, data) { return post(`/litters/puppies/${id}/weight`, data); },
// Öffentlich
public(params) { return get('/litters?' + new URLSearchParams(params || {}).toString()); },
detail(id) { return get(`/litters/${id}`); },
};
// ----------------------------------------------------------
// ZÜCHTER-FOTOS
// ----------------------------------------------------------
const breederPhotos = {
upload(form) { return upload('/breeder/photos/upload', form); },
list(entityType, entityId) { return get(`/photos/${entityType}/${entityId}`); },
updateVisibility(id, visibility) { return patch(`/breeder/photos/${id}/visibility`, { visibility }); },
setPrimary(id) { return patch(`/breeder/photos/${id}/primary`, {}); },
updateCaption(id, caption) { return patch(`/breeder/photos/${id}/caption`, { caption }); },
remove(id) { return del(`/breeder/photos/${id}`); },
};
// Öffentliche API
return {
get, post, put, patch, del, upload,
auth, dogs, diary, health, tieraerzte, poison,
places, routes, walks, events, sitting, forum, lost, knigge, weather, push,
friends, chat, webcal, importData, sharing, widget, notifications, services, ratings, sittingAccess, training, notes,
// ----------------------------------------------------------
// ZUCHTKARTEI (Hunde-Stammdaten, Gesundheit, Genetik, Titel)
// ----------------------------------------------------------
const zuchthunde = {
// Hunde
list() { return get('/zuchthunde'); },
get(id) { return get(`/zuchthunde/${id}`); },
create(data) { return post('/zuchthunde', data); },
update(id, data) { return put(`/zuchthunde/${id}`, data); },
remove(id) { return del(`/zuchthunde/${id}`); },
pedigree(id, gen=4) { return get(`/zuchthunde/${id}/pedigree?generations=${gen}`); },
// Gesundheitstests
healthTests(id) { return get(`/zuchthunde/${id}/health-tests`); },
addHealthTest(id, data) { return post(`/zuchthunde/${id}/health-tests`, data); },
updateHealthTest(tid, data) { return put(`/zuchthunde/health-tests/${tid}`, data); },
deleteHealthTest(tid) { return del(`/zuchthunde/health-tests/${tid}`); },
// Gentests
geneticTests(id) { return get(`/zuchthunde/${id}/genetic-tests`); },
addGeneticTest(id, data) { return post(`/zuchthunde/${id}/genetic-tests`, data); },
updateGeneticTest(tid, data) { return put(`/zuchthunde/genetic-tests/${tid}`, data); },
deleteGeneticTest(tid) { return del(`/zuchthunde/genetic-tests/${tid}`); },
// Titel
titles(id) { return get(`/zuchthunde/${id}/titles`); },
addTitle(id, data) { return post(`/zuchthunde/${id}/titles`, data); },
updateTitle(tid, data) { return put(`/zuchthunde/titles/${tid}`, data); },
deleteTitle(tid) { return del(`/zuchthunde/titles/${tid}`); },
// Probeverpaarung
trialMating(vaterId, mutterId) { return post('/zuchthunde/trial-mating', { vater_id: vaterId, mutter_id: mutterId }); },
};
breeder, litters, breederPhotos, zuchthunde,
subscribeToPush, getLocation, clientNow,
APIError,
};