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:
parent
58cb2b4ad3
commit
91340be5a3
24 changed files with 6660 additions and 27 deletions
|
|
@ -1011,6 +1011,14 @@ window.Page_health = (() => {
|
|||
if (e.datum) rows.push(['Datum', UI.time.format(e.datum + 'T00:00:00')]);
|
||||
if (e.typ === 'laeufigkeit' && e.wert) rows.push(['Dauer', `${e.wert} Tage`]);
|
||||
if (e.naechstes) rows.push([e.typ === 'laeufigkeit' ? 'Nächste erwartet' : 'Nächstes', UI.time.format(e.naechstes + 'T00:00:00')]);
|
||||
if (e.typ === 'laeufigkeit' && e.deckdatum) rows.push(['Deckdatum', UI.time.format(e.deckdatum + 'T00:00:00')]);
|
||||
if (e.typ === 'laeufigkeit' && e.wurftermin) {
|
||||
const wurfDate = new Date(e.wurftermin + 'T00:00:00');
|
||||
const today = new Date(); today.setHours(0,0,0,0);
|
||||
const diffDays = Math.round((wurfDate - today) / 86400000);
|
||||
const zukunft = diffDays > 0 ? ` <span style="color:var(--c-primary);font-weight:600">in ${diffDays} Tagen</span>` : '';
|
||||
rows.push(['Wurftermin', UI.time.format(e.wurftermin + 'T00:00:00') + zukunft]);
|
||||
}
|
||||
if (e.tierarzt_id) {
|
||||
const praxis = _praxen.find(p => p.id === e.tierarzt_id);
|
||||
if (praxis) {
|
||||
|
|
@ -1478,6 +1486,27 @@ window.Page_health = (() => {
|
|||
<input class="form-control" type="date" name="naechstes"
|
||||
value="${entry?.naechstes || ''}" id="laeufi-naechstes">
|
||||
</div>
|
||||
${['breeder', 'admin'].includes(_appState.user?.rolle) ? `
|
||||
<div class="form-group" id="laeufi-zuechter-fields" style="margin-top:var(--space-4);
|
||||
padding-top:var(--space-4);border-top:1px solid var(--c-border)">
|
||||
<div style="font-size:var(--text-xs);font-weight:600;color:var(--c-text-secondary);
|
||||
text-transform:uppercase;letter-spacing:0.05em;margin-bottom:var(--space-3)">
|
||||
Zucht (optional)
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Deckdatum</label>
|
||||
<input class="form-control" type="date" name="deckdatum"
|
||||
value="${entry?.deckdatum || ''}" id="laeufi-deckdatum">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Wurftermin (63 Tage nach Deckung)</label>
|
||||
<input class="form-control" type="date" name="wurftermin"
|
||||
value="${entry?.wurftermin || ''}" id="laeufi-wurftermin" readonly
|
||||
style="background:var(--c-surface-2)">
|
||||
</div>
|
||||
</div>
|
||||
</div>` : ''}
|
||||
<script>
|
||||
(function() {
|
||||
const datum = document.querySelector('[name="datum"]');
|
||||
|
|
@ -1495,6 +1524,16 @@ window.Page_health = (() => {
|
|||
datum?.addEventListener('change', updateNext);
|
||||
interval?.addEventListener('change', updateNext);
|
||||
if (!naechstes?.value) updateNext();
|
||||
|
||||
const deckdatum = document.getElementById('laeufi-deckdatum');
|
||||
const wurftermin = document.getElementById('laeufi-wurftermin');
|
||||
deckdatum?.addEventListener('change', e => {
|
||||
const deckDate = new Date(e.target.value);
|
||||
if (!isNaN(deckDate)) {
|
||||
deckDate.setDate(deckDate.getDate() + 63);
|
||||
wurftermin.value = deckDate.toISOString().split('T')[0];
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
`;
|
||||
|
|
@ -1524,6 +1563,8 @@ window.Page_health = (() => {
|
|||
}
|
||||
if (typ === 'laeufigkeit') {
|
||||
p.bezeichnung = p.bezeichnung || 'Läufigkeit';
|
||||
p.deckdatum = fd.deckdatum || null;
|
||||
p.wurftermin = fd.wurftermin || null;
|
||||
}
|
||||
if (fd.kosten) p.kosten = parseFloat(fd.kosten.toString().replace(',', '.'));
|
||||
if (fd.tierarzt_id) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue