import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Radio, CheckCircle2 } from 'lucide-react'; import { formatRelativeTime } from '@/lib/utils'; import { useFleetHeartbeat } from './useFleetHeartbeat'; import { useNodes } from '@/context/NodeContext'; import type { FleetNodeOverview } from './useFleetHeartbeat'; import type { Node } from '@/context/NodeContext'; function StatusDot({ status }: { status: 'online' | 'offline' | 'unknown' }) { const colorClass = status === 'online' ? 'bg-success' : status === 'unknown' ? 'bg-warning' : 'bg-destructive'; return ( ); } function getLatencyLabel(node: FleetNodeOverview, isPilot: boolean): string | null { if (node.type === 'local') return null; if (isPilot) return 'n/a'; if (node.status === 'online' && node.latency_ms !== undefined) return `${node.latency_ms} ms`; return null; } function getLastSeenLabel(node: FleetNodeOverview): string | null { if (node.status === 'online') return null; // Pilot-agent nodes use the tunnel heartbeat timestamp if (node.mode === 'pilot_agent') { if (node.pilot_last_seen) return formatRelativeTime(node.pilot_last_seen); return 'never reached'; } // Proxy nodes use the contact timestamp updated by the fleet overview handler const contact = node.last_successful_contact; if (!contact) return 'never reached'; return formatRelativeTime(contact); } function SkeletonRow() { return (
Unable to load fleet status.