diff --git a/frontend/profile.html b/frontend/profile.html index 9516506..0dc8fe1 100644 --- a/frontend/profile.html +++ b/frontend/profile.html @@ -1981,7 +1981,42 @@ loadFrames(); loadBookmarks(); + /* ── Рейтинг (leaderboard) ── */ + const _lbEsc = s => String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&','<':'<','>':'>','"':'"',"'":''' }[c])); + let _lbPeriod = 'week'; + function setLbPeriod(p, btn) { + _lbPeriod = p; + document.querySelectorAll('.lb-tab').forEach(t => t.classList.remove('active')); + if (btn) btn.classList.add('active'); + loadLeaderboard(); + } + window.setLbPeriod = setLbPeriod; + async function loadLeaderboard() { + const section = document.getElementById('lb-section'); + const list = document.getElementById('lb-list'); + if (!section || !list) return; + try { + const data = await LS.api('/api/gamification/leaderboard?period=' + encodeURIComponent(_lbPeriod)); + if (!data || !data.length) { section.style.display = 'none'; return; } + list.innerHTML = data.map((u, i) => { + const rank = i + 1; + const medal = rank === 1 ? '#FFD700' : rank === 2 ? '#C0C0C0' : rank === 3 ? '#CD7F32' : 'transparent'; + const meClass = u.is_me ? ' lb-row-me' : ''; + return ` +
+
${rank}
+
${u.avatar ? `` : _lbEsc((u.name || '?')[0])}
+
${_lbEsc(u.name || 'Ученик')}
+
${u.sort_xp || u.xp || 0} XP
+
`; + }).join(''); + section.style.display = ''; + if (window.lucide) lucide.createIcons(); + } catch { section.style.display = 'none'; } + } + loadProfile(); + loadLeaderboard(); if (window.lucide) lucide.createIcons(); /* ── Настройки (prefs tab) ── */