import { useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import PDFViewer from '@/components/PDFViewer'
import { useToast } from '@/components/ui/toast'
import { apiClientV2 } from '@/services/apiV2'
import { FileText, Download, AlertCircle, TrendingUp, Clock, Layers, FileJson, Loader2 } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import TaskNotFound from '@/components/TaskNotFound'
import { useTaskValidation } from '@/hooks/useTaskValidation'
export default function ResultsPage() {
const { t } = useTranslation()
const navigate = useNavigate()
const { toast } = useToast()
// Use shared hook for task validation
const { taskId, taskDetail, isLoading, isNotFound, clearAndReset } = useTaskValidation({
refetchInterval: (query) => {
const data = query.state.data
if (!data) return 2000
if (data.status === 'completed' || data.status === 'failed') {
return false
}
return 2000
},
})
// Construct PDF URL for preview - memoize to prevent unnecessary reloads
// Must be called unconditionally before any early returns (React hooks rule)
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
const pdfUrl = useMemo(() => {
return taskId ? `${API_BASE_URL}/api/v2/tasks/${taskId}/download/pdf` : ''
}, [taskId, API_BASE_URL])
// Get auth token for PDF preview - memoize to prevent new object reference each render
const pdfHttpHeaders = useMemo(() => {
const authToken = localStorage.getItem('auth_token_v2')
return authToken ? { Authorization: `Bearer ${authToken}` } : undefined
}, [])
const handleDownloadPDF = async () => {
if (!taskId) return
try {
await apiClientV2.downloadPDF(taskId)
toast({
title: t('export.exportSuccess'),
description: 'PDF 已下載',
variant: 'success',
})
} catch (error: any) {
toast({
title: t('export.exportError'),
description: error.response?.data?.detail || t('errors.networkError'),
variant: 'destructive',
})
}
}
const handleDownloadMarkdown = async () => {
if (!taskId) return
try {
await apiClientV2.downloadMarkdown(taskId)
toast({
title: t('export.exportSuccess'),
description: 'Markdown 已下載',
variant: 'success',
})
} catch (error: any) {
toast({
title: t('export.exportError'),
description: error.response?.data?.detail || t('errors.networkError'),
variant: 'destructive',
})
}
}
const handleDownloadJSON = async () => {
if (!taskId) return
try {
await apiClientV2.downloadJSON(taskId)
toast({
title: t('export.exportSuccess'),
description: 'JSON 已下載',
variant: 'success',
})
} catch (error: any) {
toast({
title: t('export.exportError'),
description: error.response?.data?.detail || t('errors.networkError'),
variant: 'destructive',
})
}
}
const getStatusBadge = (status: string) => {
switch (status) {
case 'completed':
return
載入任務結果...
{t('results.noBatchMessage', { defaultValue: '尚未選擇任何任務。請先上傳並處理檔案。' })}
任務 ID: {taskId} {taskDetail.filename && ` · ${taskDetail.filename}`}
處理時間
{taskDetail.processing_time_ms ? (taskDetail.processing_time_ms / 1000).toFixed(2) : '0'}s
處理狀態
成功
任務類型
OCR
正在處理中...
請稍候,OCR 處理需要一些時間
處理失敗
{taskDetail.error_message && ({taskDetail.error_message}
)}等待處理
請前往處理頁面啟動 OCR 處理