Files
source-gamepanel/apps/web/src/pages/server/players.tsx
T
hibna c1adb94abb Format the repository with Prettier
CI has been running `prettier --check` against a tree that was never
formatted, so the check reported 63 files and failed every run. Nothing
here is a behaviour change: `pnpm lint` and the four typecheck builds
pass exactly as before.

conduit-bringup-artifacts is added to .prettierignore instead. Those
files are captured bring-up reports, not maintained sources; reflowing
them would only churn a record of what happened.
2026-08-02 21:08:12 +03:00

80 lines
2.6 KiB
TypeScript

import { useParams } from 'react-router';
import { useQuery } from '@tanstack/react-query';
import { Users, RefreshCw } from 'lucide-react';
import { api } from '@/lib/api';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
interface Player {
name: string;
steamid?: string;
}
interface PlayerListResponse {
players: Player[];
maxPlayers: number;
}
export function PlayersPage() {
const { orgId, serverId } = useParams();
const { data, isLoading, refetch } = useQuery({
queryKey: ['players', orgId, serverId],
queryFn: () =>
api.get<PlayerListResponse>(`/organizations/${orgId}/servers/${serverId}/players`),
refetchInterval: 30000,
});
const players = data?.players ?? [];
const maxPlayers = data?.maxPlayers ?? 0;
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h2 className="text-lg font-semibold">Active Players</h2>
<p className="text-sm text-muted-foreground">
{players.length} / {maxPlayers} players online
</p>
</div>
<Button variant="outline" size="sm" onClick={() => refetch()} disabled={isLoading}>
<RefreshCw className={`h-4 w-4 ${isLoading ? 'animate-spin' : ''}`} />
Refresh
</Button>
</div>
{players.length === 0 ? (
<Card>
<CardContent className="flex flex-col items-center justify-center py-12">
<Users className="mb-4 h-12 w-12 text-muted-foreground/50" />
<p className="text-muted-foreground">No players online</p>
<p className="mt-1 text-xs text-muted-foreground">
Player tracking requires RCON to be enabled on the server
</p>
</CardContent>
</Card>
) : (
<Card>
<CardContent className="p-0">
<div className="divide-y">
{players.map((player, i) => (
<div key={i} className="flex items-center gap-3 px-4 py-3">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-sm font-medium text-primary">
{player.name.charAt(0).toUpperCase()}
</div>
<div>
<p className="font-medium">{player.name}</p>
{player.steamid && (
<p className="text-xs text-muted-foreground">{player.steamid}</p>
)}
</div>
</div>
))}
</div>
</CardContent>
</Card>
)}
</div>
);
}