From 204eb483c2edeca13378a6ca7d66cfcfd3f2fdd4 Mon Sep 17 00:00:00 2001 From: averel10 Date: Fri, 13 Mar 2026 11:15:22 +0100 Subject: [PATCH] feat: implement delete dataset functionality with confirmation dialog --- src/app/actions/datasets.ts | 22 +++++++ src/app/admin/datasets/[id]/page.tsx | 2 + src/components/DeleteDatasetButton.tsx | 84 ++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/components/DeleteDatasetButton.tsx diff --git a/src/app/actions/datasets.ts b/src/app/actions/datasets.ts index 20c4ef2..8297c42 100644 --- a/src/app/actions/datasets.ts +++ b/src/app/actions/datasets.ts @@ -4,6 +4,7 @@ import db from '@/lib/db'; import { dataset } from '@/lib/model/dataset'; import { eq } from 'drizzle-orm'; import { revalidatePath } from 'next/cache'; +import { removeAllDatasetEntries } from './remove-dataset-entries'; import { requireAdmin } from '@/lib/auth'; export async function createDataset({ name, description }: { name: string; description?: string }) { @@ -64,3 +65,24 @@ export async function updateDataset( throw new Error('Failed to update dataset'); } } + +export async function deleteDataset(id: number) { + const result = await requireAdmin(); + if (!result.authenticated || !result.admin) { + throw new Error('Unauthorized'); + } + + try { + // Remove all entries and their files using the existing action + await removeAllDatasetEntries(id); + + // Then delete the dataset itself + await db.delete(dataset).where(eq(dataset.id, id)); + + revalidatePath('/admin'); + return { success: true }; + } catch (error) { + console.error('Error deleting dataset:', error); + throw new Error('Failed to delete dataset'); + } +} diff --git a/src/app/admin/datasets/[id]/page.tsx b/src/app/admin/datasets/[id]/page.tsx index e85d3db..21fd494 100644 --- a/src/app/admin/datasets/[id]/page.tsx +++ b/src/app/admin/datasets/[id]/page.tsx @@ -6,6 +6,7 @@ import EditableDatasetHeader from '@/components/EditableDatasetHeader'; import DatasetEntriesList from '@/components/DatasetEntriesList'; import UploadDatasetEntriesModal from '@/components/UploadDatasetEntriesModal'; import RemoveAllEntriesButton from '@/components/RemoveAllEntriesButton'; +import DeleteDatasetButton from '@/components/DeleteDatasetButton'; import { requireAdmin } from '@/lib/auth'; import { redirect } from 'next/navigation'; @@ -69,6 +70,7 @@ export default async function DatasetPage({ params }: DatasetPageProps) {
+
diff --git a/src/components/DeleteDatasetButton.tsx b/src/components/DeleteDatasetButton.tsx new file mode 100644 index 0000000..277addf --- /dev/null +++ b/src/components/DeleteDatasetButton.tsx @@ -0,0 +1,84 @@ +'use client'; + +import { useState } from 'react'; +import { deleteDataset } from '@/app/actions/datasets'; +import { useRouter } from 'next/navigation'; + +interface DeleteDatasetButtonProps { + datasetId: number; + datasetName: string; +} + +export default function DeleteDatasetButton({ datasetId, datasetName }: DeleteDatasetButtonProps) { + const [isConfirming, setIsConfirming] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const router = useRouter(); + + async function handleConfirm() { + setLoading(true); + setError(null); + + try { + await deleteDataset(datasetId); + setIsConfirming(false); + // Redirect to admin page after deletion + router.push('/admin'); + } catch (err) { + const message = err instanceof Error ? err.message : 'Failed to delete dataset'; + setError(message); + } finally { + setLoading(false); + } + } + + if (isConfirming) { + return ( +
+
+

+ Delete dataset "{datasetName}"? +

+

+ This will permanently delete the dataset and all of its entries. This action cannot be undone. +

+ + {error && ( +
+ {error} +
+ )} + +
+ + +
+
+
+ ); + } + + return ( + + ); +}