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"
/>
)}
>
);
}