Add admin dashboard pages and restructure admin route
Introduces new admin dashboard pages for alerts, bans, invites, orders, settings, status, and vendors under app/dashboard/admin/. Moves the main admin page to the new dashboard structure and adds a shared admin layout. Updates sidebar configuration and adds supporting components and hooks for admin features.
This commit is contained in:
210
app/dashboard/admin/status/page.tsx
Normal file
210
app/dashboard/admin/status/page.tsx
Normal file
@@ -0,0 +1,210 @@
|
||||
import React from "react";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Server, Database, Cpu, HardDrive, Activity } from "lucide-react";
|
||||
import { fetchServer } from "@/lib/api";
|
||||
|
||||
interface SystemStatus {
|
||||
uptimeSeconds: number;
|
||||
memory: {
|
||||
rss: number;
|
||||
heapTotal: number;
|
||||
heapUsed: number;
|
||||
external: number;
|
||||
arrayBuffers: number;
|
||||
};
|
||||
versions: Record<string, string>;
|
||||
counts: {
|
||||
vendors: number;
|
||||
orders: number;
|
||||
products: number;
|
||||
chats: number;
|
||||
};
|
||||
}
|
||||
|
||||
export default async function AdminStatusPage() {
|
||||
let systemStatus: SystemStatus | null = null;
|
||||
let error: string | null = null;
|
||||
|
||||
try {
|
||||
systemStatus = await fetchServer<SystemStatus>("/admin/system-status");
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch system status:", err);
|
||||
error = "Failed to load system status";
|
||||
}
|
||||
if (error) {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">System Status</h1>
|
||||
<p className="text-sm text-muted-foreground mt-1">Monitor system health and performance metrics</p>
|
||||
</div>
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<div className="text-center text-red-500">
|
||||
<p>{error}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const formatUptime = (seconds: number) => {
|
||||
const days = Math.floor(seconds / 86400);
|
||||
const hours = Math.floor((seconds % 86400) / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
return `${days}d ${hours}h ${minutes}m`;
|
||||
};
|
||||
|
||||
const formatBytes = (bytes: number) => {
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
||||
};
|
||||
|
||||
const memoryUsagePercent = systemStatus ?
|
||||
Math.round((systemStatus.memory.heapUsed / systemStatus.memory.heapTotal) * 100) : 0;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">System Status</h1>
|
||||
<p className="text-sm text-muted-foreground mt-1">Monitor system health and performance metrics</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{/* Server Status */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Server Status</CardTitle>
|
||||
<Server className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge variant="default" className="bg-green-500">Online</Badge>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{systemStatus ? formatUptime(systemStatus.uptimeSeconds) : 'N/A'}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
Last checked: {new Date().toLocaleTimeString()}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Database Status */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Database</CardTitle>
|
||||
<Database className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge variant="default" className="bg-green-500">Connected</Badge>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{systemStatus ? `${systemStatus.counts.vendors + systemStatus.counts.orders + systemStatus.counts.products} records` : 'N/A'}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
Total collections: 4
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Memory Usage */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Memory</CardTitle>
|
||||
<HardDrive className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge variant={memoryUsagePercent > 80 ? "destructive" : memoryUsagePercent > 60 ? "secondary" : "outline"}>
|
||||
{memoryUsagePercent}%
|
||||
</Badge>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{systemStatus ? formatBytes(systemStatus.memory.heapUsed) : 'N/A'}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
Total: {systemStatus ? formatBytes(systemStatus.memory.heapTotal) : 'N/A'}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Platform Stats */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Platform Stats</CardTitle>
|
||||
<Activity className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge variant="default" className="bg-green-500">Active</Badge>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{systemStatus ? `${systemStatus.counts.vendors} vendors` : 'N/A'}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
{systemStatus ? `${systemStatus.counts.orders} orders, ${systemStatus.counts.products} products` : 'N/A'}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Node.js Version */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Runtime</CardTitle>
|
||||
<Activity className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge variant="outline">
|
||||
{systemStatus ? `Node ${systemStatus.versions.node}` : 'N/A'}
|
||||
</Badge>
|
||||
<span className="text-sm text-muted-foreground">Runtime</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
{systemStatus ? `V8: ${systemStatus.versions.v8}` : 'N/A'}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Recent System Activity</CardTitle>
|
||||
<CardDescription>Latest system events and changes</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium">System health check completed</p>
|
||||
<p className="text-xs text-muted-foreground">2 minutes ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium">Database backup completed</p>
|
||||
<p className="text-xs text-muted-foreground">1 hour ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-2 h-2 bg-yellow-500 rounded-full"></div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium">High memory usage detected</p>
|
||||
<p className="text-xs text-muted-foreground">3 hours ago</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user