Files
flxn-app/src/features/admin/components/dashboard/tools-list.tsx
T
kyle fd0489a22f refactor(telemetry): chart scale labels, calmer vitals and error styling, usage-first tabs
- sparklines get start/end date and max-value footers
- vitals rating shown by value color instead of badges
- error rows use plain counts, subtle resolve button, terse empty state
- telemetry tab order: usage, players, functions, events, errors; usage is default
2026-08-25 22:35:16 -07:00

111 lines
3.1 KiB
TypeScript

import { List, Text } from "@mantine/core";
import { Plural, Trans, useLingui } from "@lingui/react/macro";
import {
DatabaseIcon,
TreeStructureIcon,
TrophyIcon,
MedalIcon,
CrownIcon,
PulseIcon,
} from "@phosphor-icons/react";
import ListLink from "@/components/list-link";
import ListButton from "@/components/list-button";
import { getBadgeMigrationStatus, migrateBadgeProgress } from "@/features/badges/server";
import { useServerQuery } from "@/lib/tanstack-query/hooks";
import toast from "@/lib/sonner";
export const ToolsList = () => {
const { t } = useLingui();
const { data: migrationStatus, refetch: refetchMigrationStatus } = useServerQuery({
queryKey: ["admin", "badge-migration-status"],
queryFn: () => getBadgeMigrationStatus(),
options: {
refetchInterval: (query) =>
query.state.data?.state === "running" ? 2000 : false,
},
});
const isMigrating = migrationStatus?.state === "running";
const handleMigrateBadges = async () => {
if (isMigrating) return;
const result = await migrateBadgeProgress();
if (result.success) {
toast.success(
result.data.started
? t`Badge recalculation started in the background`
: t`Badge recalculation is already running`
);
} else {
toast.error(t`Failed to start badge recalculation`);
}
await refetchMigrationStatus();
};
return (
<List p="0">
<ListLink
label={t`Manage Tournaments`}
Icon={TrophyIcon}
to="/admin/tournaments"
/>
<ListLink
label={t`Telemetry`}
Icon={PulseIcon}
to="/admin/telemetry/usage"
/>
<ListLink
label={t`Award Badges`}
Icon={CrownIcon}
to="/admin/badges"
/>
<ListButton
label={t`Migrate Badge Progress`}
Icon={MedalIcon}
onClick={handleMigrateBadges}
loading={isMigrating}
/>
{migrationStatus?.state === "running" && (
<Text size="sm" c="dimmed" px="md" py="xs">
<Trans>
Recalculating badges in the background ({migrationStatus.playersProcessed}/{migrationStatus.totalPlayers})
</Trans>
</Text>
)}
{migrationStatus?.state === "completed" && (
<Text size="sm" c="dimmed" px="md" py="xs">
<Trans>
Last recalculation:{" "}
<Plural
value={migrationStatus.result.totalBadgesEarned}
one="# badge earned"
other="# badges earned"
/>
</Trans>
</Text>
)}
{migrationStatus?.state === "failed" && (
<Text size="sm" c="red" px="md" py="xs">
<Trans>Badge recalculation failed. Check the server logs.</Trans>
</Text>
)}
<ListButton
label={t`Open Pocketbase`}
Icon={DatabaseIcon}
onClick={() =>
window.location.replace(process.env.POCKETBASE_URL! + "/_/")
}
/>
<ListLink
label={t`Bracket Preview`}
Icon={TreeStructureIcon}
to="/admin/preview"
/>
</List>
);
};
export default ToolsList;