diff --git a/src/components/extractions/ExtractionsRow.tsx b/src/components/extractions/ExtractionsRow.tsx index 56e8ebd..191aa4e 100644 --- a/src/components/extractions/ExtractionsRow.tsx +++ b/src/components/extractions/ExtractionsRow.tsx @@ -1,7 +1,15 @@ import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' import { TableCell, TableRow } from '@/components/ui/table' -import type { ExtractionInfo } from '@/lib/api/services/extractions' +import { extractionsService, type ExtractionInfo } from '@/lib/api/services/extractions' import { formatDateDistanceToNow } from '@/utils/format-date' import { AlertCircle, @@ -10,14 +18,44 @@ import { Clock, ExternalLink, Loader2, + Trash2, User } from 'lucide-react' +import { useState } from 'react' +import { toast } from 'sonner' interface ExtractionsRowProps { extraction: ExtractionInfo + onExtractionDeleted?: (extractionId: number) => void } -export function ExtractionsRow({ extraction }: ExtractionsRowProps) { +export function ExtractionsRow({ extraction, onExtractionDeleted }: ExtractionsRowProps) { + const [showDeleteDialog, setShowDeleteDialog] = useState(false) + const [deleteLoading, setDeleteLoading] = useState(false) + + const handleDeleteExtraction = async () => { + if (!extraction.id) return + + try { + setDeleteLoading(true) + const response = await extractionsService.deleteExtraction(extraction.id) + toast.success(response.message) + + // Close dialog + setShowDeleteDialog(false) + + // Notify parent component + if (onExtractionDeleted) { + onExtractionDeleted(extraction.id) + } + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : 'Failed to delete extraction' + toast.error(errorMessage) + } finally { + setDeleteLoading(false) + } + } const getStatusBadge = (status: ExtractionInfo['status']) => { switch (status) { case 'pending': @@ -75,6 +113,7 @@ export function ExtractionsRow({ extraction }: ExtractionsRowProps) { } return ( + <>
@@ -128,8 +167,64 @@ export function ExtractionsRow({ extraction }: ExtractionsRowProps) { +
+ + + + + Delete Extraction + + Are you sure you want to delete this extraction? This action cannot be undone. + {extraction.title && ( + <> +
+
+ Title: {extraction.title} +
+ URL: {extraction.url} + + )} +
+
+ + + + +
+
+ ) } \ No newline at end of file diff --git a/src/components/extractions/ExtractionsTable.tsx b/src/components/extractions/ExtractionsTable.tsx index 3091430..8ce2bfa 100644 --- a/src/components/extractions/ExtractionsTable.tsx +++ b/src/components/extractions/ExtractionsTable.tsx @@ -10,9 +10,10 @@ import type { ExtractionInfo } from '@/lib/api/services/extractions' interface ExtractionsTableProps { extractions: ExtractionInfo[] + onExtractionDeleted?: (extractionId: number) => void } -export function ExtractionsTable({ extractions }: ExtractionsTableProps) { +export function ExtractionsTable({ extractions, onExtractionDeleted }: ExtractionsTableProps) { return (
@@ -31,6 +32,7 @@ export function ExtractionsTable({ extractions }: ExtractionsTableProps) { ))} diff --git a/src/lib/api/services/extractions.ts b/src/lib/api/services/extractions.ts index 30f3a27..447996f 100644 --- a/src/lib/api/services/extractions.ts +++ b/src/lib/api/services/extractions.ts @@ -41,6 +41,10 @@ export interface GetExtractionsParams { limit?: number } +export interface DeleteExtractionResponse { + message: string +} + export class ExtractionsService { /** * Create a new extraction job @@ -135,6 +139,16 @@ export class ExtractionsService { ) return response } + + /** + * Delete an extraction + */ + async deleteExtraction(extractionId: number): Promise { + const response = await apiClient.delete( + `/api/v1/extractions/${extractionId}` + ) + return response + } } export const extractionsService = new ExtractionsService() diff --git a/src/pages/ExtractionsPage.tsx b/src/pages/ExtractionsPage.tsx index 74216ca..c1c4ca8 100644 --- a/src/pages/ExtractionsPage.tsx +++ b/src/pages/ExtractionsPage.tsx @@ -159,6 +159,23 @@ export function ExtractionsPage() { setShowCreateDialog(false) } + const handleExtractionDeleted = (extractionId: number) => { + // Remove the deleted extraction from the current list + setExtractions(prev => prev.filter(extraction => extraction.id !== extractionId)) + + // Update total count + setTotalCount(prev => prev - 1) + + // If current page is now empty and not the first page, go to previous page + const remainingOnCurrentPage = extractions.length - 1 + if (remainingOnCurrentPage === 0 && currentPage > 1) { + setCurrentPage(currentPage - 1) + } + + // Refresh the full list to ensure accuracy + fetchExtractions() + } + const renderContent = () => { if (loading) { return @@ -174,7 +191,10 @@ export function ExtractionsPage() { return (
- +