mirror of
https://github.com/sakaljurgis/best-choice.git
synced 2026-07-08 21:47:40 +00:00
delete project
This commit is contained in:
@@ -120,3 +120,7 @@ export const updateProject = async (
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteProject = async (projectId: string): Promise<void> => {
|
||||
await apiFetch<void>(`/projects/${projectId}`, { method: 'DELETE' });
|
||||
};
|
||||
|
||||
@@ -2,16 +2,20 @@ import { FormEvent, useMemo, useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
useCreateProjectMutation,
|
||||
useDeleteProjectMutation,
|
||||
useProjectsQuery
|
||||
} from '../query/projects';
|
||||
|
||||
function ProjectsPage() {
|
||||
const { data, isLoading, isError, error } = useProjectsQuery();
|
||||
const createProjectMutation = useCreateProjectMutation();
|
||||
const deleteProjectMutation = useDeleteProjectMutation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const [newProjectName, setNewProjectName] = useState('');
|
||||
const [createError, setCreateError] = useState<string | null>(null);
|
||||
const [deleteError, setDeleteError] = useState<string | null>(null);
|
||||
const [pendingDeletionId, setPendingDeletionId] = useState<string | null>(null);
|
||||
|
||||
const projects = data?.data ?? [];
|
||||
|
||||
@@ -49,6 +53,27 @@ function ProjectsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteProject = async (projectId: string, projectName: string) => {
|
||||
const confirmed = window.confirm(
|
||||
`Delete project "${projectName}"? This will remove all items and their prices, but any saved URLs will be kept.`
|
||||
);
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDeleteError(null);
|
||||
setPendingDeletionId(projectId);
|
||||
|
||||
try {
|
||||
await deleteProjectMutation.mutateAsync(projectId);
|
||||
} catch (submitError) {
|
||||
setDeleteError((submitError as Error).message);
|
||||
} finally {
|
||||
setPendingDeletionId(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-10">
|
||||
<section className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
|
||||
@@ -100,6 +125,11 @@ function ProjectsPage() {
|
||||
{listError ? (
|
||||
<p className="rounded-md bg-red-50 px-3 py-2 text-sm text-red-600">{listError}</p>
|
||||
) : null}
|
||||
{deleteError ? (
|
||||
<p className="mt-3 rounded-md bg-red-50 px-3 py-2 text-sm text-red-600">
|
||||
{deleteError}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-slate-200 text-sm">
|
||||
@@ -117,6 +147,9 @@ function ProjectsPage() {
|
||||
<th className="px-4 py-3 text-left font-medium uppercase tracking-wide text-slate-500">
|
||||
Updated
|
||||
</th>
|
||||
<th className="px-4 py-3 text-right font-medium uppercase tracking-wide text-slate-500">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-slate-200">
|
||||
@@ -142,6 +175,18 @@ function ProjectsPage() {
|
||||
<td className="px-4 py-3 text-xs text-slate-500">
|
||||
{new Date(project.updatedAt).toLocaleString()}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-right">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-md border border-red-200 px-3 py-1.5 text-xs font-semibold text-red-600 transition hover:bg-red-50 disabled:cursor-not-allowed disabled:border-red-100 disabled:text-red-300"
|
||||
onClick={() => handleDeleteProject(project.id, project.name)}
|
||||
disabled={deleteProjectMutation.isPending}
|
||||
>
|
||||
{deleteProjectMutation.isPending && pendingDeletionId === project.id
|
||||
? 'Deleting…'
|
||||
: 'Delete'}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
fetchProject,
|
||||
fetchProjects,
|
||||
updateProject,
|
||||
deleteProject,
|
||||
type CreateProjectPayload,
|
||||
type ProjectsListResponse,
|
||||
type UpdateProjectPayload
|
||||
@@ -116,3 +117,16 @@ export const useUpdateItemMutation = (projectId: string | undefined) => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteProjectMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (projectId: string) => deleteProject(projectId),
|
||||
onSuccess: (_, projectId) => {
|
||||
queryClient.invalidateQueries({ queryKey: projectsKeys.list() });
|
||||
queryClient.removeQueries({ queryKey: projectsKeys.detail(projectId) });
|
||||
queryClient.removeQueries({ queryKey: projectsKeys.items(projectId) });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user