import { useMutation, useQuery } from "@tanstack/react-query"; import { redirect, useParams } from "react-router"; import { toast } from "sonner"; import { listSnapshotFilesOptions, restoreSnapshotMutation } from "~/client/api-client/@tanstack/react-query.gen"; import { Button } from "~/client/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "~/client/components/ui/card"; import { RestoreSnapshotDialog, type RestoreSnapshotOptions, } from "~/client/components/restore-snapshot-dialog"; import { SnapshotFileBrowser } from "~/client/modules/backups/components/snapshot-file-browser"; import { getSnapshotDetails } from "~/client/api-client"; import type { Route } from "./+types/snapshot-details"; export const handle = { breadcrumb: (match: Route.MetaArgs) => [ { label: "Repositories", href: "/repositories" }, { label: match.params.name, href: `/repositories/${match.params.name}` }, { label: match.params.snapshotId }, ], }; export function meta({ params }: Route.MetaArgs) { return [ { title: `Zerobyte - Snapshot ${params.snapshotId}` }, { name: "description", content: "Browse and restore files from a backup snapshot.", }, ]; } export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => { const snapshot = await getSnapshotDetails({ path: { name: params.name, snapshotId: params.snapshotId }, }); if (snapshot.data) return snapshot.data; return redirect("/repositories"); }; export default function SnapshotDetailsPage({ loaderData }: Route.ComponentProps) { const { name, snapshotId } = useParams<{ name: string; snapshotId: string; }>(); const { data } = useQuery({ ...listSnapshotFilesOptions({ path: { name: name ?? "", snapshotId: snapshotId ?? "" }, query: { path: "/" }, }), enabled: !!name && !!snapshotId, }); const { mutate: restoreSnapshot, isPending: isRestoring } = useMutation({ ...restoreSnapshotMutation(), onSuccess: (data) => { toast.success("Restore completed", { description: `Successfully restored ${data.filesRestored} file(s). ${data.filesSkipped} file(s) skipped.`, }); }, onError: (error) => { toast.error("Restore failed", { description: error.message || "Failed to restore snapshot" }); }, }); const handleRestore = (options: RestoreSnapshotOptions) => { if (!name || !snapshotId) return; restoreSnapshot({ path: { name }, body: { snapshotId, include: options.include, delete: options.delete, excludeXattr: options.excludeXattr, targetPath: options.targetPath, overwrite: options.overwrite, }, }); }; if (!name || !snapshotId) { return (

Invalid snapshot reference

); } return (

{name}

Snapshot: {snapshotId}

{isRestoring ? "Restoring..." : "Restore Snapshot"} } />
{data?.snapshot && ( Snapshot Information
Snapshot ID:

{data.snapshot.id}

Short ID:

{data.snapshot.short_id}

Hostname:

{data.snapshot.hostname}

Time:

{new Date(data.snapshot.time).toLocaleString()}

Paths:
{data.snapshot.paths.map((path) => (

{path}

))}
)}
); }