- {history.map((line, i) =>
{line}
)}
+
inputRef.current?.focus()}>
+ {history.map((line, i) => (
+
+ {line}
+
+ ))}
{isLoading &&
Processing...
}
-
);
@@ -1232,10 +1555,759 @@ function SettingsApp({ wallpaper, setWallpaper, soundEnabled, setSoundEnabled }:
+
+
+
Network Map
+
+
+
+
+
+
+
+
+
+
+
+ {nodes.map((node: any, i: number) => {
+ const angle = (i / nodes.length) * 2 * Math.PI - Math.PI / 2;
+ const radius = 140;
+ const x = Math.cos(angle) * radius;
+ const y = Math.sin(angle) * radius;
+ return (
+
+
+
+
+
+
{node.username}
+
Lv.{node.level}
+
+
+ );
+ })}
+
+
+
+ {nodes.length} nodes connected
+
+
+ );
+}
+
+function MetricsDashboardApp() {
+ const { data: metrics, isLoading } = useQuery({
+ queryKey: ['os-dashboard-metrics'],
+ queryFn: async () => {
+ const res = await fetch('/api/metrics');
+ return res.json();
+ },
+ refetchInterval: 30000,
+ });
+
+ const [animatedValues, setAnimatedValues] = useState({ profiles: 0, projects: 0, xp: 0 });
+
+ useEffect(() => {
+ if (metrics) {
+ const duration = 1000;
+ const steps = 20;
+ const interval = duration / steps;
+ let step = 0;
+ const timer = setInterval(() => {
+ step++;
+ const progress = step / steps;
+ setAnimatedValues({
+ profiles: Math.round(progress * (metrics.totalProfiles || 0)),
+ projects: Math.round(progress * (metrics.totalProjects || 0)),
+ xp: Math.round(progress * (metrics.totalXP || 0)),
+ });
+ if (step >= steps) clearInterval(timer);
+ }, interval);
+ return () => clearInterval(timer);
+ }
+ }, [metrics]);
+
+ if (isLoading) {
+ return (
+