Feature: HUND-Geburtstag-Hint für Nicht-aktiven Hund

Wenn ein anderer Hund (nicht der angezeigte) Geburtstag hat:
- Cake-Icon (Phosphor) animiert bounce in der Info-Karte unten
- "[Name] hat heute/morgen Geburtstag!" + Pfeil-Button
- Klick → wechselt direkt zum Geburtstagshund + zeigt Birthday-Banner
Kein Tab-Indicator (nur HUND-Welt). SW by-v1027, APP_VER 1027
This commit is contained in:
rene 2026-05-16 11:51:06 +02:00
parent d8b75fbcab
commit 1328e2c4e3
4 changed files with 55 additions and 3 deletions

View file

@ -1360,6 +1360,9 @@ window.Worlds = (() => {
const bday = bdayDog ? _birthdayState(bdayDog.geburtstag) : null;
const bdayYear = bdayDog?.geburtstag ? new Date().getFullYear() - parseInt(bdayDog.geburtstag.slice(0, 4)) : null;
// Merken ob ein anderer Hund Geburtstag hat (für Info-Karte unten)
const otherBdayDog = (bdayDog && bdayDog.id !== dog.id) ? bdayDog : null;
const [streakRes, diaryRes] = await Promise.allSettled([
_cachedGet(`streak_${dog.id}`, `/streak/${dog.id}`),
_cachedGet(`diary_${dog.id}`, `/dogs/${dog.id}/diary?limit=1`),
@ -1417,6 +1420,22 @@ window.Worlds = (() => {
</div>
<div style="justify-self:end;display:flex;align-items:center">${otherAvatarsHtml}</div>
</div>
${otherBdayDog ? `
<div style="margin-top:8px;padding-top:8px;border-top:1px solid rgba(255,255,255,0.12);
display:flex;align-items:center;gap:8px;cursor:pointer"
id="wh-other-bday-hint">
<span style="animation:by-bday-bounce 1.2s ease-in-out infinite;display:inline-flex">
<svg class="ph-icon" style="width:1.2rem;height:1.2rem;color:#f59e0b" aria-hidden="true">
<use href="/icons/phosphor.svg#cake"></use>
</svg>
</span>
<span style="font-size:var(--text-xs);color:rgba(255,255,255,0.75);font-weight:600">
${_esc(otherBdayDog.name)} hat ${_birthdayState(otherBdayDog.geburtstag) === 'today' ? 'heute' : 'morgen'} Geburtstag!
</span>
<svg class="ph-icon" style="width:.9rem;height:.9rem;color:rgba(196,132,58,0.8);margin-left:auto" aria-hidden="true">
<use href="/icons/phosphor.svg#arrow-circle-right"></use>
</svg>
</div>` : ''}
</div>
${bday ? `
<style>
@ -1523,6 +1542,19 @@ window.Worlds = (() => {
if (!isNaN(idx) && idx !== _dogIdx) { _dogIdx = idx; _renderHund(); }
});
});
// Geburtstag-Hinweis → zum Geburtstagshund wechseln
if (otherBdayDog) {
if (!document.getElementById('by-bday-anim-style')) {
const s = document.createElement('style');
s.id = 'by-bday-anim-style';
s.textContent = '@keyframes by-bday-bounce{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-5px) scale(1.3)}}';
document.head.appendChild(s);
}
el.querySelector('#wh-other-bday-hint')?.addEventListener('click', () => {
const idx = _dogs.indexOf(otherBdayDog);
if (idx >= 0) { _dogIdx = idx; _renderHund(); }
});
}
// Geburtstags-Banner → KI
el.querySelector('#wh-bday-banner')?.addEventListener('click', () => _openBdayKI(dog, bday));
@ -1717,6 +1749,26 @@ window.Worlds = (() => {
`).join('');
}
function _updateBdayTabIndicator(bdayDog) {
if (bdayDog && !document.getElementById('by-bday-tab-style')) {
const s = document.createElement('style');
s.id = 'by-bday-tab-style';
s.textContent = '@keyframes by-bday-bounce{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-5px) scale(1.25)}}' +
'.wlabel-bday-ic{display:inline-block;animation:by-bday-bounce 1.2s ease-in-out infinite;margin-left:3px;font-size:.85em}';
document.head.appendChild(s);
}
const hundTab = document.querySelectorAll('#world-labels .wlabel')[1];
if (!hundTab) return;
hundTab.querySelector('.wlabel-bday-ic')?.remove();
if (bdayDog) {
const ic = document.createElement('span');
ic.className = 'wlabel-bday-ic';
ic.textContent = '🎂';
ic.title = `${bdayDog.name} hat ${_birthdayState(bdayDog.geburtstag) === 'today' ? 'heute' : 'morgen'} Geburtstag!`;
hundTab.appendChild(ic);
}
}
function _fmtDate(d) {
if (!d) return '';
try { return new Date(d).toLocaleDateString('de-DE', { day:'numeric', month:'short' }); }