forked from syntaxbullet/aurorabot
165 lines
7.1 KiB
TypeScript
165 lines
7.1 KiB
TypeScript
import React, { useState } from "react";
|
|
import { SectionHeader } from "../../components/section-header";
|
|
import { useSocket } from "../../hooks/use-socket";
|
|
import { StatCard } from "../../components/stat-card";
|
|
import { ActivityChart } from "../../components/activity-chart";
|
|
import { LootdropCard } from "../../components/lootdrop-card";
|
|
import { LeaderboardCard } from "../../components/leaderboard-card";
|
|
import { RecentActivity } from "../../components/recent-activity";
|
|
import { CommandsDrawer } from "../../components/commands-drawer";
|
|
import { Server, Users, Terminal, Activity, Coins, TrendingUp, Flame, Package } from "lucide-react";
|
|
import { cn } from "../../lib/utils";
|
|
|
|
export function AdminOverview() {
|
|
const { isConnected, stats } = useSocket();
|
|
const [commandsDrawerOpen, setCommandsDrawerOpen] = useState(false);
|
|
|
|
return (
|
|
<>
|
|
<main className="pt-8 px-8 pb-12 max-w-7xl mx-auto space-y-8">
|
|
<SectionHeader
|
|
badge="Admin Dashboard"
|
|
title="Overview"
|
|
description="Monitor your Aurora RPG server statistics and activity."
|
|
/>
|
|
|
|
{/* Stats Grid */}
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 animate-in fade-in slide-up duration-700">
|
|
<StatCard
|
|
title="Total Servers"
|
|
icon={Server}
|
|
isLoading={!stats}
|
|
value={stats?.guilds.count.toLocaleString()}
|
|
subtitle={stats?.guilds.changeFromLastMonth
|
|
? `${stats.guilds.changeFromLastMonth > 0 ? '+' : ''}${stats.guilds.changeFromLastMonth} from last month`
|
|
: "Active Guilds"
|
|
}
|
|
/>
|
|
|
|
<StatCard
|
|
title="Total Users"
|
|
icon={Users}
|
|
isLoading={!stats}
|
|
value={stats?.users.total.toLocaleString()}
|
|
subtitle={stats ? `${stats.users.active.toLocaleString()} active now` : undefined}
|
|
className="delay-100"
|
|
/>
|
|
|
|
<StatCard
|
|
title="Commands"
|
|
icon={Terminal}
|
|
isLoading={!stats}
|
|
value={stats?.commands.total.toLocaleString()}
|
|
subtitle={stats ? `${stats.commands.active} active · ${stats.commands.disabled} disabled` : undefined}
|
|
className="delay-200"
|
|
onClick={() => setCommandsDrawerOpen(true)}
|
|
/>
|
|
|
|
<StatCard
|
|
title="System Ping"
|
|
icon={Activity}
|
|
isLoading={!stats}
|
|
value={stats ? `${Math.round(stats.ping.avg)}ms` : undefined}
|
|
subtitle="Average latency"
|
|
className="delay-300"
|
|
valueClassName={stats ? cn(
|
|
"transition-colors duration-300",
|
|
stats.ping.avg < 100 ? "text-emerald-500" :
|
|
stats.ping.avg < 200 ? "text-yellow-500" : "text-red-500"
|
|
) : undefined}
|
|
/>
|
|
</div>
|
|
|
|
{/* Activity Chart */}
|
|
<div className="animate-in fade-in slide-up delay-400">
|
|
<ActivityChart />
|
|
</div>
|
|
|
|
<div className="grid gap-8 lg:grid-cols-3 animate-in fade-in slide-up delay-500">
|
|
{/* Economy Stats */}
|
|
<div className="lg:col-span-2 space-y-6">
|
|
<div>
|
|
<h2 className="text-xl font-semibold tracking-tight mb-4">Economy Overview</h2>
|
|
<div className="grid gap-4 md:grid-cols-2">
|
|
<StatCard
|
|
title="Total Wealth"
|
|
icon={Coins}
|
|
isLoading={!stats}
|
|
value={stats ? `${Number(stats.economy.totalWealth).toLocaleString()} AU` : undefined}
|
|
subtitle="Astral Units in circulation"
|
|
valueClassName="text-primary"
|
|
iconClassName="text-primary"
|
|
/>
|
|
|
|
<StatCard
|
|
title="Items Circulating"
|
|
icon={Package}
|
|
isLoading={!stats}
|
|
value={stats?.economy.totalItems?.toLocaleString()}
|
|
subtitle="Total items owned by users"
|
|
className="delay-75"
|
|
valueClassName="text-blue-500"
|
|
iconClassName="text-blue-500"
|
|
/>
|
|
|
|
<StatCard
|
|
title="Average Level"
|
|
icon={TrendingUp}
|
|
isLoading={!stats}
|
|
value={stats ? `Lvl ${stats.economy.avgLevel}` : undefined}
|
|
subtitle="Global player average"
|
|
className="delay-100"
|
|
valueClassName="text-secondary"
|
|
iconClassName="text-secondary"
|
|
/>
|
|
|
|
<StatCard
|
|
title="Top /daily Streak"
|
|
icon={Flame}
|
|
isLoading={!stats}
|
|
value={stats?.economy.topStreak}
|
|
subtitle="Days daily streak"
|
|
className="delay-200"
|
|
valueClassName="text-destructive"
|
|
iconClassName="text-destructive"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<LeaderboardCard
|
|
data={stats?.leaderboards}
|
|
isLoading={!stats}
|
|
className="w-full"
|
|
/>
|
|
</div>
|
|
|
|
{/* Recent Activity & Lootdrops */}
|
|
<div className="space-y-6">
|
|
<LootdropCard
|
|
drop={stats?.activeLootdrops?.[0]}
|
|
state={stats?.lootdropState}
|
|
isLoading={!stats}
|
|
/>
|
|
<div className="h-[calc(100%-12rem)] min-h-[400px]">
|
|
<h2 className="text-xl font-semibold tracking-tight mb-4">Live Feed</h2>
|
|
<RecentActivity
|
|
events={stats?.recentEvents || []}
|
|
isLoading={!stats}
|
|
className="h-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
{/* Commands Drawer */}
|
|
<CommandsDrawer
|
|
open={commandsDrawerOpen}
|
|
onOpenChange={setCommandsDrawerOpen}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default AdminOverview;
|