diff --git a/frontend/src/hooks/useAnalysis.ts b/frontend/src/hooks/useAnalysis.ts index 87425c9..c3249c3 100644 --- a/frontend/src/hooks/useAnalysis.ts +++ b/frontend/src/hooks/useAnalysis.ts @@ -1,5 +1,5 @@ -import { useQuery } from "@tanstack/react-query"; -import { getAnalysis, getAnalysisStatus } from "../api/analysis"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { getAnalysis, getAnalysisStatus, deleteAnalysis } from "../api/analysis"; import type { AnalysisDetail, AnalysisStatus } from "../types/analysis"; export function useAnalysis(analysisId: string | undefined) { @@ -10,6 +10,17 @@ export function useAnalysis(analysisId: string | undefined) { }); } +export function useDeleteAnalysis() { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: (analysisId: string) => deleteAnalysis(analysisId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["projects"] }); + queryClient.invalidateQueries({ queryKey: ["project"] }); + }, + }); +} + export function useAnalysisStatus( analysisId: string | undefined, enabled: boolean = true, diff --git a/frontend/src/pages/AnalysisView.tsx b/frontend/src/pages/AnalysisView.tsx index b83596a..ed30893 100644 --- a/frontend/src/pages/AnalysisView.tsx +++ b/frontend/src/pages/AnalysisView.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { useParams } from "react-router-dom"; -import { useAnalysis } from "../hooks/useAnalysis"; +import { useParams, useNavigate } from "react-router-dom"; +import { useAnalysis, useDeleteAnalysis } from "../hooks/useAnalysis"; import { useAnalysisStore, type AnalysisTab } from "../stores/analysisStore"; import { getAnalysisImageUrl, checkAIInsightsAvailable, generateAIInsights } from "../api/analysis"; import type { Insight } from "../types/analysis"; @@ -125,7 +125,9 @@ const tabs: { key: AnalysisTab; label: string }[] = [ export default function AnalysisView() { const { analysisId } = useParams<{ analysisId: string }>(); + const navigate = useNavigate(); const { data: analysis, isLoading, error } = useAnalysis(analysisId); + const deleteAnalysisMutation = useDeleteAnalysis(); const activeTab = useAnalysisStore((s) => s.activeTab); const setActiveTab = useAnalysisStore((s) => s.setActiveTab); const setCurrentAnalysis = useAnalysisStore((s) => s.setCurrentAnalysis); @@ -180,6 +182,13 @@ export default function AnalysisView() { }; }, [analysis, setCurrentAnalysis, reset]); + const handleDeleteAnalysis = async () => { + if (!analysisId) return; + if (!window.confirm("Are you sure you want to delete this analysis? This cannot be undone.")) return; + await deleteAnalysisMutation.mutateAsync(analysisId); + navigate(-1); + }; + const handleDownloadPdf = async () => { if (!analysisId) return; try { @@ -241,6 +250,13 @@ export default function AnalysisView() { )} + diff --git a/frontend/src/pages/ProjectDetail.tsx b/frontend/src/pages/ProjectDetail.tsx index 70359f8..4feaf67 100644 --- a/frontend/src/pages/ProjectDetail.tsx +++ b/frontend/src/pages/ProjectDetail.tsx @@ -1,5 +1,7 @@ +import { useState } from "react"; import { useParams, Link, useNavigate } from "react-router-dom"; import { useProject, useDeleteProject } from "../hooks/useProjects"; +import { useDeleteAnalysis } from "../hooks/useAnalysis"; import { getAnalysisImageUrl } from "../api/analysis"; import Card from "../components/common/Card"; import Button from "../components/common/Button"; @@ -10,6 +12,20 @@ export default function ProjectDetail() { const navigate = useNavigate(); const { data: project, isLoading, error } = useProject(projectId); const deleteProject = useDeleteProject(); + const deleteAnalysis = useDeleteAnalysis(); + const [deletingId, setDeletingId] = useState(null); + + const handleDeleteAnalysis = async (e: React.MouseEvent, analysisId: string, analysisName: string) => { + e.preventDefault(); + e.stopPropagation(); + if (!window.confirm(`Delete analysis "${analysisName}"? This cannot be undone.`)) return; + setDeletingId(analysisId); + try { + await deleteAnalysis.mutateAsync(analysisId); + } finally { + setDeletingId(null); + } + }; const handleDelete = async () => { if (!projectId) return; @@ -131,12 +147,31 @@ export default function ProjectDetail() {
-

- {analysis.name} -

+
+

+ {analysis.name} +

+ +
{analysis.model}