/** * LeaderboardUI — renders the live leaderboard and user chip. */ import { Auth } from '../auth/Auth.js'; import { Leaderboard } from '../auth/Leaderboard.js'; export class LeaderboardUI { constructor() { this._interval = null; } $(id) { return document.getElementById(id); } startAutoRefresh() { if (this._interval) clearInterval(this._interval); this._interval = setInterval(() => { Leaderboard.bumpPeers(); this.render(); }, 12000); } refreshUserChip() { const u = Auth.current(); if (u) { this.$('userName').textContent = u.name || u.email.split('@')[0]; this.$('userAvatar').textContent = (u.name || u.email).slice(0, 1).toUpperCase(); this.$('signOutBtn').style.display = ''; // Sync persisted star count to header this.$('t-stars').textContent = (u.stars || 0).toLocaleString(); } else { this.$('userName').textContent = 'Guest'; this.$('userAvatar').textContent = 'G'; this.$('signOutBtn').style.display = 'none'; this.$('t-stars').textContent = '0'; } } render() { const u = Auth.current(); const rows = Leaderboard.combinedRanks(u); const top = rows.slice(0, 8); const meRow = rows.find(r => r.me); if (meRow && !top.find(r => r.me)) top.push(meRow); const html = top.map(r => { const rankCls = r.rank <= 3 ? ` r${r.rank}` : ''; const meCls = r.me ? ' me' : ''; const rankIcon = r.rank <= 3 ? ['🥇', '🥈', '🥉'][r.rank - 1] : r.rank; return `