Implemented comprehensive Chromebook-specific fixes including viewport adjustments, enhanced touch and keyboard detection, improved scrolling and keyboard navigation hooks, and extensive CSS optimizations for better usability. Updated chat and dashboard interfaces for larger touch targets, better focus management, and responsive layouts. Added documentation in docs/CHROMEBOOK-FIXES.md and new hooks for Chromebook scroll and keyboard handling.
211 lines
8.1 KiB
TypeScript
211 lines
8.1 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";
|
|
|
|
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-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>
|
|
|
|
{/* 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>
|
|
);
|
|
}
|