import { useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { Archive, Upload } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui"; import { backupsApi } from "@/api/backups"; import { apiErrorMessage } from "@/api/client"; function Checkbox({ checked, onChange, label, hint, }: { checked: boolean; onChange: (v: boolean) => void; label: string; hint?: string; }) { return ( ); } function Modal({ children, onClose }: { children: React.ReactNode; onClose: () => void }) { return (
e.stopPropagation()} > {children}
); } export function BackupButton({ stackId }: { stackId: string }) { const [open, setOpen] = useState(false); const [includeVolumes, setIncludeVolumes] = useState(true); const [stopFirst, setStopFirst] = useState(true); const [busy, setBusy] = useState(false); const run = async () => { setBusy(true); const tid = toast.loading("Creating backup…"); try { await backupsApi.download(stackId, { includeVolumes, stopFirst }); toast.success("Backup downloaded", { id: tid }); setOpen(false); } catch (e) { toast.error(apiErrorMessage(e), { id: tid }); } finally { setBusy(false); } }; return ( <> {open && ( !busy && setOpen(false)}>

Back up “{stackId}”

)} ); } export function RestoreButton() { const qc = useQueryClient(); const [open, setOpen] = useState(false); const [file, setFile] = useState(null); const [targetId, setTargetId] = useState(""); const [overwrite, setOverwrite] = useState(false); const [restoreVolumes, setRestoreVolumes] = useState(true); const [busy, setBusy] = useState(false); const run = async () => { if (!file) { toast.error("Select a backup file"); return; } setBusy(true); const tid = toast.loading("Restoring…"); try { const res = await backupsApi.restore(file, { targetId: targetId.trim() || undefined, overwrite, restoreVolumes, }); toast.success( `Restored '${res.stack_id}' (${res.volumes_restored} volume(s))`, { id: tid } ); qc.invalidateQueries({ queryKey: ["stacks"] }); setOpen(false); setFile(null); setTargetId(""); } catch (e) { toast.error(apiErrorMessage(e), { id: tid }); } finally { setBusy(false); } }; return ( <> {open && ( !busy && setOpen(false)}>

Restore from backup

setFile(e.target.files?.[0] ?? null)} className="block w-full text-sm text-slate-600 file:mr-3 file:rounded-lg file:border-0 file:bg-accent file:px-3 file:py-2 file:text-sm file:text-white dark:text-slate-300 dark:file:bg-accent-dark dark:file:text-slate-900" />
)} ); }