aethex-studio/components/NexusSyncMonitor.tsx
2026-01-27 06:16:41 +00:00

168 lines
6.9 KiB
TypeScript

"use client";
import React from 'react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { useAppStore } from '@/store/app-store';
import { formatTimestamp } from '@/lib/utils';
import { ChevronRight } from 'lucide-react';
export function NexusSyncMonitor() {
const { syncEvents, syncStates } = useAppStore();
const [expandedItems, setExpandedItems] = React.useState<Set<string>>(new Set(['players']));
const toggleExpand = (id: string) => {
setExpandedItems(prev => {
const next = new Set(prev);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
});
};
return (
<div className="h-full flex bg-background">
{/* Left: State Tree */}
<div className="w-1/2 border-r border-gray-800 flex flex-col">
<div className="px-4 py-3 border-b border-gray-800">
<h3 className="font-semibold text-white">State Tree</h3>
</div>
<ScrollArea className="flex-1">
<div className="p-4 font-mono text-sm space-y-1">
<div className="text-primary"> GameState</div>
<div>
<button
onClick={() => toggleExpand('players')}
className="flex items-center gap-1 text-gray-300 hover:text-white w-full"
>
<ChevronRight className={`w-4 h-4 transition-transform ${expandedItems.has('players') ? 'rotate-90' : ''}`} />
<span> Players (3 connected)</span>
</button>
{expandedItems.has('players') && (
<div className="ml-8 space-y-1 mt-1">
<div className="text-gray-400"> Player_001</div>
<div className="ml-4 text-gray-500"> position: {JSON.stringify({x: 120, y: 85, z: 0})}</div>
<div className="ml-4 text-gray-500"> health: 100</div>
<div className="ml-4 text-gray-500"> inventory: [item1, item2]</div>
<div className="text-gray-400"> Player_002</div>
<div className="text-gray-400"> Player_003</div>
</div>
)}
</div>
<div>
<button
onClick={() => toggleExpand('world')}
className="flex items-center gap-1 text-gray-300 hover:text-white w-full"
>
<ChevronRight className={`w-4 h-4 transition-transform ${expandedItems.has('world') ? 'rotate-90' : ''}`} />
<span> World</span>
</button>
{expandedItems.has('world') && (
<div className="ml-8 space-y-1 mt-1">
<div className="text-gray-500"> objects: [...]</div>
<div className="text-gray-500"> weather: &quot;sunny&quot;</div>
</div>
)}
</div>
<div>
<button
onClick={() => toggleExpand('matchmaking')}
className="flex items-center gap-1 text-gray-300 hover:text-white w-full"
>
<ChevronRight className={`w-4 h-4 transition-transform ${expandedItems.has('matchmaking') ? 'rotate-90' : ''}`} />
<span> Matchmaking</span>
</button>
{expandedItems.has('matchmaking') && (
<div className="ml-8 space-y-1 mt-1">
<div className="text-gray-500"> queue: []</div>
</div>
)}
</div>
</div>
</ScrollArea>
</div>
{/* Right: Activity Feed */}
<div className="w-1/2 flex flex-col">
<div className="px-4 py-3 border-b border-gray-800">
<h3 className="font-semibold text-white">Sync Activity Feed</h3>
</div>
<ScrollArea className="flex-1">
<div className="p-4 font-mono text-xs space-y-2">
{/* Mock events */}
<div className="flex gap-2 text-blue-400">
<span className="text-gray-500">14:30:45.123</span>
<span>[RobloxAll] Player_001.position updated</span>
</div>
<div className="flex gap-2 text-gray-400">
<span className="text-gray-500">14:30:45.124</span>
<span>[Web] Ack received (12ms latency)</span>
</div>
<div className="flex gap-2 text-gray-400">
<span className="text-gray-500">14:30:45.126</span>
<span>[Mobile] Ack received (14ms latency)</span>
</div>
<div className="flex gap-2 text-gray-400">
<span className="text-gray-500">14:30:45.140</span>
<span>[Desktop] Ack received (28ms latency)</span>
</div>
<div className="flex gap-2 text-blue-400">
<span className="text-gray-500">14:30:46.001</span>
<span>[WebAll] Player_002.health changed: 10095</span>
</div>
<div className="flex gap-2 text-yellow-400">
<span className="text-gray-500">14:30:46.015</span>
<span>[Conflict] Player_001.inventory - resolving...</span>
</div>
<div className="flex gap-2 text-green-400">
<span className="text-gray-500">14:30:46.020</span>
<span>[Resolved] Server authority applied</span>
</div>
{syncEvents.map((event: any) => (
<div
key={event.id}
className={`flex gap-2 ${
event.type === 'sync' ? 'text-blue-400' :
event.type === 'ack' ? 'text-gray-400' :
event.type === 'conflict' ? 'text-yellow-400' :
'text-green-400'
}`}
>
<span className="text-gray-500">{formatTimestamp(event.timestamp)}</span>
<span>[{event.source}{event.target}] {event.variable} {event.type}</span>
</div>
))}
</div>
</ScrollArea>
{/* Bottom Stats */}
<div className="px-4 py-3 border-t border-gray-800 bg-surface">
<div className="grid grid-cols-2 gap-4 text-xs">
<div>
<div className="text-gray-400">Total syncs</div>
<div className="text-white font-semibold text-lg">1,247</div>
</div>
<div>
<div className="text-gray-400">Conflicts</div>
<div className="text-yellow-400 font-semibold text-lg">3</div>
</div>
<div>
<div className="text-gray-400">Avg latency</div>
<div className="text-green-400 font-semibold text-lg">18ms</div>
</div>
<div>
<div className="text-gray-400">Bandwidth</div>
<div className="text-cyan-400 font-semibold text-lg">2.3 KB/s</div>
</div>
</div>
</div>
</div>
</div>
);
}