import { useState, useEffect, useCallback } from 'react'; import { apiFetch } from '@/lib/api'; import { formatCount } from '@/lib/utils'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Bell, Zap, Shield, HardDrive, WifiOff, CheckCircle2, } from 'lucide-react'; import { useLicense } from '@/context/LicenseContext'; import type { ConfigurationStatusPayload } from '@/components/dashboard'; interface FleetNodeConfiguration { id: number; name: string; type: 'local' | 'remote'; status: 'online' | 'offline'; configuration: ConfigurationStatusPayload | null; } function SummaryRow({ icon: Icon, label, value }: { icon: typeof Bell; label: string; value: string; }) { return (
{label} {value}
); } function NodeCard({ node, isPaid }: { node: FleetNodeConfiguration; isPaid: boolean }) { const isRemote = node.type === 'remote'; if (!node.configuration) { return (
{node.name} {isRemote ? 'Remote' : 'Local'} Offline

Node is unreachable. Configuration unavailable.

); } const { notifications, automation, security, backup, thresholds } = node.configuration; const agentCount = [ notifications.agents.discord.enabled, notifications.agents.slack.enabled, notifications.agents.webhook.enabled, ].filter(Boolean).length; return (
{node.name} {isRemote ? 'Remote' : 'Local'}
Online
{isPaid && ( )} {!automation.webhooks.locked && ( )} {!isRemote && ( )} {!security.scanPolicies.locked && ( )} {!isRemote && !backup.locked && ( )}
); } export function FleetConfiguration() { const { isPaid } = useLicense(); const [nodes, setNodes] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { const res = await apiFetch('/fleet/configuration', { localOnly: true }); if (!res.ok) { setError('Failed to fetch fleet configuration.'); return; } const data = await res.json() as FleetNodeConfiguration[]; setNodes(data); setError(null); } catch { setError('Unable to reach the server.'); } finally { setLoading(false); } }, []); useEffect(() => { void fetchData(); }, [fetchData]); if (loading) { return (
{Array.from({ length: 2 }).map((_, i) => (
{Array.from({ length: 4 }).map((_, j) => (
))} ))}
); } if (error) { return (

{error}

); } if (nodes.length === 0) { return (

No nodes configured.

); } return (
{nodes.map(node => )}
); }