Spaces:
Running
Running
sigma
Browse files- index.html +47 -156
index.html
CHANGED
|
@@ -188,18 +188,6 @@
|
|
| 188 |
.modal-corner.bl { bottom: -1px; left: -1px; border-width: 0 0 2px 2px; }
|
| 189 |
.modal-corner.br { bottom: -1px; right: -1px; border-width: 0 2px 2px 0; }
|
| 190 |
|
| 191 |
-
.modal-close {
|
| 192 |
-
position: absolute;
|
| 193 |
-
top: 15px; right: 15px;
|
| 194 |
-
background: transparent;
|
| 195 |
-
border: none;
|
| 196 |
-
color: var(--text-dim);
|
| 197 |
-
font-size: 16px;
|
| 198 |
-
cursor: pointer;
|
| 199 |
-
transition: color .2s;
|
| 200 |
-
}
|
| 201 |
-
.modal-close:hover { color: var(--accent2); }
|
| 202 |
-
|
| 203 |
.modal-title {
|
| 204 |
font-family: 'Orbitron', sans-serif;
|
| 205 |
font-size: 18px;
|
|
@@ -269,22 +257,16 @@
|
|
| 269 |
display: none;
|
| 270 |
}
|
| 271 |
|
| 272 |
-
.
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
font-size: 11px;
|
| 276 |
-
color: var(--text-dim);
|
| 277 |
-
}
|
| 278 |
-
.auth-toggle button {
|
| 279 |
background: none; border: none;
|
| 280 |
-
color: var(--
|
|
|
|
| 281 |
cursor: pointer;
|
| 282 |
-
|
| 283 |
-
letter-spacing: 1px;
|
| 284 |
-
text-decoration: underline;
|
| 285 |
-
margin-left: 5px;
|
| 286 |
}
|
| 287 |
-
.
|
| 288 |
|
| 289 |
/* ββ ANON BANNER ββ */
|
| 290 |
.anon-banner {
|
|
@@ -486,6 +468,7 @@
|
|
| 486 |
.data-table tbody tr:hover { background: rgba(0,212,255,0.04); }
|
| 487 |
.data-table tbody tr:last-child td { border-bottom: none; }
|
| 488 |
|
|
|
|
| 489 |
.data-table tbody tr.own-row {
|
| 490 |
background: rgba(0,212,255,0.06);
|
| 491 |
border-left: 3px solid var(--accent);
|
|
@@ -636,32 +619,18 @@
|
|
| 636 |
<div class="modal-corner bl"></div>
|
| 637 |
<div class="modal-corner br"></div>
|
| 638 |
<button class="modal-close" onclick="closeLoginModal()">β</button>
|
| 639 |
-
|
| 640 |
-
<div class="modal-
|
| 641 |
-
<div class="modal-sub" id="modal-sub-text">ACCESS FULL COMBAT ANALYTICS</div>
|
| 642 |
-
|
| 643 |
-
<div class="form-group" id="group-username" style="display:none;">
|
| 644 |
-
<label>Operator Handle (Username)</label>
|
| 645 |
-
<input type="text" id="login-username" placeholder="ShadowSniper99" />
|
| 646 |
-
</div>
|
| 647 |
-
|
| 648 |
<div class="form-group">
|
| 649 |
<label>Email Address</label>
|
| 650 |
<input type="email" id="login-email" placeholder="operator@warzone.com" />
|
| 651 |
</div>
|
| 652 |
-
|
| 653 |
<div class="form-group">
|
| 654 |
<label>Password</label>
|
| 655 |
<input type="password" id="login-password" placeholder="β’β’β’β’β’β’β’β’" />
|
| 656 |
</div>
|
| 657 |
-
|
| 658 |
-
<button class="modal-submit" id="login-submit" onclick="submitAuth()">AUTHENTICATE</button>
|
| 659 |
<div class="modal-error" id="login-error"></div>
|
| 660 |
-
|
| 661 |
-
<div class="auth-toggle">
|
| 662 |
-
<span id="auth-toggle-text">Don't have clearance?</span>
|
| 663 |
-
<button id="auth-toggle-btn" onclick="toggleAuthMode()">REGISTER NEW OPERATOR</button>
|
| 664 |
-
</div>
|
| 665 |
</div>
|
| 666 |
</div>
|
| 667 |
|
|
@@ -830,8 +799,7 @@ const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZ
|
|
| 830 |
|
| 831 |
let players = [];
|
| 832 |
let charts = {};
|
| 833 |
-
let authUser = null;
|
| 834 |
-
let isLoginMode = true;
|
| 835 |
|
| 836 |
// ββ AUTH STATE βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 837 |
function isLoggedIn() { return authUser !== null; }
|
|
@@ -863,156 +831,77 @@ function applyAuthState() {
|
|
| 863 |
if (loggedIn) renderMyStats();
|
| 864 |
}
|
| 865 |
|
| 866 |
-
// ββ LOGIN
|
| 867 |
function openLoginModal() {
|
| 868 |
document.getElementById('login-modal').classList.add('active');
|
| 869 |
-
setTimeout(() =>
|
| 870 |
-
if(isLoginMode) document.getElementById('login-email').focus();
|
| 871 |
-
else document.getElementById('login-username').focus();
|
| 872 |
-
}, 300);
|
| 873 |
}
|
| 874 |
-
|
| 875 |
function closeLoginModal() {
|
| 876 |
document.getElementById('login-modal').classList.remove('active');
|
| 877 |
}
|
| 878 |
-
|
| 879 |
document.getElementById('login-modal').addEventListener('click', e => {
|
| 880 |
if (e.target === e.currentTarget) closeLoginModal();
|
| 881 |
});
|
| 882 |
document.addEventListener('keydown', e => {
|
| 883 |
if (e.key === 'Escape') closeLoginModal();
|
| 884 |
-
if (e.key === 'Enter' && document.getElementById('login-modal').classList.contains('active'))
|
| 885 |
});
|
| 886 |
|
| 887 |
-
function
|
| 888 |
-
isLoginMode = !isLoginMode;
|
| 889 |
-
const title = document.getElementById('modal-title-text');
|
| 890 |
-
const sub = document.getElementById('modal-sub-text');
|
| 891 |
-
const userGroup = document.getElementById('group-username');
|
| 892 |
-
const submitBtn = document.getElementById('login-submit');
|
| 893 |
-
const toggleText = document.getElementById('auth-toggle-text');
|
| 894 |
-
const toggleBtn = document.getElementById('auth-toggle-btn');
|
| 895 |
-
const errEl = document.getElementById('login-error');
|
| 896 |
-
|
| 897 |
-
errEl.style.display = 'none';
|
| 898 |
-
|
| 899 |
-
if (isLoginMode) {
|
| 900 |
-
title.textContent = 'SIGN IN';
|
| 901 |
-
sub.textContent = 'ACCESS FULL COMBAT ANALYTICS';
|
| 902 |
-
userGroup.style.display = 'none';
|
| 903 |
-
submitBtn.textContent = 'AUTHENTICATE';
|
| 904 |
-
toggleText.textContent = "Don't have clearance?";
|
| 905 |
-
toggleBtn.textContent = "REGISTER NEW OPERATOR";
|
| 906 |
-
} else {
|
| 907 |
-
title.textContent = 'ENLIST';
|
| 908 |
-
sub.textContent = 'CREATE YOUR OPERATOR PROFILE';
|
| 909 |
-
userGroup.style.display = 'block';
|
| 910 |
-
submitBtn.textContent = 'INITIALIZE ACCOUNT';
|
| 911 |
-
toggleText.textContent = "Already enlisted?";
|
| 912 |
-
toggleBtn.textContent = "SIGN IN HERE";
|
| 913 |
-
}
|
| 914 |
-
}
|
| 915 |
-
|
| 916 |
-
async function submitAuth() {
|
| 917 |
const email = document.getElementById('login-email').value.trim();
|
| 918 |
const password = document.getElementById('login-password').value;
|
| 919 |
-
const username = document.getElementById('login-username').value.trim();
|
| 920 |
const errEl = document.getElementById('login-error');
|
| 921 |
const btn = document.getElementById('login-submit');
|
| 922 |
|
| 923 |
errEl.style.display = 'none';
|
| 924 |
-
|
| 925 |
if (!email || !password) {
|
| 926 |
errEl.textContent = 'β EMAIL AND PASSWORD REQUIRED';
|
| 927 |
errEl.style.display = 'block';
|
| 928 |
return;
|
| 929 |
}
|
| 930 |
-
if (!isLoginMode && !username) {
|
| 931 |
-
errEl.textContent = 'β OPERATOR HANDLE REQUIRED';
|
| 932 |
-
errEl.style.display = 'block';
|
| 933 |
-
return;
|
| 934 |
-
}
|
| 935 |
|
| 936 |
btn.disabled = true;
|
| 937 |
-
btn.textContent = '
|
| 938 |
|
| 939 |
try {
|
| 940 |
-
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
res = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {
|
| 944 |
-
method: 'POST',
|
| 945 |
-
headers: { 'apikey': SUPABASE_KEY, 'Content-Type': 'application/json' },
|
| 946 |
-
body: JSON.stringify({ email, password })
|
| 947 |
-
});
|
| 948 |
-
data = await res.json();
|
| 949 |
-
if (!res.ok) throw new Error(data.error_description || data.msg || 'Login failed');
|
| 950 |
-
|
| 951 |
-
const userId = data.user?.id;
|
| 952 |
-
let fetchedUsername = data.user?.email;
|
| 953 |
-
try {
|
| 954 |
-
const statsRes = await fetch(
|
| 955 |
-
`${SUPABASE_URL}/rest/v1/player_stats?id=eq.${userId}&select=username`,
|
| 956 |
-
{ headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${data.access_token}` } }
|
| 957 |
-
);
|
| 958 |
-
const statsData = await statsRes.json();
|
| 959 |
-
if (statsData?.[0]?.username) fetchedUsername = statsData[0].username;
|
| 960 |
-
} catch(_) {}
|
| 961 |
-
|
| 962 |
-
authUser = { id: userId, email: data.user?.email, username: fetchedUsername, token: data.access_token };
|
| 963 |
-
|
| 964 |
-
} else {
|
| 965 |
-
res = await fetch(`${SUPABASE_URL}/auth/v1/signup`, {
|
| 966 |
method: 'POST',
|
| 967 |
-
headers: {
|
|
|
|
|
|
|
|
|
|
| 968 |
body: JSON.stringify({ email, password })
|
| 969 |
-
});
|
| 970 |
-
data = await res.json();
|
| 971 |
-
if (!res.ok) throw new Error(data.error_description || data.msg || 'Registration failed');
|
| 972 |
-
|
| 973 |
-
const userId = data.user?.id;
|
| 974 |
-
const token = data.session?.access_token || SUPABASE_KEY;
|
| 975 |
-
|
| 976 |
-
const createRes = await fetch(`${SUPABASE_URL}/rest/v1/player_stats`, {
|
| 977 |
-
method: 'POST',
|
| 978 |
-
headers: {
|
| 979 |
-
'apikey': SUPABASE_KEY,
|
| 980 |
-
'Authorization': `Bearer ${token}`,
|
| 981 |
-
'Content-Type': 'application/json',
|
| 982 |
-
'Prefer': 'return=minimal'
|
| 983 |
-
},
|
| 984 |
-
body: JSON.stringify({
|
| 985 |
-
id: userId,
|
| 986 |
-
username: username,
|
| 987 |
-
rank_points: 1000,
|
| 988 |
-
kills: 0,
|
| 989 |
-
deaths: 0,
|
| 990 |
-
gold: 0,
|
| 991 |
-
headshots: 0,
|
| 992 |
-
level: 1,
|
| 993 |
-
equipped_weapon: 'Pistol',
|
| 994 |
-
equipped_armor: 'None'
|
| 995 |
-
})
|
| 996 |
-
});
|
| 997 |
-
|
| 998 |
-
if (!createRes.ok) {
|
| 999 |
-
console.warn("Failed to create player_stats row. Check RLS policies.");
|
| 1000 |
}
|
|
|
|
| 1001 |
|
| 1002 |
-
|
| 1003 |
-
|
| 1004 |
-
|
| 1005 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1006 |
closeLoginModal();
|
| 1007 |
applyAuthState();
|
| 1008 |
-
|
| 1009 |
|
| 1010 |
} catch (e) {
|
| 1011 |
errEl.textContent = `β ${e.message.toUpperCase()}`;
|
| 1012 |
errEl.style.display = 'block';
|
| 1013 |
} finally {
|
| 1014 |
btn.disabled = false;
|
| 1015 |
-
btn.textContent =
|
| 1016 |
}
|
| 1017 |
}
|
| 1018 |
|
|
@@ -1022,7 +911,6 @@ function doLogout() {
|
|
| 1022 |
renderCharts();
|
| 1023 |
document.getElementById('login-email').value = '';
|
| 1024 |
document.getElementById('login-password').value = '';
|
| 1025 |
-
document.getElementById('login-username').value = '';
|
| 1026 |
}
|
| 1027 |
|
| 1028 |
// ββ FETCH DATA βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -1137,7 +1025,7 @@ function destroyAll() { Object.values(charts).forEach(c => c.destroy()); charts
|
|
| 1137 |
|
| 1138 |
function renderCharts() {
|
| 1139 |
destroyAll();
|
| 1140 |
-
if (!isLoggedIn()) return;
|
| 1141 |
|
| 1142 |
Chart.defaults.color = '#4a7a9b';
|
| 1143 |
Chart.defaults.font.family = "'Share Tech Mono', monospace";
|
|
@@ -1222,6 +1110,7 @@ function renderTable() {
|
|
| 1222 |
const loggedIn = isLoggedIn();
|
| 1223 |
const head = document.getElementById('leaderboard-head');
|
| 1224 |
|
|
|
|
| 1225 |
if (loggedIn) {
|
| 1226 |
head.innerHTML = `<tr>
|
| 1227 |
<th>#</th><th>PLAYER</th><th>TIER</th><th>RANK PTS</th>
|
|
@@ -1242,6 +1131,7 @@ function renderTable() {
|
|
| 1242 |
if (weaponFilter) data = data.filter(p => p.equipped_weapon === weaponFilter);
|
| 1243 |
data.sort((a,b) => sortKey==='kd' ? b.kd-a.kd : (b[sortKey]||0)-(a[sortKey]||0));
|
| 1244 |
|
|
|
|
| 1245 |
if (!loggedIn) data = data.slice(0, 10);
|
| 1246 |
|
| 1247 |
const tbody = document.getElementById('leaderboard-body');
|
|
@@ -1287,6 +1177,7 @@ function renderTable() {
|
|
| 1287 |
tbody.appendChild(tr);
|
| 1288 |
});
|
| 1289 |
|
|
|
|
| 1290 |
if (!loggedIn && players.length > 10) {
|
| 1291 |
const tr = document.createElement('tr');
|
| 1292 |
tr.innerHTML = `<td colspan="6" style="text-align:center;color:var(--text-dim);padding:16px;border-top:1px solid var(--border)">
|
|
|
|
| 188 |
.modal-corner.bl { bottom: -1px; left: -1px; border-width: 0 0 2px 2px; }
|
| 189 |
.modal-corner.br { bottom: -1px; right: -1px; border-width: 0 2px 2px 0; }
|
| 190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
.modal-title {
|
| 192 |
font-family: 'Orbitron', sans-serif;
|
| 193 |
font-size: 18px;
|
|
|
|
| 257 |
display: none;
|
| 258 |
}
|
| 259 |
|
| 260 |
+
.modal-close {
|
| 261 |
+
position: absolute;
|
| 262 |
+
top: 14px; right: 14px;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
background: none; border: none;
|
| 264 |
+
color: var(--text-dim);
|
| 265 |
+
font-size: 18px;
|
| 266 |
cursor: pointer;
|
| 267 |
+
transition: color .2s;
|
|
|
|
|
|
|
|
|
|
| 268 |
}
|
| 269 |
+
.modal-close:hover { color: var(--accent2); }
|
| 270 |
|
| 271 |
/* ββ ANON BANNER ββ */
|
| 272 |
.anon-banner {
|
|
|
|
| 468 |
.data-table tbody tr:hover { background: rgba(0,212,255,0.04); }
|
| 469 |
.data-table tbody tr:last-child td { border-bottom: none; }
|
| 470 |
|
| 471 |
+
/* Own player row highlight */
|
| 472 |
.data-table tbody tr.own-row {
|
| 473 |
background: rgba(0,212,255,0.06);
|
| 474 |
border-left: 3px solid var(--accent);
|
|
|
|
| 619 |
<div class="modal-corner bl"></div>
|
| 620 |
<div class="modal-corner br"></div>
|
| 621 |
<button class="modal-close" onclick="closeLoginModal()">β</button>
|
| 622 |
+
<div class="modal-title">SIGN IN</div>
|
| 623 |
+
<div class="modal-sub">ACCESS FULL COMBAT ANALYTICS</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 624 |
<div class="form-group">
|
| 625 |
<label>Email Address</label>
|
| 626 |
<input type="email" id="login-email" placeholder="operator@warzone.com" />
|
| 627 |
</div>
|
|
|
|
| 628 |
<div class="form-group">
|
| 629 |
<label>Password</label>
|
| 630 |
<input type="password" id="login-password" placeholder="β’β’β’β’β’β’β’β’" />
|
| 631 |
</div>
|
| 632 |
+
<button class="modal-submit" id="login-submit" onclick="doLogin()">AUTHENTICATE</button>
|
|
|
|
| 633 |
<div class="modal-error" id="login-error"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
</div>
|
| 635 |
</div>
|
| 636 |
|
|
|
|
| 799 |
|
| 800 |
let players = [];
|
| 801 |
let charts = {};
|
| 802 |
+
let authUser = null; // { id, email, username, token }
|
|
|
|
| 803 |
|
| 804 |
// ββ AUTH STATE βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 805 |
function isLoggedIn() { return authUser !== null; }
|
|
|
|
| 831 |
if (loggedIn) renderMyStats();
|
| 832 |
}
|
| 833 |
|
| 834 |
+
// ββ LOGIN MODAL ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 835 |
function openLoginModal() {
|
| 836 |
document.getElementById('login-modal').classList.add('active');
|
| 837 |
+
setTimeout(() => document.getElementById('login-email').focus(), 300);
|
|
|
|
|
|
|
|
|
|
| 838 |
}
|
|
|
|
| 839 |
function closeLoginModal() {
|
| 840 |
document.getElementById('login-modal').classList.remove('active');
|
| 841 |
}
|
|
|
|
| 842 |
document.getElementById('login-modal').addEventListener('click', e => {
|
| 843 |
if (e.target === e.currentTarget) closeLoginModal();
|
| 844 |
});
|
| 845 |
document.addEventListener('keydown', e => {
|
| 846 |
if (e.key === 'Escape') closeLoginModal();
|
| 847 |
+
if (e.key === 'Enter' && document.getElementById('login-modal').classList.contains('active')) doLogin();
|
| 848 |
});
|
| 849 |
|
| 850 |
+
async function doLogin() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 851 |
const email = document.getElementById('login-email').value.trim();
|
| 852 |
const password = document.getElementById('login-password').value;
|
|
|
|
| 853 |
const errEl = document.getElementById('login-error');
|
| 854 |
const btn = document.getElementById('login-submit');
|
| 855 |
|
| 856 |
errEl.style.display = 'none';
|
|
|
|
| 857 |
if (!email || !password) {
|
| 858 |
errEl.textContent = 'β EMAIL AND PASSWORD REQUIRED';
|
| 859 |
errEl.style.display = 'block';
|
| 860 |
return;
|
| 861 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 862 |
|
| 863 |
btn.disabled = true;
|
| 864 |
+
btn.textContent = 'AUTHENTICATING...';
|
| 865 |
|
| 866 |
try {
|
| 867 |
+
const res = await fetch(
|
| 868 |
+
`${SUPABASE_URL}/auth/v1/token?grant_type=password`,
|
| 869 |
+
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 870 |
method: 'POST',
|
| 871 |
+
headers: {
|
| 872 |
+
'apikey': SUPABASE_KEY,
|
| 873 |
+
'Content-Type': 'application/json'
|
| 874 |
+
},
|
| 875 |
body: JSON.stringify({ email, password })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 876 |
}
|
| 877 |
+
);
|
| 878 |
|
| 879 |
+
const data = await res.json();
|
| 880 |
+
if (!res.ok) throw new Error(data.error_description || data.msg || 'Login failed');
|
| 881 |
+
|
| 882 |
+
// Fetch username from player_stats
|
| 883 |
+
const userId = data.user?.id;
|
| 884 |
+
let username = data.user?.email;
|
| 885 |
+
try {
|
| 886 |
+
const statsRes = await fetch(
|
| 887 |
+
`${SUPABASE_URL}/rest/v1/player_stats?id=eq.${userId}&select=username`,
|
| 888 |
+
{ headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${data.access_token}` } }
|
| 889 |
+
);
|
| 890 |
+
const statsData = await statsRes.json();
|
| 891 |
+
if (statsData?.[0]?.username) username = statsData[0].username;
|
| 892 |
+
} catch(_) {}
|
| 893 |
+
|
| 894 |
+
authUser = { id: userId, email: data.user?.email, username, token: data.access_token };
|
| 895 |
closeLoginModal();
|
| 896 |
applyAuthState();
|
| 897 |
+
renderCharts();
|
| 898 |
|
| 899 |
} catch (e) {
|
| 900 |
errEl.textContent = `β ${e.message.toUpperCase()}`;
|
| 901 |
errEl.style.display = 'block';
|
| 902 |
} finally {
|
| 903 |
btn.disabled = false;
|
| 904 |
+
btn.textContent = 'AUTHENTICATE';
|
| 905 |
}
|
| 906 |
}
|
| 907 |
|
|
|
|
| 911 |
renderCharts();
|
| 912 |
document.getElementById('login-email').value = '';
|
| 913 |
document.getElementById('login-password').value = '';
|
|
|
|
| 914 |
}
|
| 915 |
|
| 916 |
// ββ FETCH DATA βββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 1025 |
|
| 1026 |
function renderCharts() {
|
| 1027 |
destroyAll();
|
| 1028 |
+
if (!isLoggedIn()) return; // charts only render when logged in
|
| 1029 |
|
| 1030 |
Chart.defaults.color = '#4a7a9b';
|
| 1031 |
Chart.defaults.font.family = "'Share Tech Mono', monospace";
|
|
|
|
| 1110 |
const loggedIn = isLoggedIn();
|
| 1111 |
const head = document.getElementById('leaderboard-head');
|
| 1112 |
|
| 1113 |
+
// Anon: limited columns. Logged in: full columns
|
| 1114 |
if (loggedIn) {
|
| 1115 |
head.innerHTML = `<tr>
|
| 1116 |
<th>#</th><th>PLAYER</th><th>TIER</th><th>RANK PTS</th>
|
|
|
|
| 1131 |
if (weaponFilter) data = data.filter(p => p.equipped_weapon === weaponFilter);
|
| 1132 |
data.sort((a,b) => sortKey==='kd' ? b.kd-a.kd : (b[sortKey]||0)-(a[sortKey]||0));
|
| 1133 |
|
| 1134 |
+
// Anonymous: top 10 only
|
| 1135 |
if (!loggedIn) data = data.slice(0, 10);
|
| 1136 |
|
| 1137 |
const tbody = document.getElementById('leaderboard-body');
|
|
|
|
| 1177 |
tbody.appendChild(tr);
|
| 1178 |
});
|
| 1179 |
|
| 1180 |
+
// If anon: add teaser row
|
| 1181 |
if (!loggedIn && players.length > 10) {
|
| 1182 |
const tr = document.createElement('tr');
|
| 1183 |
tr.innerHTML = `<td colspan="6" style="text-align:center;color:var(--text-dim);padding:16px;border-top:1px solid var(--border)">
|