Sprint 11: Freunde & Chat + Phosphor-Icon-Vollmigration
- Freundschaften (pending/accepted), Nutzersuche, Anfragen per Push - Direktnachrichten mit Polling, iMessage-Stil, Deep-Links aus Push - Alle Seiten (map, places, diary, health, dog-profile, sitting, knigge, forum, wiki, walks) vollständig auf Phosphor-Icons migriert - Wikidata-Rassen-Scraper (~833 neue Rassen, lokal gespiegelte Fotos) - TheDogAPI lokal gespiegelt (169 Rassen + Fotos) - Quiz-Result-Cards horizontal (korrekte Bildproportionen) - SW by-v89
This commit is contained in:
parent
96bd57f0ad
commit
097295c628
44 changed files with 9980 additions and 300 deletions
|
|
@ -47,7 +47,7 @@ window.Page_dog_profile = (() => {
|
|||
async function _render() {
|
||||
if (!_appState.user) {
|
||||
_container.innerHTML = UI.emptyState({
|
||||
icon : '🐕',
|
||||
icon : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#dog"></use></svg>',
|
||||
title : 'Anmelden erforderlich',
|
||||
text : 'Melde dich an, um ein Hundeprofil anzulegen.',
|
||||
action: `<button class="btn btn-primary" id="profile-goto-login">Anmelden</button>`,
|
||||
|
|
@ -85,13 +85,13 @@ window.Page_dog_profile = (() => {
|
|||
: `<div style="width:120px;height:120px;border-radius:50%;
|
||||
background:var(--c-surface-2);display:flex;
|
||||
align-items:center;justify-content:center;
|
||||
font-size:3.5rem;border:3px solid var(--c-border)">🐕</div>`}
|
||||
font-size:3.5rem;border:3px solid var(--c-border)">${UI.icon('dog')}</div>`}
|
||||
<label style="position:absolute;bottom:4px;right:4px;
|
||||
background:var(--c-primary);color:#fff;border-radius:50%;
|
||||
width:30px;height:30px;display:flex;align-items:center;
|
||||
justify-content:center;cursor:pointer;font-size:14px"
|
||||
title="Foto ändern">
|
||||
📷
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#camera"></use></svg>
|
||||
<input type="file" id="dp-photo-input" accept="image/*"
|
||||
style="display:none">
|
||||
</label>
|
||||
|
|
@ -110,7 +110,7 @@ window.Page_dog_profile = (() => {
|
|||
${geburtstag ? `
|
||||
<div class="card" style="padding:var(--space-3)">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
margin-bottom:2px">🎂 Geburtstag</div>
|
||||
margin-bottom:2px"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-dots"></use></svg> Geburtstag</div>
|
||||
<div style="font-weight:500;font-size:var(--text-sm)">${geburtstag}</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
|
||||
${_calcAlter(dog.geburtstag)}
|
||||
|
|
@ -120,7 +120,7 @@ window.Page_dog_profile = (() => {
|
|||
${dog.geschlecht ? `
|
||||
<div class="card" style="padding:var(--space-3)">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
margin-bottom:2px">${dog.geschlecht === 'm' ? '♂' : '♀'} Geschlecht</div>
|
||||
margin-bottom:2px">${dog.geschlecht === 'm' ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-male"></use></svg>' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-female"></use></svg>'} Geschlecht</div>
|
||||
<div style="font-weight:500;font-size:var(--text-sm)">
|
||||
${dog.geschlecht === 'm' ? 'Rüde' : 'Hündin'}
|
||||
</div>
|
||||
|
|
@ -129,14 +129,14 @@ window.Page_dog_profile = (() => {
|
|||
${dog.gewicht_kg ? `
|
||||
<div class="card" style="padding:var(--space-3)">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
margin-bottom:2px">⚖️ Gewicht</div>
|
||||
margin-bottom:2px"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg> Gewicht</div>
|
||||
<div style="font-weight:500;font-size:var(--text-sm)">${dog.gewicht_kg} kg</div>
|
||||
</div>
|
||||
` : ''}
|
||||
${dog.chip_nr ? `
|
||||
<div class="card" style="padding:var(--space-3)">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
margin-bottom:2px">💾 Chip-Nr.</div>
|
||||
margin-bottom:2px"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#tag"></use></svg> Chip-Nr.</div>
|
||||
<div style="font-size:var(--text-xs);font-weight:500;
|
||||
word-break:break-all">${_esc(dog.chip_nr)}</div>
|
||||
</div>
|
||||
|
|
@ -151,6 +151,34 @@ window.Page_dog_profile = (() => {
|
|||
</div>
|
||||
` : ''}
|
||||
|
||||
${dog.is_public ? `
|
||||
<div style="background:var(--c-primary-subtle);border:1px solid var(--c-primary-light);
|
||||
border-radius:var(--radius-md);padding:var(--space-4);
|
||||
margin-bottom:var(--space-5);text-align:left">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
margin-bottom:var(--space-2);font-weight:var(--weight-medium)">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#tag"></use></svg> NFC-Link
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:var(--space-2);
|
||||
flex-wrap:wrap">
|
||||
<code id="dp-nfc-link"
|
||||
style="flex:1;font-size:var(--text-sm);background:var(--c-surface);
|
||||
border:1px solid var(--c-border);border-radius:var(--radius-sm);
|
||||
padding:var(--space-2) var(--space-3);color:var(--c-text);
|
||||
word-break:break-all">banyaro.app/hund/${dog.id}</code>
|
||||
<button class="btn btn-secondary btn-sm" id="dp-copy-link-btn"
|
||||
style="flex-shrink:0;padding:var(--space-2) var(--space-3);
|
||||
font-size:var(--text-sm);min-height:36px">
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clipboard-text"></use></svg> Kopieren
|
||||
</button>
|
||||
</div>
|
||||
<p style="margin:var(--space-2) 0 0;font-size:var(--text-xs);
|
||||
color:var(--c-text-muted)">
|
||||
Dieser Link kann auf ein NFC-Tag gebrannt werden
|
||||
</p>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
|
||||
<button class="btn btn-primary w-full" id="dp-edit-btn">
|
||||
Profil bearbeiten
|
||||
|
|
@ -182,6 +210,26 @@ window.Page_dog_profile = (() => {
|
|||
UI.toast.error(err.message || 'Fehler beim Hochladen.');
|
||||
}
|
||||
});
|
||||
// NFC-Link kopieren
|
||||
document.getElementById('dp-copy-link-btn')?.addEventListener('click', async () => {
|
||||
const url = `https://banyaro.app/hund/${dog.id}`;
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
UI.toast.success('Link kopiert!');
|
||||
} catch {
|
||||
// Fallback für ältere Browser
|
||||
const el = document.getElementById('dp-nfc-link');
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(el);
|
||||
const sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
document.execCommand('copy');
|
||||
sel.removeAllRanges();
|
||||
UI.toast.success('Link kopiert!');
|
||||
}
|
||||
});
|
||||
|
||||
// Edit- und Add-Klicks laufen über Event-Delegation in init() — keine direkten Listener nötig.
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +240,7 @@ window.Page_dog_profile = (() => {
|
|||
_container.innerHTML = `
|
||||
<div style="padding:var(--space-4) 0 var(--space-2)">
|
||||
<div style="text-align:center;margin-bottom:var(--space-5)">
|
||||
<div style="font-size:3rem;margin-bottom:var(--space-2)">🐕</div>
|
||||
<div style="font-size:3rem;margin-bottom:var(--space-2)">${UI.icon('dog')}</div>
|
||||
<h2 style="font-size:var(--text-xl);font-weight:700;margin:0 0 var(--space-2)">
|
||||
Hund anlegen
|
||||
</h2>
|
||||
|
|
@ -215,7 +263,7 @@ window.Page_dog_profile = (() => {
|
|||
body: _formHTML(null, true),
|
||||
footer: `
|
||||
<button type="button" class="btn btn-secondary flex-1" id="dp-form-cancel">Abbrechen</button>
|
||||
<button type="submit" form="dp-form" class="btn btn-primary flex-1">🐕 Hund anlegen</button>
|
||||
<button type="submit" form="dp-form" class="btn btn-primary flex-1">${UI.icon('dog')} Hund anlegen</button>
|
||||
`,
|
||||
});
|
||||
_bindForm(null, true);
|
||||
|
|
@ -317,7 +365,7 @@ window.Page_dog_profile = (() => {
|
|||
background:var(--c-surface-2);border:2px solid var(--c-border);
|
||||
display:${dog?.foto_url ? 'block' : 'none'}">
|
||||
<label class="btn btn-secondary btn-sm" style="cursor:pointer;margin:0">
|
||||
📷 Foto auswählen
|
||||
<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#camera"></use></svg> Foto auswählen
|
||||
<input type="file" name="foto" accept="image/*" style="display:none"
|
||||
id="dp-form-foto">
|
||||
</label>
|
||||
|
|
@ -329,7 +377,7 @@ window.Page_dog_profile = (() => {
|
|||
${dog ? `<button type="button" class="btn btn-secondary flex-1"
|
||||
id="dp-form-cancel">Abbrechen</button>` : ''}
|
||||
<button type="submit" class="btn btn-primary flex-1">
|
||||
${dog ? 'Speichern' : '🐕 Hund anlegen'}
|
||||
${dog ? 'Speichern' : `${UI.icon('dog')} Hund anlegen`}
|
||||
</button>
|
||||
</div>` : ''}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue