import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import { useState } from "react"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { toast } from "sonner"; import { ChevronDown, Database, Pencil, Square, Stethoscope, Trash2, Unlock } from "lucide-react"; import { cancelDoctorMutation, deleteRepositoryMutation, getRepositoryOptions, startDoctorMutation, unlockRepositoryMutation, } from "~/client/api-client/@tanstack/react-query.gen"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, 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 { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs"; import { parseError } from "~/client/lib/errors"; import { cn } from "~/client/lib/utils"; import type { BackupSchedule, Snapshot } from "~/client/lib/types"; import type { GetRepositoryStatsResponse } from "~/client/api-client/types.gen"; import { RepositoryInfoTabContent } from "../tabs/info"; import { RepositorySnapshotsTabContent } from "../tabs/snapshots"; import { useTimeFormat } from "~/client/lib/datetime"; export default function RepositoryDetailsPage({ repositoryId, initialSnapshots, initialBackupSchedules, initialStats, }: { repositoryId: string; initialSnapshots?: Snapshot[]; initialBackupSchedules?: BackupSchedule[]; initialStats?: GetRepositoryStatsResponse; }) { const { formatDateTime, formatTimeAgo } = useTimeFormat(); const navigate = useNavigate(); const { tab } = useSearch({ from: "/(dashboard)/repositories/$repositoryId/" }); const activeTab = tab || "info"; const { data: repository } = useSuspenseQuery({ ...getRepositoryOptions({ path: { shortId: repositoryId } }), }); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const deleteRepo = useMutation({ ...deleteRepositoryMutation(), onSuccess: () => { toast.success("Repository deleted successfully"); void navigate({ to: "/repositories" }); }, onError: (error) => { toast.error("Failed to delete repository", { description: parseError(error)?.message, }); }, }); const startDoctor = useMutation({ ...startDoctorMutation(), onError: (error) => { toast.error("Failed to start doctor", { description: parseError(error)?.message, }); }, }); const cancelDoctor = useMutation({ ...cancelDoctorMutation(), onSuccess: () => { toast.info("Doctor operation cancelled"); }, onError: (error) => { toast.error("Failed to cancel doctor", { description: parseError(error)?.message, }); }, }); const unlockRepo = useMutation({ ...unlockRepositoryMutation(), }); const handleConfirmDelete = () => { setShowDeleteConfirm(false); deleteRepo.mutate({ path: { shortId: repository.shortId } }); }; const isDoctorRunning = repository.status === "doctor"; return ( <>

{repository.name}

{repository.status || "Unknown"} {repository.type} {repository.provisioningId && Managed}

Created {formatDateTime(repository.createdAt)} · Last checked  {formatTimeAgo(repository.lastChecked)}

{isDoctorRunning ? ( ) : ( )} navigate({ to: `/repositories/${repository.shortId}/edit` })}> Edit toast.promise(unlockRepo.mutateAsync({ path: { shortId: repository.shortId } }), { loading: "Unlocking repo", success: "Repository unlocked successfully", error: (e) => toast.error("Failed to unlock repository", { description: parseError(e)?.message, }), }) } disabled={unlockRepo.isPending} > Unlock setShowDeleteConfirm(true)} disabled={deleteRepo.isPending} > Delete
{repository.lastError && (

Last Error

{repository.lastError}

)} navigate({ to: ".", search: () => ({ tab: value }) })}> Configuration Snapshots
Delete repository? Are you sure you want to delete the repository {repository.name}? This will not remove the actual data from the backend storage, only the repository configuration will be deleted.

All backup schedules associated with this repository will also be removed.
Cancel Delete repository
); }