refactor: delete alert dialogs

This commit is contained in:
Nicolas Meienberger
2025-11-02 16:55:24 +01:00
parent c2041932b5
commit ccfa5e35e9
2 changed files with 71 additions and 15 deletions

View File

@@ -1,12 +1,22 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useNavigate, useParams, useSearchParams } from "react-router"; import { useNavigate, useParams, useSearchParams } from "react-router";
import { toast } from "sonner"; import { toast } from "sonner";
import { useState, useEffect } from "react";
import { import {
deleteRepositoryMutation, deleteRepositoryMutation,
getRepositoryOptions, getRepositoryOptions,
listSnapshotsOptions, listSnapshotsOptions,
} from "~/api-client/@tanstack/react-query.gen"; } from "~/api-client/@tanstack/react-query.gen";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogTitle,
} from "~/components/ui/alert-dialog";
import { parseError } from "~/lib/errors"; import { parseError } from "~/lib/errors";
import { getRepository } from "~/api-client/sdk.gen"; import { getRepository } from "~/api-client/sdk.gen";
import type { Route } from "./+types/repository-details"; import type { Route } from "./+types/repository-details";
@@ -14,7 +24,6 @@ import { cn } from "~/lib/utils";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import { RepositoryInfoTabContent } from "../tabs/info"; import { RepositoryInfoTabContent } from "../tabs/info";
import { RepositorySnapshotsTabContent } from "../tabs/snapshots"; import { RepositorySnapshotsTabContent } from "../tabs/snapshots";
import { useEffect } from "react";
export function meta({ params }: Route.MetaArgs) { export function meta({ params }: Route.MetaArgs) {
return [ return [
@@ -35,6 +44,7 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
const { name } = useParams<{ name: string }>(); const { name } = useParams<{ name: string }>();
const navigate = useNavigate(); const navigate = useNavigate();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const activeTab = searchParams.get("tab") || "info"; const activeTab = searchParams.get("tab") || "info";
@@ -65,14 +75,9 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
}, },
}); });
const handleDeleteConfirm = (name: string) => { const handleConfirmDelete = () => {
if ( setShowDeleteConfirm(false);
confirm( deleteRepo.mutate({ path: { name: name ?? "" } });
`Are you sure you want to delete the repository "${name}"? This action cannot be undone and will remove all backup data.`,
)
) {
deleteRepo.mutate({ path: { name } });
}
}; };
if (!name) { if (!name) {
@@ -103,7 +108,7 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
</div> </div>
</div> </div>
<div className="flex gap-4"> <div className="flex gap-4">
<Button variant="destructive" onClick={() => handleDeleteConfirm(name)} disabled={deleteRepo.isPending}> <Button variant="destructive" onClick={() => setShowDeleteConfirm(true)} disabled={deleteRepo.isPending}>
Delete Delete
</Button> </Button>
</div> </div>
@@ -121,6 +126,27 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
<RepositorySnapshotsTabContent repository={data} /> <RepositorySnapshotsTabContent repository={data} />
</TabsContent> </TabsContent>
</Tabs> </Tabs>
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete repository?</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete the repository <strong>{name}</strong>? This action cannot be undone and
will remove all backup data.
</AlertDialogDescription>
</AlertDialogHeader>
<div className="flex gap-3 justify-end">
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleConfirmDelete}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Delete repository
</AlertDialogAction>
</div>
</AlertDialogContent>
</AlertDialog>
</> </>
); );
} }

View File

@@ -1,6 +1,7 @@
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { useNavigate, useParams, useSearchParams } from "react-router"; import { useNavigate, useParams, useSearchParams } from "react-router";
import { toast } from "sonner"; import { toast } from "sonner";
import { useState } from "react";
import { import {
deleteVolumeMutation, deleteVolumeMutation,
getVolumeOptions, getVolumeOptions,
@@ -10,6 +11,15 @@ import {
import { StatusDot } from "~/components/status-dot"; import { StatusDot } from "~/components/status-dot";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogTitle,
} from "~/components/ui/alert-dialog";
import { VolumeIcon } from "~/components/volume-icon"; import { VolumeIcon } from "~/components/volume-icon";
import { parseError } from "~/lib/errors"; import { parseError } from "~/lib/errors";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
@@ -39,6 +49,7 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) {
const navigate = useNavigate(); const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const activeTab = searchParams.get("tab") || "info"; const activeTab = searchParams.get("tab") || "info";
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const { data } = useQuery({ const { data } = useQuery({
...getVolumeOptions({ path: { name: name ?? "" } }), ...getVolumeOptions({ path: { name: name ?? "" } }),
@@ -84,10 +95,9 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) {
}, },
}); });
const handleDeleteConfirm = (name: string) => { const handleConfirmDelete = () => {
if (confirm(`Are you sure you want to delete the volume "${name}"? This action cannot be undone.`)) { setShowDeleteConfirm(false);
deleteVol.mutate({ path: { name } }); deleteVol.mutate({ path: { name: name ?? "" } });
}
}; };
if (!name) { if (!name) {
@@ -127,7 +137,7 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) {
> >
Unmount Unmount
</Button> </Button>
<Button variant="destructive" onClick={() => handleDeleteConfirm(name)} disabled={deleteVol.isPending}> <Button variant="destructive" onClick={() => setShowDeleteConfirm(true)} disabled={deleteVol.isPending}>
Delete Delete
</Button> </Button>
</div> </div>
@@ -148,6 +158,26 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) {
<DockerTabContent volume={volume} /> <DockerTabContent volume={volume} />
</TabsContent> </TabsContent>
</Tabs> </Tabs>
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete volume?</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete the volume <strong>{name}</strong>? This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<div className="flex gap-3 justify-end">
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleConfirmDelete}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Delete volume
</AlertDialogAction>
</div>
</AlertDialogContent>
</AlertDialog>
</> </>
); );
} }