import { Check, ChevronDown, Database, Eraser, HardDrive, Pencil, Play, Square, Trash2, X } from "lucide-react"; import { useMemo, useState } from "react"; import { OnOff } from "~/client/components/onoff"; import { Button } from "~/client/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle, } from "~/client/components/ui/alert-dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "~/client/components/ui/dropdown-menu"; import type { BackupSchedule } from "~/client/lib/types"; import { BackupProgressCard } from "./backup-progress-card"; import { getBackupProgressOptions, runForgetMutation } from "~/client/api-client/@tanstack/react-query.gen"; import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import { Link, useNavigate } from "@tanstack/react-router"; import { toast } from "sonner"; import { handleRepositoryError } from "~/client/lib/errors"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/client/components/ui/collapsible"; import { TimeAgo } from "~/client/components/time-ago"; import { useTimeFormat } from "~/client/lib/datetime"; import { cn } from "~/client/lib/utils"; type Props = { schedule: BackupSchedule; handleToggleEnabled: (enabled: boolean) => void; handleRunBackupNow: () => void; handleStopBackup: () => void; handleDeleteSchedule: () => void; }; export const ScheduleSummary = (props: Props) => { const { schedule, handleToggleEnabled, handleRunBackupNow, handleStopBackup, handleDeleteSchedule } = props; const { formatShortDateTime } = useTimeFormat(); const navigate = useNavigate(); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [showForgetConfirm, setShowForgetConfirm] = useState(false); const [showStopConfirm, setShowStopConfirm] = useState(false); const { data: initialProgress } = useSuspenseQuery({ ...getBackupProgressOptions({ path: { shortId: schedule.shortId } }), }); const runForget = useMutation({ ...runForgetMutation(), onError: (error) => { handleRepositoryError("Failed to apply retention policy", error, schedule.repository.shortId); }, }); const summary = useMemo(() => { const scheduleLabel = schedule ? schedule.cronExpression || "Manual only" : "-"; const retentionParts: string[] = []; if (schedule?.retentionPolicy) { const rp = schedule.retentionPolicy; if (rp.keepLast) retentionParts.push(`${rp.keepLast} last`); if (rp.keepHourly) retentionParts.push(`${rp.keepHourly} hourly`); if (rp.keepDaily) retentionParts.push(`${rp.keepDaily} daily`); if (rp.keepWeekly) retentionParts.push(`${rp.keepWeekly} weekly`); if (rp.keepMonthly) retentionParts.push(`${rp.keepMonthly} monthly`); if (rp.keepYearly) retentionParts.push(`${rp.keepYearly} yearly`); } return { vol: schedule.volume.name, scheduleLabel, repositoryLabel: schedule.repositoryId || "No repository selected", retentionLabel: retentionParts.length > 0 ? retentionParts.join(" • ") : "No retention policy", }; }, [schedule]); const handleConfirmDelete = () => { setShowDeleteConfirm(false); handleDeleteSchedule(); }; const handleConfirmForget = () => { setShowForgetConfirm(false); toast.promise(runForget.mutateAsync({ path: { shortId: schedule.shortId } }), { loading: "Running cleanup...", success: "Retention policy applied successfully", }); }; const handleConfirmStop = () => { setShowStopConfirm(false); if (schedule.lastBackupStatus !== "in_progress") return; handleStopBackup(); }; return (
Schedule
{summary.scheduleLabel}
Repository
{schedule.repository.name}
Last backup
Next backup
{formatShortDateTime(schedule.nextBackupAt)}
Status
{schedule.lastBackupStatus === "success" && "✓ Success"} {schedule.lastBackupStatus === "error" && "✗ Error"} {schedule.lastBackupStatus === "in_progress" && "⟳ in progress..."} {schedule.lastBackupStatus === "warning" && "! Warning"} {!schedule.lastBackupStatus && "—"}
{schedule.lastBackupError ?? "No additional details available. check your container logs for more information."}