import { Check, 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 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 { toast } from "sonner"; import { handleRepositoryError } from "~/client/lib/errors"; import { formatShortDateTime, formatTimeAgo } from "~/client/lib/datetime"; import { Link } from "@tanstack/react-router"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/client/components/ui/collapsible"; import { cn } from "~/client/lib/utils"; type Props = { schedule: BackupSchedule; handleToggleEnabled: (enabled: boolean) => void; handleRunBackupNow: () => void; handleStopBackup: () => void; handleDeleteSchedule: () => void; setIsEditMode: (isEdit: boolean) => void; }; export const ScheduleSummary = (props: Props) => { const { schedule, handleToggleEnabled, handleRunBackupNow, handleStopBackup, handleDeleteSchedule, setIsEditMode } = props; 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(), onSuccess: () => { toast.success("Retention policy applied successfully"); }, onError: (error) => { handleRepositoryError("Failed to apply retention policy", error, schedule.repository.shortId); }, }); const summary = useMemo(() => { const scheduleLabel = schedule ? schedule.cronExpression : "-"; 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); runForget.mutate({ path: { shortId: schedule.shortId } }); }; const handleConfirmStop = () => { setShowStopConfirm(false); if (schedule.lastBackupStatus !== "in_progress") return; handleStopBackup(); }; return (
{schedule.name} {schedule.volume.name} {schedule.repository.name}
{schedule.lastBackupStatus === "in_progress" ? ( ) : ( )} {schedule.retentionPolicy && ( )}

Schedule

{summary.scheduleLabel}

Repository

{schedule.repository.name}

Last backup

{formatTimeAgo(schedule.lastBackupAt)}

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.lastBackupStatus === "warning" || schedule.lastBackupStatus === "error") && (
{schedule.lastBackupStatus === "warning" ? "Warning details" : "Error details"}

{schedule.lastBackupError ?? "No additional details available. check your container logs for more information."}

)}
{schedule.lastBackupStatus === "in_progress" && ( )} Delete backup schedule? Are you sure you want to delete this backup schedule for {schedule.volume.name}? This action cannot be undone. Existing snapshots will not be deleted.
Cancel Delete schedule
Run retention policy cleanup? This will apply the retention policy and permanently delete old snapshots according to the configured rules ({summary.retentionLabel}). This action cannot be undone.
Cancel Run cleanup
Stop running backup? Are you sure you want to stop the current backup for {schedule.name}?
Cancel Stop backup
); };