Züchter-Editor: Wurfnamen sichtbar, 'undefined Medien' gefixt, Mitgliedschaften & Zertifikate
Rene: 'Züchter sollten mehr Einfluss haben — Wurfnamen (B-Wurf), Mitglied- schaften und Zertifikate fürs Profil.' - Wurfnamen: Infrastruktur existierte komplett (wurf_rang/wurf_name in DB, Backend, Wurfverwaltungs-Formular) — war nur im Editor und auf der öffentlichen Seite unsichtbar. Editor-Karten zeigen jetzt 'B-Wurf · Name' (Feldname-Bug geburtsdatum→geburt_datum), öffentliche Wurf-Karten bekommen den Rang/Namen als Badge, Hinweis im Editor verlinkt zur Vergabe. - 'undefined Medien': my-editor lieferte kein foto_count (+photos fürs Profil-Grid) — ergänzt. - NEU Mitgliedschaften & Zertifikate: entity_type 'certificate' im Foto- System (Ownership wie breeder), Editor-Sektion mit Upload (Bezeichnung als Caption) + Löschen, öffentliche Profilseite zeigt eigene Sektion mit Logos/Urkunden (klickbar, lazy). Public-Endpoint liefert result.zertifikate. Tests: my-editor inkl. Wurfname/foto_count, Zertifikat-Roundtrip bis zur öffentlichen Seite. Suite: 61 passed.
This commit is contained in:
parent
dfffd07a96
commit
5f01abc590
10 changed files with 186 additions and 28 deletions
|
|
@ -138,6 +138,34 @@ window.Page_breeder_editor = (() => {
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Mitgliedschaften & Zertifikate -->
|
||||
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
|
||||
<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-2)">
|
||||
Mitgliedschaften & Zertifikate
|
||||
</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-bottom:var(--space-2)">
|
||||
Vereins-Logos, VDH-Mitgliedschaft, Urkunden — werden auf deiner öffentlichen
|
||||
Profilseite in einer eigenen Sektion gezeigt.
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-2);margin:var(--space-3) 0">
|
||||
${(p.certificates || []).map(c => `
|
||||
<div style="position:relative;border:1px solid var(--c-border);border-radius:var(--radius-md);overflow:hidden;background:var(--c-surface-2)">
|
||||
<img src="${UI.escape(c.thumbnail_url || c.url)}" style="width:100%;aspect-ratio:1;object-fit:contain;padding:6px;box-sizing:border-box">
|
||||
<div style="font-size:10px;text-align:center;padding:2px 4px 5px;color:var(--c-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${UI.escape(c.caption || '—')}</div>
|
||||
<button class="be-cert-del" data-id="${c.id}"
|
||||
style="position:absolute;top:4px;right:4px;background:rgba(0,0,0,.6);
|
||||
border:none;border-radius:50%;width:24px;height:24px;cursor:pointer;
|
||||
color:#fff;font-size:14px;display:flex;align-items:center;justify-content:center">×</button>
|
||||
</div>`).join('')}
|
||||
</div>
|
||||
<label class="btn btn-secondary btn-sm" style="cursor:pointer;display:inline-flex;align-items:center;gap:6px">
|
||||
<svg class="ph-icon" style="width:16px;height:16px"><use href="/icons/phosphor.svg#plus"></use></svg>
|
||||
Logo / Urkunde hinzufügen
|
||||
<input type="file" id="be-cert-input" accept="image/*" class="hidden">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Würfe — Schnellupload -->
|
||||
${litters.length ? `
|
||||
<div class="card" style="padding:var(--space-4);margin-bottom:var(--space-3)">
|
||||
|
|
@ -148,6 +176,10 @@ window.Page_breeder_editor = (() => {
|
|||
<div class="flex-col-gap-3">
|
||||
${litters.map(l => _renderLitterCard(l)).join('')}
|
||||
</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-top:var(--space-2)">
|
||||
${UI.icon('info')} Wurf-Rang (A-, B-Wurf …) und Wurfnamen vergibst du in der
|
||||
<a href="#litters" class="text-primary">Wurfverwaltung</a>.
|
||||
</div>
|
||||
</div>` : ''}
|
||||
|
||||
</div>
|
||||
|
|
@ -179,12 +211,14 @@ window.Page_breeder_editor = (() => {
|
|||
}
|
||||
|
||||
function _renderLitterCard(l) {
|
||||
const label = l.geburtsdatum
|
||||
? `Wurf vom ${new Date(l.geburtsdatum).toLocaleDateString('de-DE')}`
|
||||
: `Wurf #${l.id}`;
|
||||
// Wurf-Rang/-Name (aus der Wurfverwaltung) zuerst, dann Datum, dann #id
|
||||
const name = [l.wurf_rang ? `${l.wurf_rang}-Wurf` : null, l.wurf_name]
|
||||
.filter(Boolean).join(' · ');
|
||||
const label = name
|
||||
|| (l.geburt_datum ? `Wurf vom ${new Date(l.geburt_datum).toLocaleDateString('de-DE')}` : `Wurf #${l.id}`);
|
||||
const info = [
|
||||
l.welpen_gesamt ? `${l.welpen_gesamt} Welpen` : null,
|
||||
`${l.foto_count} Medien`,
|
||||
`${l.foto_count ?? 0} Medien`,
|
||||
].filter(Boolean).join(' · ');
|
||||
return `
|
||||
<div style="border:1px solid var(--c-border);border-radius:var(--radius-md);padding:var(--space-3)">
|
||||
|
|
@ -287,6 +321,36 @@ window.Page_breeder_editor = (() => {
|
|||
});
|
||||
|
||||
// Wurf-Upload
|
||||
// Zertifikat/Mitgliedschaft hochladen — Bezeichnung wird als Caption gespeichert
|
||||
el.querySelector('#be-cert-input')?.addEventListener('change', async e => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
const caption = (window.prompt('Bezeichnung (z. B. „VDH-Mitglied", „Club für Britische Hütehunde"):') || '').trim();
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
fd.append('entity_type', 'certificate');
|
||||
fd.append('entity_id', String(_data.profile.id));
|
||||
fd.append('visibility', 'public');
|
||||
if (caption) fd.append('caption', caption);
|
||||
try {
|
||||
const ph = await API.breederPhotos.upload(fd);
|
||||
(_data.profile.certificates ||= []).push(ph);
|
||||
UI.toast.success('Zertifikat hinzugefügt — erscheint auf deiner Profilseite.');
|
||||
_render();
|
||||
} catch (err) { UI.toast.error(err.message); }
|
||||
});
|
||||
|
||||
// Zertifikat löschen
|
||||
el.querySelectorAll('.be-cert-del').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
try {
|
||||
await API.breederPhotos.remove(parseInt(btn.dataset.id));
|
||||
_data.profile.certificates = (_data.profile.certificates || []).filter(c => String(c.id) !== btn.dataset.id);
|
||||
_render();
|
||||
} catch (err) { UI.toast.error(err.message); }
|
||||
});
|
||||
});
|
||||
|
||||
el.querySelectorAll('.be-litter-input').forEach(input => {
|
||||
input.addEventListener('change', async e => {
|
||||
const file = e.target.files[0];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue