feat(admin): dashboard home, telemetry section, enrollment ops screen

- mission-control dashboard: now strip, tournament quick actions, usage
  sparklines, error feed, live activity, tools list
- /admin/telemetry with functions/events/errors/players/usage child routes,
  hand-rolled svg chart primitives, decomposed activities table
- error browser with grouping and mark-resolved
- consolidated per-tournament enrollment screen; hub simplified with
  run tournament promoted
- /admin/activities redirects to /admin/telemetry/functions
This commit is contained in:
2026-08-25 21:54:21 -07:00
parent 06fe1f4ed7
commit a52872bea8
46 changed files with 2824 additions and 645 deletions
+3 -48
View File
@@ -1,52 +1,7 @@
import { createFileRoute } from "@tanstack/react-router";
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
import { ActivitiesTable, activityQueries } from "@/features/activities";
import { PlayersActivityTable, playerQueries } from "@/features/players";
import { ListSkeleton } from "@/components/skeletons";
import { Tabs } from "@mantine/core";
import { Suspense, useState } from "react";
import { Trans } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";
import { createFileRoute, redirect } from "@tanstack/react-router";
export const Route = createFileRoute("/_authed/admin/activities")({
component: Stats,
beforeLoad: ({ context }) => {
const queryClient = context.queryClient;
prefetchServerQuery(queryClient, activityQueries.search());
prefetchServerQuery(queryClient, playerQueries.activity());
beforeLoad: () => {
throw redirect({ to: "/admin/telemetry/functions" });
},
loader: () => ({
withPadding: false,
fullWidth: true,
header: {
title: msg`Activities`,
withBackButton: true,
},
refresh: [activityQueries.search().queryKey, playerQueries.activity().queryKey],
}),
});
function Stats() {
const [activeTab, setActiveTab] = useState<string | null>("server-functions");
return (
<Tabs value={activeTab} onChange={setActiveTab}>
<Tabs.List mb='md'>
<Tabs.Tab value="server-functions"><Trans>Server Functions</Trans></Tabs.Tab>
<Tabs.Tab value="player-activity"><Trans>Player Activity</Trans></Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="server-functions">
<Suspense fallback={<ListSkeleton rows={8} withSearch withSubtitle withTrailing="text" />}>
<ActivitiesTable />
</Suspense>
</Tabs.Panel>
<Tabs.Panel value="player-activity">
<Suspense fallback={<ListSkeleton rows={8} withSubtitle withTrailing="text" />}>
<PlayersActivityTable />
</Suspense>
</Tabs.Panel>
</Tabs>
);
}