"use client"; import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { Skeleton } from "@/components/ui/skeleton"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { PlayerAvatar } from "@/components/PlayerAvatar"; import { formatHours, timeAgo } from "@/lib/time"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; export type PlaytimeEntry = { uuid: string; name: string; playtimeTicks: number; playtimeHours: number; lastPlayedMs: number; }; const TOP_N = 10; export function PlaytimeLeaderboard() { const [showAll, setShowAll] = useState(false); const { data = [], isLoading, isError } = useQuery({ queryKey: ["players-playtime"], queryFn: () => fetch("/api/players/playtime").then((r) => r.json()), staleTime: 60_000, refetchInterval: 5 * 60_000, }); const visible = showAll ? data : data.slice(0, TOP_N); const totalHours = data.reduce((sum, e) => sum + e.playtimeHours, 0); return (
Playtime Total hours played by each whitelisted player
{data.length > 0 && (

Combined

{formatHours(totalHours)}

)}
{isLoading ? (
    {Array.from({ length: 5 }).map((_, i) => (
  • ))}
) : isError ? (

Failed to load playtime.

) : data.length === 0 ? (

No playtime recorded yet.

) : ( <>
    {visible.map((p, i) => (
  1. {i + 1}

    {p.name}

    last seen {timeAgo(p.lastPlayedMs)}

    {formatHours(p.playtimeHours)}
  2. ))}
{data.length > TOP_N && (
)} )}
); }