ai generated solutions to our ai generated problems

This commit is contained in:
Heidi
2026-06-18 00:43:52 +01:00
parent ed4b2db600
commit 930e53bf51
+63 -20
View File
@@ -15,6 +15,7 @@ const apiEndpoints = {
viewerEvent: '/api/viewers/event',
viewerDelete: '/api/viewers/delete',
teams: '/api/tss/leaderboard/teams?limit=100',
homeTeams: '/api/tss/leaderboard/teams?limit=4',
teamsHealth: '/api/tss/leaderboard/teams?limit=1',
recentGames: '/api/tss/games/recent?limit=50',
game: (gameId) => `/api/tss/games/${encodeURIComponent(gameId)}`,
@@ -910,6 +911,7 @@ function App() {
function AppContent() {
const [route, setRoute] = useState(() => parseRoute())
const [leaderboard, setLeaderboard] = useState({ status: 'idle', data: null, error: null })
const [homeTeams, setHomeTeams] = useState({ status: 'idle', data: null, error: null })
const [live, setLive] = useState({ status: 'idle', data: null, error: null, updatedAt: 0 })
const [uptime, setUptime] = useState({ status: 'idle', checks: [], history: [], updatedAt: null })
const [viewers, setViewers] = useState({ status: 'idle', data: null, error: null, updatedAt: null })
@@ -932,6 +934,10 @@ function AppContent() {
() => leaderboard.data?.teams || leaderboard.data?.squadrons || [],
[leaderboard.data],
)
const teamsToWatch = useMemo(
() => homeTeams.data?.teams || homeTeams.data?.squadrons || teams.slice(0, 4),
[homeTeams.data, teams],
)
const matches = live.data?.matches || []
const liveRef = useRef(live)
const navPillRef = useRef(null)
@@ -1163,7 +1169,7 @@ function AppContent() {
}, [teamQuery])
useEffect(() => {
if (!['home', 'teams', 'team', 'battle-logs'].includes(route.page)) return
if (!['teams', 'team', 'battle-logs'].includes(route.page)) return
if (leaderboard.status === 'ready' || leaderboard.status === 'loading') return
const controller = new AbortController()
@@ -1181,7 +1187,25 @@ function AppContent() {
}, [leaderboard.status, route.page])
useEffect(() => {
if (!['home', 'teams', 'team', 'battle-logs'].includes(route.page)) return
if (route.page !== 'home') return
if (homeTeams.status === 'ready' || homeTeams.status === 'loading') return
const controller = new AbortController()
setHomeTeams({ status: 'loading', data: null, error: null })
fetchJson(apiEndpoints.homeTeams, controller.signal)
.then((data) => setHomeTeams({ status: 'ready', data, error: null }))
.catch((error) => {
if (!controller.signal.aborted) {
setHomeTeams({ status: 'error', data: null, error: error.message })
}
})
return () => controller.abort()
}, [homeTeams.status, route.page])
useEffect(() => {
if (!['teams', 'team', 'battle-logs'].includes(route.page)) return
const controller = new AbortController()
const timer = window.setInterval(() => {
@@ -1617,6 +1641,7 @@ function AppContent() {
setTeamQuery={setTeamQuery}
teamSuggestions={teamSuggestions}
teams={teams}
teamsToWatch={teamsToWatch}
teamQuery={teamQuery}
/>
) : null}
@@ -2104,6 +2129,7 @@ function Landing({
setTeamQuery,
teamSuggestions,
teams,
teamsToWatch,
teamQuery,
}) {
const treeRef = useRef(null)
@@ -2190,15 +2216,16 @@ function Landing({
</section>
</div>
<LandingOverview teams={teams} matches={matches} navigate={navigate} />
<LandingOverview teams={teams} teamsToWatch={teamsToWatch} matches={matches} navigate={navigate} />
<RecentGamesSection live={live} matches={matches} navigate={navigate} />
<LandingTrustSection navigate={navigate} />
</div>
)
}
function LandingOverview({ teams, matches, navigate }) {
const activeTeams = teams.slice(0, 4)
function LandingOverview({ teams, teamsToWatch, matches, navigate }) {
const activeTeams = teamsToWatch.slice(0, 4)
const visibleTeamCount = teams.length || teamsToWatch.length
const totalPlayers = matches.reduce((sum, match) => sum + Number(match.player_count || 0), 0)
const latestMatch = matches[0]
@@ -2216,7 +2243,7 @@ function LandingOverview({ teams, matches, navigate }) {
</p>
<div className="mt-6 grid gap-3 sm:grid-cols-3">
<LandingMetric label="Teams indexed" value={formatNumber(teams.length)} />
<LandingMetric label="Teams indexed" value={formatNumber(visibleTeamCount)} />
<LandingMetric label="Recent games" value={formatNumber(matches.length)} />
<LandingMetric label="Players seen" value={formatNumber(totalPlayers)} />
</div>
@@ -2800,49 +2827,65 @@ function GamePage({ gameId, navigate }) {
</div>
</div>
<div>
<div className="overflow-x-auto">
<div className="min-w-[760px]">
{participants.length ? (
<div className="grid grid-cols-[minmax(220px,1fr)_80px_repeat(5,88px)] gap-3 border-b border-surface px-5 py-3 text-xs font-semibold uppercase tracking-wide text-text-soft">
<p>Team / player</p>
<p className="text-right">Players</p>
<p className="text-right">Ground</p>
<p className="text-right">Air</p>
<p className="text-right">Assists</p>
<p className="text-right">Score</p>
<p className="text-right">Deaths</p>
</div>
) : null}
{participants.map((participant) => {
const won = String(participant.result || '').toLowerCase() === 'win'
return (
<div className="border-b border-surface" key={participant.team_name}>
<button
className="grid w-full gap-4 px-5 py-4 text-left transition hover:bg-surface md:grid-cols-[1fr_repeat(5,auto)] md:items-center"
className="grid w-full grid-cols-[minmax(220px,1fr)_80px_repeat(5,88px)] gap-3 px-5 py-3 text-left transition hover:bg-surface"
onClick={() => navigate(teamPath(participant.team_name))}
type="button"
>
<p className={`truncate font-semibold ${won ? 'text-fury-violet' : 'text-text-soft'}`}>
{participant.team_name}
</p>
<p className="text-sm">{formatNumber(participant.player_count)} players</p>
<p className="text-sm">{formatNumber(participant.stats?.ground_kills)} ground</p>
<p className="text-sm">{formatNumber(participant.stats?.air_kills)} air</p>
<p className="text-sm">{formatNumber(participant.stats?.assists)} assists</p>
<p className="text-sm">{formatNumber(participant.stats?.deaths)} deaths</p>
<p className="text-right text-sm">{formatNumber(participant.player_count)}</p>
<p className="text-right text-sm">{formatNumber(participant.stats?.ground_kills)}</p>
<p className="text-right text-sm">{formatNumber(participant.stats?.air_kills)}</p>
<p className="text-right text-sm">{formatNumber(participant.stats?.assists)}</p>
<p className="text-right text-sm text-text-muted">-</p>
<p className="text-right text-sm">{formatNumber(participant.stats?.deaths)}</p>
</button>
<div className="pb-3">
{(participant.players || []).map((player) => (
<button
className="grid w-full gap-3 px-5 py-2 pl-10 text-left text-sm transition hover:bg-surface md:grid-cols-[1fr_repeat(5,auto)] md:items-center sm:pl-14"
className="grid w-full grid-cols-[minmax(220px,1fr)_80px_repeat(5,88px)] gap-3 px-5 py-2 text-left text-sm transition hover:bg-surface"
key={player.uid}
onClick={() => navigate(`/players/${encodeURIComponent(player.uid)}`)}
type="button"
>
<div className="min-w-0">
<div className="min-w-0 pl-8 sm:pl-12">
<p className="truncate font-semibold text-text">{player.nick || player.uid}</p>
<p className="text-xs text-text-soft">{player.uid}</p>
</div>
<p>{formatNumber(player.stats?.ground_kills)} ground</p>
<p>{formatNumber(player.stats?.air_kills)} air</p>
<p>{formatNumber(player.stats?.assists)} assists</p>
<p>{formatNumber(player.stats?.score)} score</p>
<p>{formatNumber(player.stats?.deaths)} deaths</p>
<p className="text-right text-text-muted">-</p>
<p className="text-right">{formatNumber(player.stats?.ground_kills)}</p>
<p className="text-right">{formatNumber(player.stats?.air_kills)}</p>
<p className="text-right">{formatNumber(player.stats?.assists)}</p>
<p className="text-right">{formatNumber(player.stats?.score)}</p>
<p className="text-right">{formatNumber(player.stats?.deaths)}</p>
</button>
))}
</div>
</div>
)
})}
</div>
{!participants.length ? (
<p className="px-5 py-10 text-sm text-text-soft">