From 5c611166f3afa49c17b6d184f97088e33b4499f2 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Sun, 31 May 2026 11:18:46 +0300 Subject: [PATCH] =?UTF-8?q?fix(dashboard):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20loadPetHero=20(Reference?= =?UTF-8?q?Error=20=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B4=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Функция loadPetHero вызывалась, но её тело не попало в коммит 667054f (Edit не применился). Восстановлено: рендер питомца через PetSprite + загрузка /api/pet, как и задумано. Co-Authored-By: Claude Opus 4.8 --- frontend/dashboard.html | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/frontend/dashboard.html b/frontend/dashboard.html index b38d109..ea3ec54 100644 --- a/frontend/dashboard.html +++ b/frontend/dashboard.html @@ -3261,6 +3261,41 @@ document.getElementById('hc-lab-meta').textContent = 'Освой: ' + lab.goal; } + /* ══ HERO: Pet (synced with /pet module via /api/pet + PetSprite) ═ */ + async function loadPetHero() { + const card = document.getElementById('hc-pet'); + if (!card) return; + let d; + try { d = await LS.api('/api/pet'); } + catch { card.style.display = 'none'; return; } // фича питомца выключена + if (!d) { card.style.display = 'none'; return; } + + // Sprite — единый рендер из pet-sprite.js (как на /pet) + const art = document.getElementById('hc-pet-art'); + if (art && window.PetSprite) { + art.innerHTML = PetSprite.render(d.petLevel || 1, d.mood || 'neutral', d.accessories || [], d.petColor || 'purple', d.streakCurrent || 0); + } + document.getElementById('hc-pet-name').textContent = d.petName || 'Квантик'; + document.getElementById('hc-pet-lvl').textContent = d.petLevel || 1; + + // XP до следующего уровня питомца + const cur = d.xpForCurrLevel || 0; + const next = d.xpForNextLevel; // null = макс + const have = Math.max(0, (d.xp || 0) - cur); + const need = next != null ? Math.max(1, next - cur) : have; + const pct = next != null ? Math.min(100, Math.round(have / need * 100)) : 100; + document.getElementById('hc-pet-xp').textContent = have; + document.getElementById('hc-pet-xpmax').textContent = next != null ? need : '—'; + document.getElementById('hc-pet-prog').style.width = pct + '%'; + + // Стрик / цель дня / настроение + document.getElementById('hc-pet-streak').textContent = d.streakCurrent || 0; + const quests = d.quests || []; + const doneCnt = quests.filter(q => q.done).length; + document.getElementById('hc-pet-goal').textContent = quests.length ? `${doneCnt}/${quests.length}` : '—'; + document.getElementById('hc-pet-mood').textContent = window.PetSprite ? PetSprite.moodLabel(d.mood) : (d.mood || 'бодр'); + } + /* ══ ACTIVITY: data structure ══════════════════════════════════════ */ let _activityRows = []; // raw history rows let _hmScale = 12; // weeks to show