feat(profile): рейтинг (leaderboard) перенесён в таб «Достижения»

Карточка рейтинга с табами Неделя/Всё время, /api/gamification/leaderboard,
самодостаточный JS (свой esc). Рейтинг убран с дашборда ранее.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-31 11:53:48 +03:00
parent edfa799d9c
commit 3ffe4ff560
+35
View File
@@ -1981,7 +1981,42 @@
loadFrames();
loadBookmarks();
/* ── Рейтинг (leaderboard) ── */
const _lbEsc = s => String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[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 `
<div class="lb-row${meClass}">
<div class="lb-rank" style="color:${medal !== 'transparent' ? medal : 'var(--text-3)'}">${rank}</div>
<div class="lb-avatar">${u.avatar ? `<img src="${_lbEsc(u.avatar)}">` : _lbEsc((u.name || '?')[0])}</div>
<div class="lb-name">${_lbEsc(u.name || 'Ученик')}</div>
<div class="lb-xp">${u.sort_xp || u.xp || 0} XP</div>
</div>`;
}).join('');
section.style.display = '';
if (window.lucide) lucide.createIcons();
} catch { section.style.display = 'none'; }
}
loadProfile();
loadLeaderboard();
if (window.lucide) lucide.createIcons();
/* ── Настройки (prefs tab) ── */