"use client" import { useEffect, useRef, useState } from "react" import { Button } from "./ui/button" import { fetchApi } from "../lib/api-config" import { useT } from "../lib/i18n/provider" export type HostUpdateJob = { id: string state: "starting" | "running" | "attention" | "finalizing" | "complete" exit_code: number | null } export function HostUpdateJobs({ open, activeId, onResume, onJobs, onSettled }: { open: boolean activeId?: string onResume: (job: HostUpdateJob) => void onJobs: (jobs: HostUpdateJob[]) => void onSettled: () => void }) { const t = useT() const [jobs, setJobs] = useState([]) const [hidden, setHidden] = useState>(new Set()) const callbacks = useRef({ onJobs, onSettled }) callbacks.current = { onJobs, onSettled } const observed = useRef(new Set()) useEffect(() => { if (!open) return let closed = false const read = async () => { try { const data = await fetchApi<{ jobs: HostUpdateJob[] }>("/api/host-update-jobs") if (closed) return const next = Array.isArray(data.jobs) ? data.jobs : [] setJobs(next) callbacks.current.onJobs(next) for (const job of next) { if (job.state === "complete" && !observed.current.has(job.id)) { observed.current.add(job.id) callbacks.current.onSettled() } } } catch { // Authentication recovery belongs to fetchApi. Never retry a start. } } void read() const timer = setInterval(() => { void read() }, 5000) return () => { closed = true; clearInterval(timer) } }, [open]) const visible = jobs.filter(job => job.id !== activeId && !(job.state === "complete" && hidden.has(job.id))) if (!visible.length) return null return
{visible.map(job =>

{t(`healthStatus.hostUpdate.${job.state === "complete" ? "finished" : job.state === "attention" ? "attention" : "running"}`)}

{job.state === "complete" && }
)}
}