import { useMutation } from "@tanstack/react-query"; import { useState } from "react"; import { toast } from "sonner"; import { Pencil, Square, Stethoscope, Trash2, Unlock } from "lucide-react"; import { Card, CardContent, CardTitle } from "~/client/components/ui/card"; import { Button } from "~/client/components/ui/button"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle, } from "~/client/components/ui/alert-dialog"; import type { Repository } from "~/client/lib/types"; import type { GetRepositoryStatsResponse } from "~/client/api-client/types.gen"; import { formatDateTime, formatTimeAgo } from "~/client/lib/datetime"; import { cancelDoctorMutation, deleteRepositoryMutation, startDoctorMutation, unlockRepositoryMutation, } from "~/client/api-client/@tanstack/react-query.gen"; import type { RepositoryConfig } from "@zerobyte/core/restic"; import { DoctorReport } from "../components/doctor-report"; import { parseError } from "~/client/lib/errors"; import { useNavigate } from "@tanstack/react-router"; import { CompressionStatsChart } from "../components/compression-stats-chart"; import { cn } from "~/client/lib/utils"; import { ManagedBadge } from "~/client/components/managed-badge"; type Props = { repository: Repository; initialStats?: GetRepositoryStatsResponse; }; const getEffectiveLocalPath = (repository: Repository): string | null => { if (repository.config.backend !== "local") return null; return repository.config.path; }; export const RepositoryInfoTabContent = ({ repository, initialStats }: Props) => { const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const navigate = useNavigate(); const effectiveLocalPath = getEffectiveLocalPath(repository); 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(), onSuccess: () => { toast.success("Repository unlocked successfully"); }, onError: (error) => { toast.error("Failed to unlock repository", { description: parseError(error)?.message, }); }, }); const handleConfirmDelete = () => { setShowDeleteConfirm(false); deleteRepo.mutate({ path: { shortId: repository.shortId } }); }; const config = repository.config as RepositoryConfig; const isDoctorRunning = repository.status === "doctor"; const hasLocalPath = Boolean(effectiveLocalPath); const hasCaCert = Boolean(config.cacert); const hasLastError = Boolean(repository.lastError); const hasInsecureTlsConfig = config.insecureTls !== undefined; const isTlsValidationDisabled = config.insecureTls === true; return ( <>
{repository.name}
{repository.type}
{repository.provisioningId ? "Provisioned" : "Manual"}
{repository.compressionMode || "off"}
{formatDateTime(repository.createdAt)}
{repository.status || "Unknown"}
{formatTimeAgo(repository.lastChecked)}
{effectiveLocalPath}
Configured
Disabled Enabled
Last Error
{repository.lastError}
{JSON.stringify(repository.config, null, 2)}