import { useState } from 'react'; import { ChevronDown, ChevronRight, Layers, ExternalLink, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { apiFetch } from '@/lib/api'; import { toast } from '@/components/ui/toast-store'; import { LabelDot } from '../LabelPill'; import type { Label as StackLabel } from '../label-types'; interface StackContainer { Id?: string; Names?: string[]; Image?: string; State?: string; Status?: string; } function containerName(c: StackContainer): string { if (c.Names && c.Names.length > 0) { return c.Names[0].replace(/^\//, ''); } return c.Id?.slice(0, 12) ?? 'unknown'; } function ContainerRow({ container, onNavigate }: { container: StackContainer; onNavigate: () => void; }) { const name = containerName(container); const state = container.State?.toLowerCase() ?? 'unknown'; const image = container.Image; const status = container.Status ?? ''; const stateColor = state === 'running' ? 'bg-success' : state === 'restarting' ? 'bg-warning' : 'bg-destructive'; return (
{name} {state}
{(image || status) && (
{image && {image}} {status && {image ? 'ยท ' : ''}{status}}
)}
); } export function StackSection({ stackName, nodeId, onNavigate, labelMap }: { stackName: string; nodeId: number; onNavigate: (nodeId: number, stackName: string) => void; labelMap?: Record; }) { const [expanded, setExpanded] = useState(false); const [containers, setContainers] = useState(null); const [loading, setLoading] = useState(false); const handleExpand = async () => { if (loading) return; const next = !expanded; setExpanded(next); if (next && containers === null) { setLoading(true); try { const res = await apiFetch(`/fleet/node/${nodeId}/stacks/${encodeURIComponent(stackName)}/containers`, { localOnly: true }); if (res.ok) { setContainers(await res.json()); } else { toast.error('Failed to load containers for ' + stackName); } } catch (error) { console.error('Failed to load containers for', stackName, error); toast.error('Failed to load containers for ' + stackName); setExpanded(false); } finally { setLoading(false); } } }; const runningCount = containers?.filter(c => c.State?.toLowerCase() === 'running').length ?? 0; const totalCount = containers?.length ?? 0; return (
{expanded && (
{loading ? (
) : containers && containers.length > 0 ? ( containers.map(c => ( onNavigate(nodeId, stackName)} /> )) ) : (

No containers

)}
)}
); }