feat(dashboard): expand stats & remove admin token auth

This commit is contained in:
syntaxbullet
2026-01-08 22:14:13 +01:00
parent cf4c28e1df
commit d46434de18
10 changed files with 257 additions and 330 deletions

View File

@@ -5,7 +5,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Activity, Server, Users, Zap } from "lucide-react";
import { Activity, Server, Users, Zap, Package, Trophy, Coins } from "lucide-react";
import { useDashboardStats } from "@/hooks/use-dashboard-stats";
import { useActivityStats } from "@/hooks/use-activity-stats";
import { ControlPanel } from "@/components/ControlPanel";
@@ -62,10 +62,11 @@ export function Dashboard() {
<p className="text-white/40 font-medium">Monitoring real-time activity and core bot metrics.</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
{/* Metric Cards */}
{[
{ title: "Active Users", value: stats.users.active.toLocaleString(), label: `${stats.users.total.toLocaleString()} total registered`, icon: Users, color: "from-purple-500 to-pink-500" },
{ title: "Items in Circulation", value: stats.economy.totalItems.toLocaleString(), label: "Total items owned", icon: Package, color: "from-blue-500 to-cyan-500" },
{ title: "Commands registered", value: stats.commands.total, label: "Total system capabilities", icon: Zap, color: "from-yellow-500 to-orange-500" },
{ title: "Avg Latency", value: `${stats.ping.avg}ms`, label: "WebSocket heartbeat", icon: Activity, color: "from-emerald-500 to-teal-500" },
].map((metric, i) => (
@@ -144,6 +145,34 @@ export function Dashboard() {
{/* Administrative Control Panel */}
<ControlPanel maintenanceMode={stats.maintenanceMode} />
{/* Active Lootdrop Alert */}
{stats.activeLootdrops && stats.activeLootdrops.length > 0 && (
<Card className="bg-gradient-to-br from-red-500/10 to-orange-500/10 border-red-500/20 overflow-hidden relative">
<div className="absolute top-0 right-0 p-4 opacity-10">
<Zap className="w-24 h-24 text-red-500" />
</div>
<CardHeader className="pb-2">
<CardTitle className="text-lg font-bold text-red-400 flex items-center gap-2">
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-red-500"></span>
</span>
ACTIVE LOOTDROP
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex flex-col gap-1">
<p className="text-2xl font-black text-white/90">
{stats.activeLootdrops[0]?.rewardAmount} {stats.activeLootdrops[0]?.currency}
</p>
<p className="text-xs font-medium text-white/50">
Expires <span className="text-red-300">{stats.activeLootdrops[0]?.expiresAt ? new Date(stats.activeLootdrops[0].expiresAt).toLocaleTimeString() : 'Never'}</span>
</p>
</div>
</CardContent>
</Card>
)}
{/* Recent Events Feed */}
<Card className="glass border-white/5 overflow-hidden flex-1">
<CardHeader className="bg-white/[0.02] border-b border-white/5">
@@ -187,6 +216,63 @@ export function Dashboard() {
</Card>
</div>
</div>
{/* Leaderboards Section */}
<div className="grid gap-6 md:grid-cols-2">
<Card className="glass border-white/5">
<CardHeader className="flex flex-row items-center gap-4">
<div className="p-2 bg-yellow-500/10 rounded-lg">
<Trophy className="w-5 h-5 text-yellow-500" />
</div>
<div>
<CardTitle className="text-lg font-bold">Top Levels</CardTitle>
<CardDescription className="text-white/40">Highest ranked users</CardDescription>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
{stats.leaderboards?.topLevels.map((user, i) => (
<div key={i} className="flex items-center justify-between p-3 rounded-lg bg-white/5 border border-white/5">
<div className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm ${i === 0 ? 'bg-yellow-500/20 text-yellow-500' : i === 1 ? 'bg-gray-400/20 text-gray-400' : i === 2 ? 'bg-orange-700/20 text-orange-700' : 'bg-white/5 text-white/40'}`}>
{i + 1}
</div>
<span className="font-semibold">{user.username}</span>
</div>
<span className="font-mono text-sm text-white/60">Lvl {user.level}</span>
</div>
)) || <p className="text-white/20 text-sm">No data available</p>}
</div>
</CardContent>
</Card>
<Card className="glass border-white/5">
<CardHeader className="flex flex-row items-center gap-4">
<div className="p-2 bg-emerald-500/10 rounded-lg">
<Coins className="w-5 h-5 text-emerald-500" />
</div>
<div>
<CardTitle className="text-lg font-bold">Richest Users</CardTitle>
<CardDescription className="text-white/40">Highest net worth</CardDescription>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
{stats.leaderboards?.topWealth.map((user, i) => (
<div key={i} className="flex items-center justify-between p-3 rounded-lg bg-white/5 border border-white/5">
<div className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm ${i === 0 ? 'bg-yellow-500/20 text-yellow-500' : i === 1 ? 'bg-gray-400/20 text-gray-400' : i === 2 ? 'bg-orange-700/20 text-orange-700' : 'bg-white/5 text-white/40'}`}>
{i + 1}
</div>
<span className="font-semibold">{user.username}</span>
</div>
<span className="font-mono text-sm text-white/60">{BigInt(user.balance).toLocaleString()} AU</span>
</div>
)) || <p className="text-white/20 text-sm">No data available</p>}
</div>
</CardContent>
</Card>
</div>
</div>
);
}