import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { RefreshCw, ArrowUpCircle, CheckCircle2, HelpCircle } from "lucide-react"; import { toast } from "sonner"; import { Button, Card, Spinner } from "@/components/ui"; import { HostHeader } from "@/components/hosts/HostHeader"; import { imagesApi, type ImageRow } from "@/api/images"; import { agentsApi } from "@/api/agents"; import { apiErrorMessage } from "@/api/client"; import { formatBytes, relativeTime } from "@/lib/utils"; import { useAuthStore } from "@/store/auth"; import type { Agent } from "@/types"; function UpdateBadge({ row }: { row: ImageRow }) { const u = row.update; if (!u) return not checked; if (u.error) return ⚠ {u.error}; if (u.update_available) return ( update available ); return ( up to date ); } export function Images() { const isAdmin = useAuthStore((s) => s.user?.role === "admin"); const agents = useQuery({ queryKey: ["agents"], queryFn: () => agentsApi.list(), refetchInterval: 15000, }); const hasAgents = (agents.data?.length ?? 0) > 0; return (
{agents.data?.map((agent) => ( ))}
); } function ImagesSection({ agent, isAdmin, showHostLabel, }: { agent?: Agent; isAdmin: boolean; showHostLabel: boolean; }) { const agentId = agent?.id; const online = !agent || agent.status === "online"; const qc = useQueryClient(); const [checking, setChecking] = useState(false); const { data, isLoading } = useQuery({ queryKey: ["images", agentId ?? "local"], queryFn: () => imagesApi.list(agentId), enabled: online, }); const check = async () => { setChecking(true); const t = toast.loading("Checking for updates…"); try { await imagesApi.check(agentId); await qc.invalidateQueries({ queryKey: ["images", agentId ?? "local"] }); toast.success("Update check complete", { id: t }); } catch (e) { toast.error(apiErrorMessage(e), { id: t }); } finally { setChecking(false); } }; return (
{(showHostLabel || (isAdmin && online)) && ( {isAdmin && online && ( )} )} {!online ? (

Host is {agent?.status}. Check it under Settings → Remote hosts.

) : isLoading ? ( ) : ( {data?.map((row) => ( ))} {data?.length === 0 && ( )}
Image Used by Size Created Status
{row.tag} {row.stacks.length ? row.stacks.join(", ") : "—"} {formatBytes(row.size)} {row.created ? relativeTime(row.created) : "—"}
No images.
)}
); }