first
This commit is contained in:
90
frontend/src/components/ResultsTable.tsx
Normal file
90
frontend/src/components/ResultsTable.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import type { FileResult } from '@/types/api'
|
||||
|
||||
interface ResultsTableProps {
|
||||
files: FileResult[]
|
||||
onViewResult?: (fileId: number) => void
|
||||
onDownloadPDF?: (fileId: number) => void
|
||||
}
|
||||
|
||||
export default function ResultsTable({ files, onViewResult, onDownloadPDF }: ResultsTableProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const getStatusBadge = (status: FileResult['status']) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return <Badge variant="success">{t('processing.completed')}</Badge>
|
||||
case 'processing':
|
||||
return <Badge variant="default">{t('processing.processing')}</Badge>
|
||||
case 'failed':
|
||||
return <Badge variant="destructive">{t('processing.failed')}</Badge>
|
||||
default:
|
||||
return <Badge variant="secondary">{t('processing.pending')}</Badge>
|
||||
}
|
||||
}
|
||||
|
||||
const formatTime = (seconds?: number) => {
|
||||
if (!seconds) return 'N/A'
|
||||
return `${seconds.toFixed(2)}s`
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>{t('results.filename')}</TableHead>
|
||||
<TableHead>{t('results.status')}</TableHead>
|
||||
<TableHead>{t('results.processingTime')}</TableHead>
|
||||
<TableHead className="text-right">{t('results.actions')}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{files.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} className="text-center text-muted-foreground">
|
||||
{t('results.noResults')}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
files.map((file) => (
|
||||
<TableRow key={file.id}>
|
||||
<TableCell className="font-medium">{file.filename}</TableCell>
|
||||
<TableCell>{getStatusBadge(file.status)}</TableCell>
|
||||
<TableCell>{formatTime(file.processing_time)}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
{file.status === 'completed' && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onViewResult?.(file.id)}
|
||||
>
|
||||
{t('results.viewMarkdown')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onDownloadPDF?.(file.id)}
|
||||
>
|
||||
{t('results.downloadPDF')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{file.status === 'failed' && file.error && (
|
||||
<span className="text-sm text-destructive">{file.error}</span>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user