import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { redirect, useNavigate, useSearchParams } from "react-router"; import { toast } from "sonner"; import { useState, useEffect } from "react"; import { deleteRepositoryMutation, doctorRepositoryMutation, getRepositoryOptions, listSnapshotsOptions, } from "~/client/api-client/@tanstack/react-query.gen"; import { Button } from "~/client/components/ui/button"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle, } from "~/client/components/ui/alert-dialog"; import { parseError } from "~/client/lib/errors"; import { getRepository } from "~/client/api-client/sdk.gen"; import type { Route } from "./+types/repository-details"; import { cn } from "~/client/lib/utils"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs"; import { RepositoryInfoTabContent } from "../tabs/info"; import { RepositorySnapshotsTabContent } from "../tabs/snapshots"; import { Loader2, Stethoscope, Trash2 } from "lucide-react"; export const handle = { breadcrumb: (match: Route.MetaArgs) => [ { label: "Repositories", href: "/repositories" }, { label: match.loaderData?.name || match.params.id }, ], }; export function meta({ params, loaderData }: Route.MetaArgs) { return [ { title: `Zerobyte - ${loaderData?.name || params.id}` }, { name: "description", content: "View repository configuration, status, and snapshots.", }, ]; } export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => { const repository = await getRepository({ path: { id: params.id ?? "" } }); if (repository.data) return repository.data; return redirect("/repositories"); }; export default function RepositoryDetailsPage({ loaderData }: Route.ComponentProps) { const [showDoctorResults, setShowDoctorResults] = useState(false); const navigate = useNavigate(); const queryClient = useQueryClient(); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [searchParams, setSearchParams] = useSearchParams(); const activeTab = searchParams.get("tab") || "info"; const { data } = useQuery({ ...getRepositoryOptions({ path: { id: loaderData.id } }), initialData: loaderData, }); useEffect(() => { queryClient.prefetchQuery(listSnapshotsOptions({ path: { id: data.id } })); }, [queryClient, data.id]); const deleteRepo = useMutation({ ...deleteRepositoryMutation(), onSuccess: () => { toast.success("Repository deleted successfully"); navigate("/repositories"); }, onError: (error) => { toast.error("Failed to delete repository", { description: parseError(error)?.message, }); }, }); const doctorMutation = useMutation({ ...doctorRepositoryMutation(), onSuccess: (data) => { if (data) { setShowDoctorResults(true); if (data.success) { toast.success("Repository doctor completed successfully"); } else { toast.warning("Doctor completed with some issues", { description: "Check the details for more information", richColors: true, }); } } }, onError: (error) => { toast.error("Failed to run doctor", { description: parseError(error)?.message, }); }, }); const handleConfirmDelete = () => { setShowDeleteConfirm(false); deleteRepo.mutate({ path: { id: data.id } }); }; const getStepLabel = (step: string) => { switch (step) { case "unlock": return "Unlock Repository"; case "check": return "Check Repository"; case "repair_index": return "Repair Index"; case "recheck": return "Re-check Repository"; default: return step; } }; return ( <>
{data.status || "unknown"} {data.type}
setSearchParams({ tab: value })}> Configuration Snapshots Delete repository? Are you sure you want to delete the repository {data.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
Doctor results Repository doctor operation completed {doctorMutation.data && (
{doctorMutation.data.steps.map((step) => (
{getStepLabel(step.step)} {step.success ? "Success" : "Warning"}
{step.error &&

{step.error}

}
))}
)}
); }