"use client" import { useEffect, useRef, useState } from "react" import { Archive, Clock, Loader2, LockKeyhole, RefreshCw, Trash2 } from "lucide-react" import { Badge } from "./ui/badge" import { Button } from "./ui/button" import { Checkbox } from "./ui/checkbox" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "./ui/dialog" import { useT } from "@/lib/i18n/provider" import { deleteGuestBackups, type GuestBackup } from "../lib/guest-backup-archives" export function GuestBackupList({ vmid, backups, loading, onRefresh, storageColor }: { vmid: number backups: GuestBackup[] loading: boolean onRefresh: () => Promise storageColor?: (storage: string) => { bg: string; text: string; border: string } }) { const t = useT() const [selected, setSelected] = useState([]) const [confirm, setConfirm] = useState(false) const [busy, setBusy] = useState(false) const [refreshing, setRefreshing] = useState(false) const [message, setMessage] = useState("") const [error, setError] = useState("") const mounted = useRef(true) useEffect(() => { mounted.current = true return () => { mounted.current = false } }, []) // A fresh list can remove a selection or reveal a newly protected archive. useEffect(() => { setSelected(previous => previous.filter(volid => backups.some(backup => backup.volid === volid && !backup.protected))) }, [backups]) const chosen = backups.filter(backup => selected.includes(backup.volid) && !backup.protected) const selectable = backups.filter(backup => !backup.protected) const disabled = loading || busy || refreshing const storageClass = (storage: string) => { const color = storageColor?.(storage) return color ? `${color.bg} ${color.text} ${color.border}` : "" } async function refresh() { setRefreshing(true) setError("") try { await onRefresh() } catch { if (mounted.current) setError(t("vmLxc.backups.refreshFailed")) } finally { if (mounted.current) setRefreshing(false) } } async function remove() { if (!chosen.length || busy) return setBusy(true) setError("") setMessage("") try { const results = await deleteGuestBackups(vmid, chosen) if (!mounted.current) return const deleted = results.filter(result => result.status === "deleted").length const unconfirmed = results.length - deleted setMessage(t("vmLxc.backups.deletedCount", { count: deleted })) if (unconfirmed) setError(t("vmLxc.backups.unconfirmedCount", { count: unconfirmed })) setSelected([]) } catch (error) { if (mounted.current) setError(`${t("vmLxc.backups.deleteFailed")} ${error instanceof Error ? error.message : ""}`) } finally { // A timeout can hide a successful native task. Always bypass both caches. try { await onRefresh() } catch { if (mounted.current) setError(t("vmLxc.backups.refreshFailed")) } if (mounted.current) { setBusy(false); setConfirm(false) } } } return <>
{t("vmLxc.backups.available")} {backups.length}
{message &&

{message}

} {error &&

{error}

} {loading ?
{t("vmLxc.backups.loading")}
: backups.length === 0 ?
{t("vmLxc.backups.empty")} {t("vmLxc.backups.emptyHint")}
: <>
{backups.map(backup =>