Added 'Year to Date' and 'Last Year' filters to analytics, and improved summary cards to show total revenue and orders for the selected period. Refactored SystemStatusCard to include a debug view with detailed system metrics and raw JSON response. Updated nav-item active state detection for more precision and improved navigation handling. Removed redundant recent activity card from admin status page.
181 lines
6.8 KiB
TypeScript
181 lines
6.8 KiB
TypeScript
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";
|
|
import SystemStatusCard from "@/components/admin/SystemStatusCard";
|
|
|
|
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>
|
|
|
|
<SystemStatusCard />
|
|
|
|
<div className="grid gap-4 lg:gap-6 sm: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>
|
|
</div>
|
|
);
|
|
}
|