import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { Play, Square, RotateCw, ChevronDown, ChevronRight } from "lucide-react"; import { toast } from "sonner"; import { Badge, Button, Card, Spinner, StatusDot } from "@/components/ui"; import { ContainerPorts } from "@/components/stacks/ContainerPorts"; import { containersApi, type ContainerAction } from "@/api/containers"; import { apiErrorMessage } from "@/api/client"; import type { ContainerInfo } from "@/types"; export function ContainerCard({ container, agentId, host, isAdmin, onChanged, }: { container: ContainerInfo; agentId?: number; host?: string; isAdmin: boolean; onChanged?: () => void; }) { const [open, setOpen] = useState(false); const [busy, setBusy] = useState(false); const running = container.state === "running"; const detail = useQuery({ queryKey: ["container", agentId ?? "local", container.id], queryFn: () => containersApi.inspect(container.id, agentId), enabled: open, }); const act = async (action: ContainerAction) => { setBusy(true); const t = toast.loading(`${action} ${container.service}…`); try { await containersApi.action(container.id, action, agentId); toast.success(`${container.service}: ${action} ok`, { id: t }); onChanged?.(); if (open) detail.refetch(); } catch (e) { toast.error(apiErrorMessage(e), { id: t }); } finally { setBusy(false); } }; return (
{container.health && {container.health}} {container.status} {isAdmin && (
)}
{open && (
{detail.isLoading ? ( ) : detail.data ? (
{detail.data.name} {detail.data.id.slice(0, 12)} {detail.data.state} {detail.data.exit_code != null && detail.data.state !== "running" ? ` (exit ${detail.data.exit_code})` : ""} {detail.data.restart_count} {detail.data.started_at && ( {new Date(detail.data.started_at).toLocaleString()} )} {detail.data.networks.length > 0 && ( {detail.data.networks.join(", ")} )} {detail.data.mounts.length > 0 && (

Mounts

    {detail.data.mounts.map((m, i) => (
  • {m.source} → {m.destination} {m.rw ? "(rw)" : "(ro)"}
  • ))}
)} {detail.data.env.length > 0 && (

Environment

                    {detail.data.env.join("\n")}
                  
)}
) : (

{apiErrorMessage(detail.error)}

)}
)}
); } function Field({ label, children }: { label: string; children: React.ReactNode }) { return (
{label} {children}
); }