feat: add extraction deletion functionality with confirmation dialog and update extraction list on deletion
Some checks failed
Frontend CI / lint (push) Failing after 18s
Frontend CI / build (push) Has been skipped

This commit is contained in:
JSC
2025-08-25 21:40:47 +02:00
parent 4a973e5044
commit 6a40311a82
4 changed files with 135 additions and 4 deletions

View File

@@ -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 (
<>
<TableRow className="hover:bg-muted/50">
<TableCell>
<div className="min-w-0">
@@ -128,8 +167,64 @@ export function ExtractionsRow({ extraction }: ExtractionsRowProps) {
<ExternalLink className="h-4 w-4" />
</a>
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => setShowDeleteDialog(true)}
title="Delete extraction"
className="text-destructive hover:text-destructive"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</TableCell>
</TableRow>
<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete Extraction</DialogTitle>
<DialogDescription>
Are you sure you want to delete this extraction? This action cannot be undone.
{extraction.title && (
<>
<br />
<br />
<strong>Title:</strong> {extraction.title}
<br />
<strong>URL:</strong> {extraction.url}
</>
)}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button
variant="outline"
onClick={() => setShowDeleteDialog(false)}
disabled={deleteLoading}
>
Cancel
</Button>
<Button
variant="destructive"
onClick={handleDeleteExtraction}
disabled={deleteLoading}
>
{deleteLoading ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Deleting...
</>
) : (
<>
<Trash2 className="h-4 w-4 mr-2" />
Delete
</>
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
)
}

View File

@@ -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 (
<div className="rounded-md border">
<Table>
@@ -31,6 +32,7 @@ export function ExtractionsTable({ extractions }: ExtractionsTableProps) {
<ExtractionsRow
key={extraction.id}
extraction={extraction}
onExtractionDeleted={onExtractionDeleted}
/>
))}
</TableBody>