import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { useState } from "react"; import { toast } from "sonner"; import { Activity, ChevronDown, HardDrive, HeartIcon, Pencil, Plug, Trash2, Unplug } from "lucide-react"; import { deleteVolumeMutation, getVolumeOptions, healthCheckVolumeMutation, mountVolumeMutation, unmountVolumeMutation, updateVolumeMutation, } from "~/client/api-client/@tanstack/react-query.gen"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "~/client/components/ui/alert-dialog"; import { Badge } from "~/client/components/ui/badge"; import { Button } from "~/client/components/ui/button"; import { Card } from "~/client/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "~/client/components/ui/dropdown-menu"; import { Separator } from "~/client/components/ui/separator"; import { Switch } from "~/client/components/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs"; import { ManagedBadge } from "~/client/components/managed-badge"; import { parseError } from "~/client/lib/errors"; import { cn } from "~/client/lib/utils"; import { VolumeInfoTabContent } from "../tabs/info"; import { FilesTabContent } from "../tabs/files"; import { useTimeFormat } from "~/client/lib/datetime"; export function VolumeDetails({ volumeId }: { volumeId: string }) { const navigate = useNavigate(); const searchParams = useSearch({ from: "/(dashboard)/volumes/$volumeId/" }); const activeTab = searchParams.tab || "info"; const { formatDateTime, formatTimeAgo } = useTimeFormat(); const { data } = useSuspenseQuery({ ...getVolumeOptions({ path: { shortId: volumeId } }), }); const { volume, statfs } = data; const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const mountVol = useMutation({ ...mountVolumeMutation(), }); const unmountVol = useMutation({ ...unmountVolumeMutation(), }); const deleteVol = useMutation({ ...deleteVolumeMutation(), onSuccess: () => { toast.success("Volume deleted successfully"); void navigate({ to: "/volumes" }); }, onError: (error) => { toast.error("Failed to delete volume", { description: parseError(error)?.message, }); }, }); const healthcheck = useMutation({ ...healthCheckVolumeMutation(), onSuccess: (d) => { if (d.error) { toast.error("Health check failed", { description: d.error }); return; } toast.success("Health check completed", { description: "The volume is healthy." }); }, onError: (error) => { toast.error("Health check failed", { description: error.message }); }, }); const toggleAutoRemount = useMutation({ ...updateVolumeMutation(), onSuccess: (d) => { toast.success("Volume updated", { description: `Auto remount is now ${d.autoRemount ? "enabled" : "paused"}.`, }); }, onError: (error) => { toast.error("Update failed", { description: error.message }); }, }); const handleConfirmDelete = () => { setShowDeleteConfirm(false); deleteVol.mutate({ path: { shortId: volume.shortId } }); }; const isMounted = volume.status === "mounted"; const isError = volume.status === "error"; return ( <>
Created {formatDateTime(volume.createdAt)}
Last Error
{volume.lastError}