Files
Minikura/apps/web/app/dashboard/topology/page.tsx
T

75 lines
2.4 KiB
TypeScript
Raw Normal View History

2026-02-17 18:12:02 +07:00
"use client";
2026-08-13 03:29:33 +07:00
import { Network, RefreshCw } from "lucide-react";
import { Button } from "@/components/ui/button";
2026-08-13 01:58:19 +07:00
import { PageHeader, PageShell, StatePanel } from "@/components/page-layout";
2026-02-17 18:12:02 +07:00
import { TopologyCanvas } from "@/components/topology/topology-canvas";
import { useTopologyData } from "@/hooks/use-topology-data";
export default function TopologyPage() {
2026-08-13 03:29:33 +07:00
const { graph, loading, error, refreshing, refresh } = useTopologyData();
2026-02-17 18:12:02 +07:00
2026-08-13 01:58:19 +07:00
const header = (
<PageHeader
eyebrow="Network / Live Graph"
title="Topology"
description="Real-time server infrastructure, proxy connections, and Kubernetes nodes"
leading={
<div className="border border-foreground bg-primary p-3 shadow-[3px_3px_0_var(--foreground)]">
<Network className="size-6 text-primary-foreground" />
2026-02-17 18:12:02 +07:00
</div>
2026-08-13 01:58:19 +07:00
}
/>
);
2026-02-17 18:12:02 +07:00
return (
2026-08-13 01:58:19 +07:00
<PageShell>
{header}
{loading ? (
2026-08-13 03:29:33 +07:00
<StatePanel
loading
title="Loading topology..."
className="h-[70vh] sm:h-[calc(100vh-250px)]"
/>
) : error && !graph ? (
2026-08-13 01:58:19 +07:00
<StatePanel
title="Error loading topology"
description={
<>
<p>{error}</p>
<p className="mt-2 text-xs">Auto-retrying...</p>
</>
}
tone="error"
2026-08-13 03:29:33 +07:00
className="h-[70vh] sm:h-[calc(100vh-250px)]"
action={<Button onClick={() => void refresh()}>Retry now</Button>}
2026-08-13 01:58:19 +07:00
/>
) : !graph || graph.nodes.length === 0 ? (
<StatePanel
title="No infrastructure found"
description="Create a server to see it appear in the topology."
2026-08-13 03:29:33 +07:00
className="h-[70vh] sm:h-[calc(100vh-250px)]"
2026-08-13 01:58:19 +07:00
/>
) : (
2026-08-13 03:29:33 +07:00
<div className="space-y-3">
{error && (
<div className="flex flex-col gap-2 border border-destructive/40 bg-destructive/10 p-3 text-sm sm:flex-row sm:items-center sm:justify-between">
<span>Refresh failed: {error}. Showing the last successful topology.</span>
<Button
size="sm"
variant="outline"
disabled={refreshing}
onClick={() => void refresh(true)}
>
<RefreshCw className={refreshing ? "animate-spin" : undefined} />
Retry
</Button>
</div>
)}
<TopologyCanvas graph={graph} />
</div>
2026-08-13 01:58:19 +07:00
)}
</PageShell>
2026-02-17 18:12:02 +07:00
);
}