"use client"; import * as React from "react"; import { useRouter } from "next/navigation"; import { Search } from "lucide-react"; import { useAdminQuery } from "@/components/admin/use-query"; import type { UserListRow, UsersResponse } from "@/components/admin/types"; import { PageHeader, RefreshButton, Panel, DataTable, ErrorState, TableSkeleton, Pagination, DenseInput, DenseSelect, UserStatusPill, type Column } from "@/components/admin/primitives"; import { dateTime, int, sc } from "@/components/admin/format"; import { timeAgo } from "@/lib/utils"; const SORTS = [ { value: "created", label: "Newest" }, { value: "spins", label: "Most spins" }, { value: "balance", label: "Highest balance" }, { value: "level", label: "Highest level" }, ] as const; type Sort = (typeof SORTS)[number]["value"]; const LIMIT = 50; const cols: Column[] = [ { key: "username", header: "Username", render: (r) => {r.username} }, { key: "level", header: "Level", align: "right", render: (r) => r.level }, { key: "balance", header: "Balance", align: "right", render: (r) => {sc(r.balance)} }, { key: "spins", header: "Spins", align: "right", render: (r) => int(r.totalSpins) }, { key: "wagered", header: "Wagered", align: "right", render: (r) => sc(r.wagered) }, { key: "won", header: "Won", align: "right", render: (r) => sc(r.won) }, { key: "status", header: "Status", render: (r) => }, { key: "created", header: "Created", render: (r) => {dateTime(r.createdAt)} }, { key: "lastLogin", header: "Last login", render: (r) => {r.lastLoginAt ? timeAgo(r.lastLoginAt) : "never"} }, ]; function useDebounced(value: T, delay = 300): T { const [v, setV] = React.useState(value); React.useEffect(() => { const t = setTimeout(() => setV(value), delay); return () => clearTimeout(t); }, [value, delay]); return v; } export default function AdminUsersPage() { const router = useRouter(); const [q, setQ] = React.useState(""); const [sort, setSort] = React.useState("created"); const [offset, setOffset] = React.useState(0); const dq = useDebounced(q.trim()); const params = new URLSearchParams({ sort, limit: String(LIMIT), offset: String(offset) }); if (dq) params.set("q", dq); const query = useAdminQuery(`/api/admin/users?${params.toString()}`); const data = query.data; return ( <> void query.refresh()} loading={query.refreshing} />} />
{ setQ(e.target.value); setOffset(0); }} aria-label="Search users" />
{ setSort(e.target.value as Sort); setOffset(0); }} aria-label="Sort users" > {SORTS.map((s) => ( ))} {data ? {int(data.total)} accounts : null}
{query.error && !data ? (
void query.refresh()} />
) : !data ? ( ) : ( <> r.id} dense stale={query.stale} onRowClick={(r) => router.push(`/admin/users/${r.id}`)} empty={dq ? `No users match "${dq}".` : "No registered users yet."} /> )}
); }