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 (
);
}
if (nodes.length === 0) {
return (
);
}
return (
{nodes.map(node => )}
);
}