"use client" import { useState, useEffect } from "react" import { Sidebar } from "@/components/sidebar" import { Button } from "@/components/ui/button" import { Card, CardContent } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog" import { FileText, Calendar, Search, Eye, Download, Trash2, Loader2 } from "lucide-react" import Link from "next/link" import { useToast } from "@/hooks/use-toast" // 歷史記錄數據類型 interface HistoryItem { id: string; title: string; type: string; score: number; grade: string; date: string; status: 'completed' | 'processing'; evaluation_id?: number; description?: string; created_at: string; updated_at: string; } // 統計數據類型 interface StatsData { totalProjects: number; completedProjects: number; processingProjects: number; averageScore: number; } export default function HistoryPage() { const [searchTerm, setSearchTerm] = useState("") const [filterType, setFilterType] = useState("all") const [filterStatus, setFilterStatus] = useState("all") const [historyData, setHistoryData] = useState([]) const [statsData, setStatsData] = useState({ totalProjects: 0, completedProjects: 0, processingProjects: 0, averageScore: 0 }) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [deletingId, setDeletingId] = useState(null) const { toast } = useToast() // 載入歷史記錄數據 useEffect(() => { const loadHistoryData = async () => { try { setLoading(true); setError(null); // 並行獲取歷史記錄和統計數據 const [historyResponse, statsResponse] = await Promise.all([ fetch('/api/history'), fetch('/api/history/stats') ]); if (!historyResponse.ok || !statsResponse.ok) { throw new Error('獲取數據失敗'); } const historyResult = await historyResponse.json(); const statsResult = await statsResponse.json(); if (historyResult.success && statsResult.success) { setHistoryData(historyResult.data); setStatsData(statsResult.data); } else { throw new Error(historyResult.error || statsResult.error || '數據載入失敗'); } } catch (err) { console.error('載入歷史記錄失敗:', err); setError(err instanceof Error ? err.message : '載入數據時發生錯誤'); } finally { setLoading(false); } }; loadHistoryData(); }, []); const filteredHistory = historyData.filter((item) => { const matchesSearch = item.title.toLowerCase().includes(searchTerm.toLowerCase()); const matchesType = filterType === "all" || item.type === filterType; const matchesStatus = filterStatus === "all" || item.status === filterStatus; return matchesSearch && matchesType && matchesStatus; }); const getGradeColor = (grade: string) => { if (grade.startsWith("A")) return "bg-green-100 text-green-800"; if (grade.startsWith("B")) return "bg-blue-100 text-blue-800"; if (grade.startsWith("C")) return "bg-yellow-100 text-yellow-800"; return "bg-gray-100 text-gray-800"; }; const getTypeIcon = (type: string) => { switch (type) { case "PPT": return ; case "Video": return ; case "Website": return ; default: return ; } }; // 下載評審報告 const handleDownload = async (evaluationId: number, projectTitle: string) => { try { toast({ title: "報告下載中", description: "評審報告 PDF 正在生成,請稍候...", }); // 調用下載 API const response = await fetch(`/api/evaluation/${evaluationId}/download`); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || '下載失敗'); } // 獲取 PDF Blob const pdfBlob = await response.blob(); // 創建下載連結 const url = window.URL.createObjectURL(pdfBlob); const link = document.createElement('a'); link.href = url; // 從 Content-Disposition 標頭獲取檔案名稱,或使用預設名稱 const contentDisposition = response.headers.get('Content-Disposition'); let fileName = `評審報告_${projectTitle}_${new Date().toISOString().split('T')[0]}.pdf`; if (contentDisposition) { const fileNameMatch = contentDisposition.match(/filename="(.+)"/); if (fileNameMatch) { fileName = decodeURIComponent(fileNameMatch[1]); } } link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); // 顯示成功提示 toast({ title: "下載完成", description: "評審報告已成功下載", }); } catch (error) { console.error('下載失敗:', error); toast({ title: "下載失敗", description: error instanceof Error ? error.message : '下載過程中發生錯誤', variant: "destructive", }); } }; // 刪除評審報告 const handleDelete = async (evaluationId: number, projectTitle: string) => { try { setDeletingId(evaluationId.toString()); const response = await fetch(`/api/evaluation/${evaluationId}/delete`, { method: 'DELETE', }); const result = await response.json(); if (result.success) { // 從本地狀態中移除已刪除的項目 setHistoryData(prev => prev.filter(item => item.evaluation_id !== evaluationId)); // 重新載入統計數據 const statsResponse = await fetch('/api/history/stats'); const statsResult = await statsResponse.json(); if (statsResult.success) { setStatsData(statsResult.data); } toast({ title: "刪除成功", description: `評審報告「${projectTitle}」已成功刪除`, }); } else { throw new Error(result.error || '刪除失敗'); } } catch (error) { console.error('刪除失敗:', error); toast({ title: "刪除失敗", description: error instanceof Error ? error.message : '刪除過程中發生錯誤', variant: "destructive", }); } finally { setDeletingId(null); } }; return (
{/* Header */}

歷史記錄

查看您的所有評審記錄和結果

{/* Filters */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* Statistics */}
{statsData.totalProjects}
總評審數
{statsData.completedProjects}
已完成
{statsData.averageScore}
平均分數
{statsData.processingProjects}
處理中
{/* Loading State */} {loading && (

載入歷史記錄中...

請稍候片刻

)} {/* Error State */} {error && (

載入失敗

{error}

)} {/* History List */} {!loading && !error && (
{filteredHistory.map((item) => (
{getTypeIcon(item.type)}

{item.title}

{item.date}
{item.type} {item.status === "completed" ? "已完成" : "處理中"}
{item.status === "completed" && (
{item.score}
{item.grade}
)}
{item.status === "completed" ? ( <> ) : ( )} 確認刪除 您確定要刪除評審報告「{item.title}」嗎?此操作將永久刪除:
• 評審結果和分數
• 專案文件和上傳的檔案
• 所有相關的評語和建議

此操作無法復原!
取消 item.evaluation_id && handleDelete(item.evaluation_id, item.title)} className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > 確認刪除
))} {filteredHistory.length === 0 && (

沒有找到相關記錄

嘗試調整搜尋條件或篩選器

)}
)}
) }