import React, { useEffect, useState, useCallback } from "react";
import { Server, Box, Globe, Layers, AlertCircle, RefreshCw } from "lucide-react";
import {
listNodesCmd,
listPodsCmd,
listDeploymentsCmd,
listNamespacesCmd,
} from "@/lib/tauriCommands";
import type { NodeInfo, PodInfo, DeploymentInfo, NamespaceInfo } from "@/lib/tauriCommands";
interface ClusterOverviewProps {
clusterId: string;
}
interface SummaryCardProps {
title: string;
value: number;
subtitle?: string;
icon: React.ReactNode;
testId: string;
subtitleTestId?: string;
}
function SummaryCard({ title, value, subtitle, icon, testId, subtitleTestId }: SummaryCardProps) {
return (
{title}
{icon}
{value}
{subtitle && (
{subtitle}
)}
);
}
function nodeIsReady(node: NodeInfo): boolean {
return node.status === "Ready";
}
export function ClusterOverview({ clusterId }: ClusterOverviewProps) {
const [nodes, setNodes] = useState([]);
const [pods, setPods] = useState([]);
const [deployments, setDeployments] = useState([]);
const [namespaces, setNamespaces] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const loadData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const [nodesData, podsData, deploymentsData, namespacesData] = await Promise.all([
listNodesCmd(clusterId),
listPodsCmd(clusterId, ""),
listDeploymentsCmd(clusterId, ""),
listNamespacesCmd(clusterId),
]);
setNodes(nodesData);
setPods(podsData);
setDeployments(deploymentsData);
setNamespaces(namespacesData);
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
} finally {
setLoading(false);
}
}, [clusterId]);
useEffect(() => {
void loadData();
}, [loadData]);
if (loading) {
return (
Loading cluster overview…
);
}
if (error) {
return (
Failed to load cluster data
{error}
);
}
const readyNodeCount = nodes.filter(nodeIsReady).length;
const runningPodCount = pods.filter((p) => p.status === "Running").length;
return (
Cluster Overview
Cluster ID: {clusterId}
{/* Summary cards */}
}
testId="node-count"
subtitleTestId="node-ready-status"
/>
}
testId="pod-count"
/>
}
testId="deployment-count"
/>
}
testId="namespace-count"
/>
{/* Node table */}
Nodes
{nodes.length === 0 ? (
No nodes found
) : (
| Name |
Status |
Roles |
Version |
Age |
{nodes.map((node) => (
| {node.name} |
{node.status}
|
{node.roles || "—"} |
{node.version} |
{node.age} |
))}
)}
{/* Info note */}
Events are available in the Cluster → Events section.
);
}