feat: (ui) first dynamic data
This commit is contained in:
@@ -28,6 +28,7 @@ export function getClientStats(): ClientStats {
|
||||
ping: AuroraClient.ws.ping,
|
||||
cachedUsers: AuroraClient.users.cache.size,
|
||||
commandsRegistered: AuroraClient.commands.size,
|
||||
commandsKnown: AuroraClient.knownCommands.size,
|
||||
uptime: process.uptime(),
|
||||
lastCommandTimestamp: AuroraClient.lastCommandTimestamp,
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@ export const DashboardStatsSchema = z.object({
|
||||
}),
|
||||
commands: z.object({
|
||||
total: z.number(),
|
||||
active: z.number(),
|
||||
disabled: z.number(),
|
||||
changePercentFromLastMonth: z.number().optional(),
|
||||
}),
|
||||
ping: z.object({
|
||||
@@ -53,6 +55,7 @@ export const ClientStatsSchema = z.object({
|
||||
ping: z.number(),
|
||||
cachedUsers: z.number(),
|
||||
commandsRegistered: z.number(),
|
||||
commandsKnown: z.number(),
|
||||
uptime: z.number(),
|
||||
lastCommandTimestamp: z.number().nullable(),
|
||||
});
|
||||
|
||||
@@ -2,6 +2,10 @@ import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useSocket } from "../hooks/use-socket";
|
||||
import { Badge } from "../components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card";
|
||||
import { Skeleton } from "../components/ui/skeleton";
|
||||
import { Server, Users, Terminal, Activity } from "lucide-react";
|
||||
import { cn } from "../lib/utils";
|
||||
|
||||
export function Dashboard() {
|
||||
const { isConnected, stats } = useSocket();
|
||||
@@ -51,15 +55,107 @@ export function Dashboard() {
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Content Placeholder */}
|
||||
<main className="pt-32 px-8 max-w-7xl mx-auto">
|
||||
<div className="glass-card p-6 rounded-lg border border-border/50">
|
||||
<h1 className="text-2xl font-bold text-primary mb-2">Dashboard Overview</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Real-time connection status: <span className={isConnected ? "text-emerald-500 font-medium" : "text-red-500 font-medium"}>
|
||||
{isConnected ? "Connected" : "Disconnected"}
|
||||
</span>
|
||||
{/* Dashboard Content */}
|
||||
<main className="pt-32 px-8 max-w-7xl mx-auto space-y-8">
|
||||
|
||||
{/* Stats Grid */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 animate-in fade-in slide-up">
|
||||
<Card className="glass-card border-none bg-card/40 hover-glow">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Servers</CardTitle>
|
||||
<Server className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{stats ? (
|
||||
<>
|
||||
<div className="text-2xl font-bold">{stats.guilds.count.toLocaleString()}</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{stats.guilds.changeFromLastMonth
|
||||
? `${stats.guilds.changeFromLastMonth > 0 ? '+' : ''}${stats.guilds.changeFromLastMonth} from last month`
|
||||
: "Active Guilds"
|
||||
}
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-8 w-[60px]" />
|
||||
<Skeleton className="h-3 w-[100px]" />
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="glass-card border-none bg-card/40 hover-glow delay-100">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Users</CardTitle>
|
||||
<Users className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{stats ? (
|
||||
<>
|
||||
<div className="text-2xl font-bold">{stats.users.total.toLocaleString()}</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{stats.users.active.toLocaleString()} active now
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-8 w-[60px]" />
|
||||
<Skeleton className="h-3 w-[100px]" />
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="glass-card border-none bg-card/40 hover-glow delay-200">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Commands</CardTitle>
|
||||
<Terminal className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{stats ? (
|
||||
<>
|
||||
<div className="text-2xl font-bold">{stats.commands.total.toLocaleString()}</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{stats.commands.active} active · {stats.commands.disabled} disabled
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-8 w-[60px]" />
|
||||
<Skeleton className="h-3 w-[100px]" />
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="glass-card border-none bg-card/40 hover-glow delay-300">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">System Ping</CardTitle>
|
||||
<Activity className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{stats ? (
|
||||
<>
|
||||
<div className={cn(
|
||||
"text-2xl font-bold transition-colors duration-300",
|
||||
stats.ping.avg < 100 ? "text-emerald-500" :
|
||||
stats.ping.avg < 200 ? "text-yellow-500" : "text-red-500"
|
||||
)}>
|
||||
{Math.round(stats.ping.avg)}ms
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Average latency
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-8 w-[60px]" />
|
||||
<Skeleton className="h-3 w-[100px]" />
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -388,6 +388,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
bot: { name: 'Aurora', avatarUrl: null },
|
||||
guilds: 0,
|
||||
commandsRegistered: 0,
|
||||
commandsKnown: 0,
|
||||
cachedUsers: 0,
|
||||
ping: 0,
|
||||
uptime: 0,
|
||||
@@ -406,7 +407,11 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
bot: clientStats.bot,
|
||||
guilds: { count: clientStats.guilds },
|
||||
users: { active: activeUsers, total: totalUsers },
|
||||
commands: { total: clientStats.commandsRegistered },
|
||||
commands: {
|
||||
total: clientStats.commandsKnown,
|
||||
active: clientStats.commandsRegistered,
|
||||
disabled: clientStats.commandsKnown - clientStats.commandsRegistered
|
||||
},
|
||||
ping: { avg: clientStats.ping },
|
||||
economy: {
|
||||
totalWealth: economyStats.totalWealth.toString(),
|
||||
|
||||
Reference in New Issue
Block a user