loading gradually player sessions instead all at once

This commit is contained in:
jenz
2026-09-12 13:56:53 +02:00
parent 300000d920
commit 74e72bfdac
4 changed files with 141 additions and 35 deletions
@@ -0,0 +1,15 @@
import { NextRequest, NextResponse } from 'next/server';
import { getSessions } from '@/lib/queries';
const PAGE_SIZE = 10;
export async function GET(req: NextRequest, { params }: { params: Promise<{ steamid: string }> }) {
const { steamid: rawSteamid } = await params;
const steamid = decodeURIComponent(rawSteamid);
const offset = Math.max(0, Number(req.nextUrl.searchParams.get('offset')) || 0);
const sessions = await getSessions(steamid, PAGE_SIZE, offset);
const hasMore = sessions.length === PAGE_SIZE;
return NextResponse.json({ sessions, hasMore });
}
@@ -1,9 +1,10 @@
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { getPlayer, getNameHistory, getSessions, getTotalPlaytimeMinutes } from '@/lib/queries';
import { getPlayer, getNameHistory, getTotalPlaytimeMinutes } from '@/lib/queries';
import { steam2ToSteam64, steamProfileUrl, formatMinutes, countryCodeToFlag } from '@/lib/steam';
import { getSteamSummary, DEFAULT_AVATAR_URL } from '@/lib/steamApi';
import { getRaceTimerSummary } from '@/lib/racetimer';
import PlayerSessionsList from '@/components/PlayerSessionsList';
export default async function PlayerDetailPage({
params,
@@ -21,9 +22,14 @@ export default async function PlayerDetailPage({
const steamId64 = steam2ToSteam64(steamid);
const profileUrl = steamProfileUrl(steamid);
const [nameHistory, sessions, totalMinutes, steamSummary, raceTimer] = await Promise.all([
// Sessions are deliberately NOT fetched here — that query's per-row
// maps_played subquery gets slower as a player accumulates history, and
// was making this page take 20-30+ seconds for long-tenured players
// regardless of whether anyone scrolled far enough to see old sessions.
// PlayerSessionsList below fetches its own first page client-side, so
// everything else on this page renders immediately.
const [nameHistory, totalMinutes, steamSummary, raceTimer] = await Promise.all([
getNameHistory(steamid),
getSessions(steamid),
getTotalPlaytimeMinutes(steamid),
steamId64 ? getSteamSummary(steamId64) : Promise.resolve(null),
getRaceTimerSummary(steamid),
@@ -120,35 +126,7 @@ export default async function PlayerDetailPage({
{/* Sessions */}
<div className="panel p-6">
<div className="stat-label mb-3">Play sessions</div>
{sessions.length === 0 ? (
<div className="text-sm text-ink-muted">No recorded sessions yet.</div>
) : (
<div className="row-divide">
<div className="grid grid-cols-[1fr_1fr_100px] gap-4 pb-2 text-xs text-ink-faint uppercase tracking-wide">
<div>Started</div>
<div>Map(s)</div>
<div className="text-right">Playtime</div>
</div>
{sessions.map((s) => (
<div key={s.session_id} className="grid grid-cols-[1fr_1fr_100px] gap-4 py-3 text-sm items-center">
<div>
<div className="text-ink">
{new Date(s.session_start_dt.replace(' ', 'T')).toLocaleString()}
</div>
<div className="text-xs text-ink-faint">
{s.session_end_dt
? `until ${new Date(s.session_end_dt.replace(' ', 'T')).toLocaleTimeString()}`
: 'still connected'}
</div>
</div>
<div className="text-ink-muted">{s.maps_played ?? '—'}</div>
<div className="text-right mono text-ink">
{formatMinutes(s.session_active_minutes)}
</div>
</div>
))}
</div>
)}
<PlayerSessionsList steamid={steamid} />
</div>
</div>
);