diff --git a/apps/client/app/modules/backups/components/schedule-summary.tsx b/apps/client/app/modules/backups/components/schedule-summary.tsx
index ad41b49..d0899e9 100644
--- a/apps/client/app/modules/backups/components/schedule-summary.tsx
+++ b/apps/client/app/modules/backups/components/schedule-summary.tsx
@@ -1,12 +1,21 @@
import { useQuery } from "@tanstack/react-query";
-import { Database, Pencil, Play } from "lucide-react";
-import { useMemo } from "react";
+import { Database, Pencil, Play, Trash2 } from "lucide-react";
+import { useMemo, useState } from "react";
import { listSnapshotsOptions } from "~/api-client/@tanstack/react-query.gen";
import { ByteSize } from "~/components/bytes-size";
import { OnOff } from "~/components/onoff";
import { SnapshotsTable } from "~/components/snapshots-table";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "~/components/ui/alert-dialog";
import type { BackupSchedule, Repository, Volume } from "~/lib/types";
type Props = {
@@ -15,11 +24,23 @@ type Props = {
repository: Repository;
handleToggleEnabled: (enabled: boolean) => void;
handleRunBackupNow: () => void;
+ handleDeleteSchedule: () => void;
setIsEditMode: (isEdit: boolean) => void;
+ isDeleting?: boolean;
};
export const ScheduleSummary = (props: Props) => {
- const { volume, schedule, repository, handleToggleEnabled, handleRunBackupNow, setIsEditMode } = props;
+ const {
+ volume,
+ schedule,
+ repository,
+ handleToggleEnabled,
+ handleRunBackupNow,
+ handleDeleteSchedule,
+ setIsEditMode,
+ isDeleting,
+ } = props;
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const { data: snapshots, isLoading: loadingSnapshots } = useQuery({
...listSnapshotsOptions({
@@ -52,6 +73,11 @@ export const ScheduleSummary = (props: Props) => {
};
}, [schedule, volume.name]);
+ const handleConfirmDelete = () => {
+ setShowDeleteConfirm(false);
+ handleDeleteSchedule();
+ };
+
return (
@@ -72,6 +98,16 @@ export const ScheduleSummary = (props: Props) => {
Edit schedule
+ setShowDeleteConfirm(true)}
+ disabled={isDeleting}
+ className="text-destructive hover:text-destructive"
+ >
+
+ Delete
+
@@ -107,6 +143,27 @@ export const ScheduleSummary = (props: Props) => {
+
+
+
+ Delete backup schedule?
+
+ Are you sure you want to delete this backup schedule for {volume.name} ? This action
+ cannot be undone. Existing snapshots will not be deleted.
+
+
+
+
Cancel
+
+ Delete schedule
+
+
+
+
+
diff --git a/apps/client/app/modules/backups/routes/backup-details.tsx b/apps/client/app/modules/backups/routes/backup-details.tsx
index 182c7a0..f610409 100644
--- a/apps/client/app/modules/backups/routes/backup-details.tsx
+++ b/apps/client/app/modules/backups/routes/backup-details.tsx
@@ -1,6 +1,6 @@
import { useId, useState } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
-import { Link, useParams } from "react-router";
+import { Link, useParams, useNavigate } from "react-router";
import { toast } from "sonner";
import { Button } from "~/components/ui/button";
import { Card, CardContent } from "~/components/ui/card";
@@ -8,6 +8,7 @@ import {
upsertBackupScheduleMutation,
getBackupScheduleOptions,
runBackupNowMutation,
+ deleteBackupScheduleMutation,
} from "~/api-client/@tanstack/react-query.gen";
import { parseError } from "~/lib/errors";
import { getCronExpression } from "~/utils/utils";
@@ -15,6 +16,7 @@ import { CreateScheduleForm, type BackupScheduleFormValues } from "../components
import { ScheduleSummary } from "../components/schedule-summary";
export default function ScheduleDetailsPage() {
+ const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
const [isEditMode, setIsEditMode] = useState(false);
const formId = useId();
@@ -52,6 +54,19 @@ export default function ScheduleDetailsPage() {
},
});
+ const deleteSchedule = useMutation({
+ ...deleteBackupScheduleMutation(),
+ onSuccess: () => {
+ toast.success("Backup schedule deleted successfully");
+ navigate("/backups");
+ },
+ onError: (error) => {
+ toast.error("Failed to delete backup schedule", {
+ description: parseError(error)?.message,
+ });
+ },
+ });
+
const handleSubmit = (formValues: BackupScheduleFormValues) => {
if (!schedule) return;
@@ -100,6 +115,12 @@ export default function ScheduleDetailsPage() {
});
};
+ const handleDeleteSchedule = () => {
+ if (!schedule) return;
+
+ deleteSchedule.mutate({ path: { scheduleId: schedule.id.toString() } });
+ };
+
if (loadingSchedule && !schedule) {
return (
@@ -130,10 +151,12 @@ export default function ScheduleDetailsPage() {
);
}