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 { runForgetMutation } from "~/client/api-client/@tanstack/react-query.gen"; import { useMutation } 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"; 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 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
{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 && "—"}
Warning Details
{schedule.lastBackupError ?? "Last backup completed with warnings. Check your container logs for more details."}
Error details
{schedule.lastBackupError}