import { useEffect, useMemo, useRef, useState } from 'react'
import Tree from '../Tree/Tree'
import FallingLeaves from '../Tree/FallingLeaves'
const numberFormat = new Intl.NumberFormat('en-GB')
const dateFormat = new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium',
timeStyle: 'short',
})
const apiEndpoints = {
health: '/health',
uptime: '/api/uptime',
viewers: '/api/viewers',
viewerEvent: '/api/viewers/event',
teams: '/api/tss/leaderboard/teams?limit=100',
teamsHealth: '/api/tss/leaderboard/teams?limit=1',
resolve: (name) => `/api/tss/teams/resolve?name=${encodeURIComponent(name)}`,
detail: (name) => `/api/tss/teams/${encodeURIComponent(name)}`,
history: (name) => `/api/tss/teams/${encodeURIComponent(name)}/history`,
games: (name) => `/api/tss/teams/${encodeURIComponent(name)}/games`,
}
const navItems = [
{ path: '/', label: 'Home' },
{ path: '/teams', label: 'Team leaderboard' },
{ path: '/battle-logs', label: 'Battle Logs' },
{ path: '/viewers', label: 'Viewers' },
]
const analyticsConsentKey = 'tssbot.analyticsConsent'
const analyticsVisitorKey = 'tssbot.analyticsVisitor'
async function fetchJson(path, signal) {
const response = await fetch(path, {
signal,
headers: { Accept: 'application/json' },
})
const body = await response.json().catch(() => null)
if (!response.ok) {
throw new Error(body?.error || `Request failed with ${response.status}`)
}
return body
}
function parseRoute(pathname = window.location.pathname) {
if (pathname === '/') return { page: 'home', teamName: '' }
if (pathname === '/teams') return { page: 'teams', teamName: '' }
if (pathname === '/uptime') return { page: 'uptime', teamName: '' }
if (pathname === '/viewers') return { page: 'viewers', teamName: '' }
if (pathname.startsWith('/teams/')) {
const teamName = decodeURIComponent(pathname.slice('/teams/'.length))
return { page: 'team', teamName }
}
if (pathname === '/battle-logs' || pathname === '/live') return { page: 'battle-logs', teamName: '' }
return { page: 'home', teamName: '' }
}
function teamPath(name) {
return `/teams/${encodeURIComponent(name)}`
}
function formatNumber(value) {
return numberFormat.format(Number(value || 0))
}
function formatDate(timestamp) {
if (!timestamp) return 'Unknown time'
return dateFormat.format(new Date(Number(timestamp) * 1000))
}
function bestTeamName(team) {
return team?.tag_name || team?.short_name || team?.long_name || ''
}
function storedConsent() {
try {
return window.localStorage.getItem(analyticsConsentKey) || ''
} catch {
return ''
}
}
function stableId(storageKey) {
try {
const existing = window.localStorage.getItem(storageKey)
if (existing) return existing
const id =
window.crypto?.randomUUID?.() ||
`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`
window.localStorage.setItem(storageKey, id)
return id
} catch {
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`
}
}
const analyticsSessionId =
window.crypto?.randomUUID?.() ||
`${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`
function browserName() {
const ua = navigator.userAgent
if (ua.includes('Edg/')) return 'Microsoft Edge'
if (ua.includes('OPR/')) return 'Opera'
if (ua.includes('Firefox/')) return 'Firefox'
if (ua.includes('Chrome/') && !ua.includes('Chromium/')) return 'Chrome'
if (ua.includes('Safari/') && ua.includes('Version/')) return 'Safari'
return 'Unknown'
}
function operatingSystem() {
const ua = navigator.userAgent
if (ua.includes('Windows NT')) return 'Windows'
if (ua.includes('Android')) return 'Android'
if (/iPhone|iPad|iPod/.test(ua)) return 'iOS'
if (ua.includes('Mac OS X')) return 'macOS'
if (ua.includes('Linux')) return 'Linux'
return 'Unknown'
}
function deviceType() {
const ua = navigator.userAgent
if (/Mobi|Android|iPhone|iPod/.test(ua)) return 'Mobile'
if (/iPad|Tablet/.test(ua)) return 'Tablet'
return 'Desktop'
}
function routeLabel(route) {
if (route.page === 'team' && route.teamName) return `Team: ${route.teamName}`
if (route.page === 'teams') return 'Team leaderboard'
if (route.page === 'battle-logs') return 'Battle Logs'
if (route.page === 'uptime') return 'Uptime'
if (route.page === 'viewers') return 'viewers'
return 'Home'
}
async function fetchRecentTssGames(teams, signal) {
const teamNames = teams.map(bestTeamName).filter(Boolean).slice(0, 12)
if (!teamNames.length) {
return { matches: [] }
}
const responses = await Promise.allSettled(
teamNames.map((name) => fetchJson(apiEndpoints.games(name), signal).then((data) => ({ name, data }))),
)
const bySession = new Map()
responses.forEach((result) => {
if (result.status !== 'fulfilled') return
const { name, data } = result.value
;(data.games || []).forEach((game) => {
if (!game.session_id) return
const existing = bySession.get(game.session_id)
const currentTimestamp = Number(game.timestamp || 0)
if (existing && Number(existing.timestamp || 0) >= currentTimestamp) return
bySession.set(game.session_id, {
...game,
team_name: data.tag_name || name,
long_name: data.long_name || '',
})
})
})
return {
matches: Array.from(bySession.values())
.sort((a, b) => Number(b.timestamp || 0) - Number(a.timestamp || 0))
.slice(0, 50),
}
}
function Stat({ label, value }) {
return (
)
}
function App() {
const [route, setRoute] = useState(() => parseRoute())
const [leaderboard, setLeaderboard] = useState({ status: 'idle', data: null, error: null })
const [live, setLive] = useState({ status: 'idle', data: null, error: null })
const [uptime, setUptime] = useState({ status: 'idle', checks: [], history: [], updatedAt: null })
const [viewers, setViewers] = useState({ status: 'idle', data: null, error: null, updatedAt: null })
const [analyticsConsent, setAnalyticsConsent] = useState(() => storedConsent())
const [teamQuery, setTeamQuery] = useState('')
const [searchHint, setSearchHint] = useState({ status: 'idle', name: '' })
const [profile, setProfile] = useState({
teamName: '',
detail: { status: 'idle', data: null, error: null },
history: { status: 'idle', data: null, error: null },
games: { status: 'idle', data: null, error: null },
})
const teams = useMemo(
() => leaderboard.data?.teams || leaderboard.data?.squadrons || [],
[leaderboard.data],
)
const matches = live.data?.matches || []
function navigate(path) {
window.history.pushState({}, '', path)
setRoute(parseRoute(path))
}
useEffect(() => {
const onPopState = () => setRoute(parseRoute())
window.addEventListener('popstate', onPopState)
return () => window.removeEventListener('popstate', onPopState)
}, [])
useEffect(() => {
const title =
route.page === 'team' && route.teamName
? `${route.teamName} | Toothless' TSS Bot`
: route.page === 'teams'
? "Team leaderboard | Toothless' TSS Bot"
: route.page === 'battle-logs'
? "Battle Logs | Toothless' TSS Bot"
: route.page === 'uptime'
? "Uptime | Toothless' TSS Bot"
: route.page === 'viewers'
? "viewers | Toothless' TSS Bot"
: "Toothless' TSS Bot"
document.title = title
}, [route.page, route.teamName])
useEffect(() => {
if (analyticsConsent !== 'analytics') return
const visitorId = stableId(analyticsVisitorKey)
let stopped = false
function sendViewerEvent(eventType) {
if (stopped) return
const body = {
consent: 'analytics',
event_type: eventType,
visitor_id: visitorId,
session_id: analyticsSessionId,
page_path: window.location.pathname,
page_title: routeLabel(route),
referrer: document.referrer,
browser: browserName(),
os: operatingSystem(),
device: deviceType(),
screen: `${window.screen.width}x${window.screen.height}`,
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
metadata: {
color_depth: window.screen.colorDepth,
viewport: `${window.innerWidth}x${window.innerHeight}`,
},
}
fetch(apiEndpoints.viewerEvent, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
keepalive: true,
}).catch(() => {})
}
sendViewerEvent('page_view')
const timer = window.setInterval(() => sendViewerEvent('heartbeat'), 30000)
const onVisibilityChange = () => {
if (document.visibilityState === 'visible') sendViewerEvent('heartbeat')
}
document.addEventListener('visibilitychange', onVisibilityChange)
return () => {
stopped = true
window.clearInterval(timer)
document.removeEventListener('visibilitychange', onVisibilityChange)
}
}, [analyticsConsent, route])
useEffect(() => {
const onKeyDown = (event) => {
if (event.key === 'Escape') {
navigate('/')
}
}
window.addEventListener('keydown', onKeyDown)
return () => window.removeEventListener('keydown', onKeyDown)
}, [])
useEffect(() => {
const query = teamQuery.trim()
if (query.length < 2) {
setSearchHint({ status: 'idle', name: '' })
return
}
const controller = new AbortController()
const timer = window.setTimeout(() => {
setSearchHint({ status: 'loading', name: '' })
fetchJson(apiEndpoints.resolve(query), controller.signal)
.then((data) => {
const name = data.tag_name || data.short_name || data.long_name || query
setSearchHint({ status: 'ready', name })
})
.catch(() => {
if (!controller.signal.aborted) {
setSearchHint({ status: 'error', name: '' })
}
})
}, 350)
return () => {
window.clearTimeout(timer)
controller.abort()
}
}, [teamQuery])
useEffect(() => {
if (!['home', 'teams', 'team', 'battle-logs'].includes(route.page)) return
if (leaderboard.status === 'ready' || leaderboard.status === 'loading') return
const controller = new AbortController()
setLeaderboard({ status: 'loading', data: null, error: null })
fetchJson(apiEndpoints.teams, controller.signal)
.then((data) => setLeaderboard({ status: 'ready', data, error: null }))
.catch((error) => {
if (!controller.signal.aborted) {
setLeaderboard({ status: 'error', data: null, error: error.message })
}
})
return () => controller.abort()
}, [leaderboard.status, route.page])
useEffect(() => {
if (!['home', 'teams', 'team', 'battle-logs'].includes(route.page)) return
const controller = new AbortController()
const timer = window.setInterval(() => {
fetchJson(apiEndpoints.teams, controller.signal)
.then((data) => setLeaderboard({ status: 'ready', data, error: null }))
.catch((error) => {
if (!controller.signal.aborted) {
setLeaderboard((current) => ({ ...current, error: error.message }))
}
})
}, 60000)
return () => {
window.clearInterval(timer)
controller.abort()
}
}, [route.page])
useEffect(() => {
if (!['home', 'battle-logs'].includes(route.page)) return
if (!teams.length) return
const controller = new AbortController()
setLive((current) =>
current.status === 'ready' ? current : { status: 'loading', data: null, error: null },
)
fetchRecentTssGames(teams, controller.signal)
.then((data) => setLive({ status: 'ready', data, error: null }))
.catch((error) => {
if (!controller.signal.aborted) {
setLive({ status: 'error', data: null, error: error.message })
}
})
return () => controller.abort()
}, [route.page, teams])
useEffect(() => {
if (!['home', 'battle-logs'].includes(route.page)) return
if (!teams.length) return
const controller = new AbortController()
const timer = window.setInterval(() => {
fetchRecentTssGames(teams, controller.signal)
.then((data) => setLive({ status: 'ready', data, error: null }))
.catch((error) => {
if (!controller.signal.aborted) {
setLive((current) => ({ ...current, error: error.message }))
}
})
}, 15000)
return () => {
window.clearInterval(timer)
controller.abort()
}
}, [route.page, teams])
useEffect(() => {
if (route.page !== 'team' || !route.teamName) return
const controller = new AbortController()
setProfile({
teamName: route.teamName,
detail: { status: 'loading', data: null, error: null },
history: { status: 'loading', data: null, error: null },
games: { status: 'loading', data: null, error: null },
})
Promise.allSettled([
fetchJson(apiEndpoints.detail(route.teamName), controller.signal),
fetchJson(apiEndpoints.history(route.teamName), controller.signal),
fetchJson(apiEndpoints.games(route.teamName), controller.signal),
]).then(([detailResult, historyResult, gamesResult]) => {
if (controller.signal.aborted) return
setProfile({
teamName: route.teamName,
detail:
detailResult.status === 'fulfilled'
? { status: 'ready', data: detailResult.value, error: null }
: { status: 'error', data: null, error: detailResult.reason.message },
history:
historyResult.status === 'fulfilled'
? { status: 'ready', data: historyResult.value, error: null }
: { status: 'error', data: null, error: historyResult.reason.message },
games:
gamesResult.status === 'fulfilled'
? { status: 'ready', data: gamesResult.value, error: null }
: { status: 'error', data: null, error: gamesResult.reason.message },
})
})
return () => controller.abort()
}, [route.page, route.teamName])
useEffect(() => {
if (route.page !== 'uptime') return
const controller = new AbortController()
async function loadUptime() {
setUptime((current) => ({
status: current.status === 'ready' ? 'refreshing' : 'loading',
checks: current.checks,
history: current.history,
updatedAt: current.updatedAt,
}))
fetchJson(apiEndpoints.uptime, controller.signal)
.then((data) => {
const latest = data.latest
const checks = latest
? [
{
name: 'Website',
detail: 'App shell and static assets',
ok: latest.website_ok,
label: latest.details?.website?.label || (latest.website_ok ? 'Online' : 'Issue'),
latency: latest.latency_ms,
},
{
name: 'Health endpoint',
detail: apiEndpoints.health,
ok: latest.health_ok,
label: latest.details?.health?.label || (latest.health_ok ? 'Operational' : 'Issue'),
latency: latest.latency_ms,
},
{
name: 'TSS data proxy',
detail: apiEndpoints.teamsHealth,
ok: latest.tss_ok,
label: latest.details?.tss?.label || (latest.tss_ok ? 'Operational' : 'Issue'),
latency: latest.details?.tss?.latency_ms || latest.latency_ms,
},
]
: []
setUptime({
status: 'ready',
checks,
history: (data.history || []).map((sample) => ({
timestamp: new Date(sample.checked_at).getTime(),
onlineChecks: [sample.website_ok, sample.health_ok, sample.tss_ok].filter(Boolean).length,
totalChecks: 3,
ok: sample.ok,
})),
updatedAt: latest ? new Date(latest.checked_at).getTime() : null,
configured: data.configured,
})
})
.catch((error) => {
if (controller.signal.aborted) return
setUptime({
status: 'error',
updatedAt: null,
configured: false,
history: [],
checks: [
{
name: 'Website',
detail: 'App shell and static assets',
ok: true,
label: 'Online',
latency: 0,
},
{
name: 'Health endpoint',
detail: apiEndpoints.health,
ok: false,
label: error.message,
latency: 0,
},
{
name: 'TSS data proxy',
detail: apiEndpoints.teamsHealth,
ok: false,
label: 'Uptime history unavailable',
latency: 0,
},
],
})
})
}
loadUptime()
const timer = window.setInterval(loadUptime, 60000)
return () => {
window.clearInterval(timer)
controller.abort()
}
}, [route.page])
useEffect(() => {
if (route.page !== 'viewers') return
const controller = new AbortController()
function loadViewers() {
setViewers((current) => ({
status: current.status === 'ready' ? 'refreshing' : 'loading',
data: current.data,
error: null,
updatedAt: current.updatedAt,
}))
fetchJson(apiEndpoints.viewers, controller.signal)
.then((data) => {
setViewers({
status: 'ready',
data,
error: null,
updatedAt: Date.now(),
})
})
.catch((error) => {
if (!controller.signal.aborted) {
setViewers((current) => ({ ...current, status: 'error', error: error.message }))
}
})
}
loadViewers()
const timer = window.setInterval(loadViewers, 5000)
return () => {
window.clearInterval(timer)
controller.abort()
}
}, [route.page])
useEffect(() => {
if (route.page !== 'team' || !route.teamName) return
const controller = new AbortController()
const timer = window.setInterval(() => {
Promise.allSettled([
fetchJson(apiEndpoints.detail(route.teamName), controller.signal),
fetchJson(apiEndpoints.history(route.teamName), controller.signal),
fetchJson(apiEndpoints.games(route.teamName), controller.signal),
]).then(([detailResult, historyResult, gamesResult]) => {
if (controller.signal.aborted) return
setProfile((current) => ({
teamName: route.teamName,
detail:
detailResult.status === 'fulfilled'
? { status: 'ready', data: detailResult.value, error: null }
: current.detail,
history:
historyResult.status === 'fulfilled'
? { status: 'ready', data: historyResult.value, error: null }
: current.history,
games:
gamesResult.status === 'fulfilled'
? { status: 'ready', data: gamesResult.value, error: null }
: current.games,
}))
})
}, 60000)
return () => {
window.clearInterval(timer)
controller.abort()
}
}, [route.page, route.teamName])
const topTeamName = bestTeamName(teams[0])
const searchPlaceholder =
searchHint.status === 'ready' ? `Found ${searchHint.name}` : topTeamName || 'Search teams'
async function handleTeamSearch(event) {
event.preventDefault()
const name = teamQuery.trim()
if (!name) return
try {
const resolved = await fetchJson(apiEndpoints.resolve(name))
navigate(teamPath(resolved.tag_name || resolved.short_name || resolved.long_name || name))
} catch {
navigate(teamPath(name))
}
}
function chooseAnalyticsConsent(value) {
try {
window.localStorage.setItem(analyticsConsentKey, value)
} catch {
// Local storage can be blocked; the in-memory choice still controls this session.
}
setAnalyticsConsent(value)
}
const activeNavPath =
route.page === 'team'
? '/teams'
: route.page === 'battle-logs'
? '/battle-logs'
: route.page === 'viewers'
? '/viewers'
: window.location.pathname
return (
navigate('/')} type="button">
Toothless' TSS Bot
{navItems.map((item) => (
navigate(item.path)}
type="button"
>
{item.label}
))}
SRE
{route.page === 'home' ? (
) : null}
{route.page === 'teams' ? (
) : null}
{route.page === 'team' ? (
) : null}
{route.page === 'battle-logs' ? : null}
{route.page === 'uptime' ? : null}
{route.page === 'viewers' ? : null}
)
}
function Footer({ navigate }) {
return (
)
}
function ConsentBanner({ consent, onChoose }) {
if (consent) {
return (
onChoose('')}
type="button"
>
Privacy settings
)
}
return (
Analytics consent
We can track page views, live viewing state, browser, device, screen size,
language, timezone, referrer, and pseudonymous identifiers so the public
viewers page works. Raw IP addresses are not shown publicly.
onChoose('declined')}
type="button"
>
Decline
onChoose('analytics')}
type="button"
>
Allow analytics
)
}
function Landing({ live, matches, navigate }) {
const treeRef = useRef(null)
return (
BorisBot got nothin on THIS
Toothless' TSS Bot
Powered by Spectra. TSS analytics.
navigate('/teams')}
type="button"
>
Team leaderboard
navigate('/battle-logs')}
type="button"
>
Battle Logs
)
}
function RecentGamesSection({ live, matches, navigate }) {
const recentMatches = matches.slice(0, 6)
return (
Recent activity
Latest games
navigate('/battle-logs')}
type="button"
>
View Battle Logs
{recentMatches.map((match) => (
{match.map_name || 'Unknown map'}
{formatDate(match.timestamp)}
{match.result || 'Unknown'}
{match.team_name || 'TSS team'}
{formatNumber(match.player_count)} players
{formatNumber(match.stats?.ground_kills)} ground
{formatNumber(match.stats?.air_kills)} air
{formatNumber(match.stats?.deaths)} deaths
))}
{!recentMatches.length ? (
{live.status === 'loading' ? 'Loading latest games' : live.error || 'No games returned'}
) : null}
)
}
function PixelMountains() {
const canvasRef = useRef(null)
useEffect(() => {
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
const WORLD_W = 1920
const WORLD_H = 900
function interpolate(points, x) {
for (let i = 0; i < points.length - 1; i++) {
const [x0, y0] = points[i]
const [x1, y1] = points[i + 1]
if (x >= x0 && x <= x1) {
const t = (x - x0) / Math.max(1, x1 - x0)
return y0 + (y1 - y0) * t
}
}
return points.at(-1)[1]
}
function drawMountain(points, color, jitter = 0) {
const width = WORLD_W
const height = WORLD_H
ctx.fillStyle = color
for (let x = 0; x < width; x++) {
const wave = jitter
? Math.sin(x * 0.08) * jitter + Math.sin(x * 0.021) * jitter * 1.8
: 0
const y = Math.round(interpolate(points, x) + wave)
ctx.fillRect(x, y, 1, height - y)
}
}
function draw() {
const width = WORLD_W
const height = WORLD_H
canvas.width = WORLD_W
canvas.height = WORLD_H
ctx.imageSmoothingEnabled = false
ctx.clearRect(0, 0, WORLD_W, WORLD_H)
drawMountain(
[
[0, height * 0.82],
[width * 0.12, height * 0.73],
[width * 0.26, height * 0.66],
[width * 0.39, height * 0.76],
[width * 0.55, height * 0.58],
[width * 0.64, height * 0.46],
[width * 0.73, height * 0.62],
[width * 0.86, height * 0.56],
[width, height * 0.64],
],
'#fcfbcf',
1.1,
)
drawMountain(
[
[0, height * 0.86],
[width * 0.15, height * 0.78],
[width * 0.31, height * 0.81],
[width * 0.43, height * 0.69],
[width * 0.52, height * 0.76],
[width * 0.62, height * 0.43],
[width * 0.69, height * 0.31],
[width * 0.78, height * 0.48],
[width, height * 0.5],
],
'#fff2e6',
1.6,
)
drawMountain(
[
[0, height * 0.94],
[width * 0.17, height * 0.9],
[width * 0.32, height * 0.92],
[width * 0.47, height * 0.83],
[width * 0.58, height * 0.89],
[width * 0.66, height * 0.61],
[width * 0.71, height * 0.5],
[width * 0.84, height * 0.7],
[width, height * 0.68],
],
'#fee5cd',
2.1,
)
drawMountain(
[
[0, height * 0.98],
[width * 0.17, height * 0.96],
[width * 0.34, height * 0.99],
[width * 0.48, height * 0.93],
[width * 0.62, height * 0.97],
[width * 0.72, height * 0.88],
[width * 0.86, height * 0.95],
[width, height * 0.93],
],
'#fdca9b',
1.4,
)
}
draw()
}, [])
return
}
function TeamsPage({ leaderboard, navigate, teams }) {
return (
Team leaderboard
{leaderboard.status === 'loading'
? 'Loading leaderboard'
: leaderboard.error || `${teams.length} teams returned`}
{teams.map((team, index) => {
const name = bestTeamName(team)
return (
navigate(teamPath(name))}
type="button"
>
#{index + 1}
{name}
{team.long_name || team.short_name || 'Unresolved'}
{formatNumber(team.player_count)} players
{formatNumber(team.total_battles)} battles
{Number(team.win_rate || 0).toFixed(1)}% WR
{formatNumber(team.points?.total_points || team.total_kills)}
)
})}
{!teams.length ? (
{leaderboard.status === 'loading' ? 'Loading leaderboard' : 'No teams returned'}
) : null}
)
}
function TeamProfilePage({ navigate, profile, requestedTeam, teams }) {
const detail = profile.detail.data
const summary = detail?.team_summary || detail?.squadron_summary
const players = detail?.players || []
const games = profile.games.data?.games || []
const history = profile.history.data?.history || []
const ratingHourly = profile.history.data?.rating_hourly || []
const latestRating = ratingHourly.at(-1)?.rating || summary?.points?.total_points
const leaderboardTeam = teams.find((team) => bestTeamName(team) === requestedTeam)
const displayName = detail?.tag_name || bestTeamName(leaderboardTeam) || requestedTeam
const longName = detail?.long_name || leaderboardTeam?.long_name || ''
return (
navigate('/teams')}
type="button"
>
Back to leaderboard
Team profile
{displayName}
{profile.detail.error || longName || profile.detail.status}
Rating {formatNumber(latestRating)}
Clan {detail?.clan_id || leaderboardTeam?.clan_id || 'n/a'}
{detail?.data_set || 'tss'}
)
}
function RosterTable({ players, status }) {
const sortedPlayers = [...players].sort((a, b) => {
return (b.total_kills || 0) - (a.total_kills || 0) || String(a.nick || '').localeCompare(b.nick || '')
})
return (
Roster
{formatNumber(sortedPlayers.length)} players
{sortedPlayers.map((player) => (
{player.nick || player.uid}
{player.uid} · {formatNumber(player.points || player.sqb_points)} pts
{formatNumber(player.total_battles)} battles
{formatNumber(player.total_kills)} kills
{Number(player.win_rate || 0).toFixed(1)}% WR
{Number(player.kdr || 0).toFixed(1)} KDR
{formatNumber(player.assists)} assists
))}
{!sortedPlayers.length ? (
{status === 'loading' ? 'Loading roster' : 'No roster rows returned'}
) : null}
)
}
function RatingPanel({ history, ratingHourly, status }) {
const recentHistory = history.slice(-8)
const firstRating = ratingHourly[0]?.rating || 0
const latestRating = ratingHourly.at(-1)?.rating || 0
const ratingChange = latestRating - firstRating
return (
History
{ratingHourly.length ? `${formatNumber(ratingHourly.length)} rating snapshots` : status}
= 0 ? '+' : ''}${formatNumber(ratingChange)}`}
/>
{recentHistory.map((item) => (
{item.period}
{formatNumber(item.battles)} battles
{Number(item.win_rate || 0).toFixed(1)}% WR
))}
{!recentHistory.length ? (
{status === 'loading' ? 'Loading history' : 'No history rows returned'}
) : null}
)
}
function BattleResults({ games, status }) {
return (
Battle results
{formatNumber(games.length)} battles returned
{games.map((game) => (
{game.map_name || 'Unknown map'}
{formatDate(game.timestamp)} · {game.session_id}
{game.result || 'Unknown'}
{formatNumber(game.player_count)} players
{formatNumber(game.stats?.ground_kills)} ground
{formatNumber(game.stats?.air_kills)} air
{formatNumber(game.stats?.assists)} assists
{formatNumber(game.stats?.deaths)} deaths
))}
{!games.length ? (
{status === 'loading' ? 'Loading battle results' : 'No battle results returned'}
) : null}
)
}
function BattleLogsPage({ live, matches }) {
return (
Battle Logs
{live.status === 'loading' ? 'Loading battles' : live.error || `${matches.length} battles returned`}
{matches.map((match) => (
{match.map_name || 'Unknown map'}
{formatDate(match.timestamp)} · {match.session_id}
{match.team_name || 'TSS team'}
{match.long_name || 'TSS battle record'}
{match.result || 'Unknown'}
{formatNumber(match.player_count)} players
{formatNumber(match.stats?.ground_kills)} ground
{formatNumber(match.stats?.air_kills)} air
{formatNumber(match.stats?.deaths)} deaths
))}
{!matches.length ? (
{live.status === 'loading' ? 'Loading battles' : 'No battles returned'}
) : null}
)
}
function relativeSeconds(timestamp) {
if (!timestamp) return 'unknown'
const seconds = Math.max(0, Math.round((Date.now() - new Date(timestamp).getTime()) / 1000))
if (seconds < 60) return `${seconds}s ago`
return `${Math.round(seconds / 60)}m ago`
}
function ViewersPage({ viewers }) {
const data = viewers.data || {}
const active = data.active || []
const topPages = data.top_pages || []
const clients = data.clients || []
const totals = data.totals || {}
const generatedAt = data.generated_at ? dateFormat.format(new Date(data.generated_at)) : 'Waiting for data'
return (
Public analytics
viewers
Live consented browser sessions and page activity. Last refreshed {generatedAt}.
{viewers.status === 'loading' ? 'Loading' : `${formatNumber(totals.active_now)} active now`}
Currently viewing
Heartbeats within {formatNumber(data.active_window_seconds || 75)} seconds
{active.map((viewer) => (
{viewer.page_title || viewer.page_path}
{viewer.page_path}
{viewer.browser} on {viewer.os}
{viewer.device} · {viewer.screen || 'unknown screen'} · {viewer.timezone || 'unknown timezone'}
{viewer.language || 'unknown language'}
Seen {relativeSeconds(viewer.last_seen_at)}
#{viewer.session}
))}
{!active.length ? (
{viewers.error || 'No consented viewers are active right now'}
) : null}
Top pages
Page views over the last 24 hours
{topPages.map((page) => (
{page.page_title || page.page_path}
{page.page_path}
{formatNumber(page.views)}
))}
{!topPages.length ?
No page views recorded yet
: null}
Clients
Browsers, devices, and operating systems seen in 24 hours
{clients.map((client) => (
{client.browser} on {client.os}
{client.device}
{formatNumber(client.events)}
))}
{!clients.length ?
No client data recorded yet
: null}
Analytics are opt-in, retained for {formatNumber(data.privacy?.retention_days || 30)} days,
and public output excludes raw IP addresses.
)
}
function UptimePage({ uptime }) {
const checks = uptime.checks
const history = uptime.history
const operationalCount = checks.filter((check) => check.ok).length
const allOperational = checks.length > 0 && operationalCount === checks.length
const updatedAt = uptime.updatedAt ? dateFormat.format(new Date(uptime.updatedAt)) : 'Not checked yet'
const onlineSamples = history.filter((sample) => sample.ok).length
const availability = history.length ? (onlineSamples / history.length) * 100 : 0
return (
Website uptime
{allOperational ? 'All systems operational' : 'Status check'}
Last server snapshot {updatedAt}. The page refreshes once a minute.
{uptime.status === 'loading' ? 'Checking' : `${operationalCount}/${checks.length || 3} online`}
Availability timeline
Last {formatNumber(history.length)} persisted server snapshots
{history.length ? `${availability.toFixed(1)}% uptime` : 'Waiting for first sample'}
{history.map((sample) => {
const height = `${Math.max(12, (sample.onlineChecks / sample.totalChecks) * 100)}%`
return (
)
})}
{!history.length ? (
Checking website status
) : null}
Uptime
Downtime or degraded
{checks.map((check) => (
{check.name}
{check.detail}
{check.ok ? 'Online' : 'Issue'}
{check.label}
{formatNumber(check.latency)} ms response window
))}
{!checks.length ? (
Checking website status
) : null}
)
}
export default App