"use client" import { useState, useEffect } from "react" import { useCompetition } from "@/contexts/competition-context" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Progress } from "@/components/ui/progress" import { Target, Users, Lightbulb, Trophy, Crown, Award, Camera, ImageIcon, ChevronLeft, ChevronRight, X, Star, MessageSquare, BarChart3, ExternalLink, Eye, Link, FileText, } from "lucide-react" import type { Award as AwardType } from "@/types/competition" interface AwardDetailDialogProps { open: boolean onOpenChange: (open: boolean) => void award: AwardType } // Judge scoring data - empty for production const getJudgeScores = (awardId: string) => { return [] } // App links and reports data - empty for production const getAppData = (awardId: string) => { return { appUrl: "", demoUrl: "", githubUrl: "", reports: [], } } export function AwardDetailDialog({ open, onOpenChange, award }: AwardDetailDialogProps) { const { competitions, judges, getTeamById, getProposalById } = useCompetition() const [activeTab, setActiveTab] = useState("overview") const [showPhotoGallery, setShowPhotoGallery] = useState(false) const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0) const [competitionJudges, setCompetitionJudges] = useState([]) // 添加調試資訊 console.log('🏆 AwardDetailDialog 渲染:', { open, award: award ? { id: award.id, competitionId: award.competitionId, awardName: award.awardName, hasCompetitionId: !!award.competitionId } : null }); const competition = competitions.find((c) => c.id === award.competitionId) const judgeScores = getJudgeScores(award.id) const appData = getAppData(award.id) // 載入競賽評審團資訊 useEffect(() => { console.log('🔍 useEffect 觸發:', { open, competitionId: award.competitionId, awardId: award.id }); if (open && award.competitionId) { const loadCompetitionJudges = async (retryCount = 0) => { try { console.log('🔍 載入競賽評審團:', award.competitionId, '重試次數:', retryCount); console.log('🏆 獎項資料:', award); // 添加時間戳防止快取,並設置快取控制標頭 const timestamp = Date.now(); const apiUrl = `/api/competitions/${award.competitionId}/judges?t=${timestamp}`; console.log('🌐 API URL:', apiUrl); const response = await fetch(apiUrl, { method: 'GET', headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' } }); console.log('📡 API 回應狀態:', response.status); console.log('📡 API 回應標頭:', Object.fromEntries(response.headers.entries())); if (!response.ok) { const errorText = await response.text(); console.error('❌ API 錯誤回應:', errorText); throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`); } const data = await response.json(); console.log('📄 API 回應資料:', JSON.stringify(data, null, 2)); if (data.success && data.data && data.data.judges) { console.log('✅ 獲取到評審團:', data.data.judges.length, '位'); console.log('👥 評審團詳細資料:', data.data.judges); setCompetitionJudges(data.data.judges); } else { console.error('❌ 獲取評審團失敗:', data.message || '未知錯誤'); console.error('❌ 完整錯誤資料:', data); // 如果沒有評審資料且是第一次嘗試,重試一次 if (retryCount === 0) { console.log('🔄 重試載入評審團...'); setTimeout(() => loadCompetitionJudges(1), 1000); } else { setCompetitionJudges([]); } } } catch (error) { console.error('❌ 載入評審團失敗:', error); // 如果是網路錯誤且是第一次嘗試,重試一次 if (retryCount === 0) { console.log('🔄 網路錯誤,重試載入評審團...'); setTimeout(() => loadCompetitionJudges(1), 2000); } else { setCompetitionJudges([]); } } }; // 清空之前的評審資料,確保重新載入 setCompetitionJudges([]); loadCompetitionJudges(); } else { console.log('❌ useEffect 條件不滿足:', { open, competitionId: award.competitionId, hasCompetitionId: !!award.competitionId }); } }, [open, award.competitionId]); // Competition photos - empty for production const getCompetitionPhotos = () => { return [] } const competitionPhotos = getCompetitionPhotos() const getCompetitionTypeIcon = (type: string) => { switch (type) { case "individual": return case "team": return case "proposal": return default: return } } const getCompetitionTypeText = (type: string) => { switch (type) { case "individual": return "個人賽" case "team": return "團隊賽" case "proposal": return "提案賽" default: return "競賽" } } const getCompetitionTypeColor = (type: string) => { switch (type) { case "individual": return "bg-blue-100 text-blue-800 border-blue-200" case "team": return "bg-green-100 text-green-800 border-green-200" case "proposal": return "bg-purple-100 text-purple-800 border-purple-200" default: return "bg-gray-100 text-gray-800 border-gray-200" } } const getFileIcon = (type: string) => { switch (type.toLowerCase()) { case "pdf": return case "pptx": case "ppt": return case "docx": case "doc": return default: return } } const nextPhoto = () => { setCurrentPhotoIndex((prev) => (prev + 1) % competitionPhotos.length) } const prevPhoto = () => { setCurrentPhotoIndex((prev) => (prev - 1 + competitionPhotos.length) % competitionPhotos.length) } const handlePreview = (report: any) => { // Open preview in new window window.open(report.previewUrl, "_blank") } const renderAwardOverview = () => (
{award.icon}
{award.awardName} {award.appName || award.proposalTitle || award.teamName}
{getCompetitionTypeIcon(award.competitionType)} {getCompetitionTypeText(award.competitionType)} {award.awardName}
{award.awardType === "popular" && award.competitionType === "team" ? `${award.score}` : award.awardType === "popular" ? `${award.score}` : award.score}
{award.competitionType === "proposal" ? "評審評分" : award.awardType === "popular" ? award.competitionType === "team" ? "人氣指數" : "收藏數" : "評審評分"}
{award.year}年{award.month}月
獲獎時間
{award.creator}
{award.competitionType === "team" ? "團隊" : award.competitionType === "proposal" ? "提案團隊" : "創作者"}
{competition && (

競賽資訊

競賽名稱: {competition.name}

競賽描述: {competition.description}

競賽期間: {competition.startDate} ~ {competition.endDate}

評審團: {competitionJudges && competitionJudges.length > 0 ? ( {competitionJudges.length} 位評審 ) : ( 暫無評審信息 )}

)}
{/* App Links Section */} 應用連結 相關應用和資源連結
{appData.appUrl && (

正式應用

APP 連結

)} {appData.demoUrl && (

演示版本

體驗環境

)} {appData.githubUrl && (

源碼倉庫

GitHub

)}
{/* Reports Section */} 相關報告 技術文檔和報告資料(僅供預覽)
{appData.reports.map((report) => (
{getFileIcon(report.type)}

{report.name}

{report.description}

大小:{report.size} 上傳:{report.uploadDate} {report.type}
))}
) const renderCompetitionPhotos = () => ( 競賽照片 競賽當天的精彩瞬間
{competitionPhotos.map((photo, index) => (
{ setCurrentPhotoIndex(index) setShowPhotoGallery(true) }} > {photo.title}

{photo.title}

))}
) const renderJudgePanel = () => { if (!competitionJudges || competitionJudges.length === 0) { return ( 評審團 本次競賽的專業評審團隊

暫無評審信息

) } return ( 評審團 本次競賽的專業評審團隊
{competitionJudges.map((judge) => (
{judge.name[0]}

{judge.name}

{judge.title}

{judge.expertise && judge.expertise.slice(0, 2).map((skill) => ( {skill} ))}
))}
) } const renderJudgeScores = () => (
{/* Overall Statistics */} 評分統計 評審團整體評分概況
{(judgeScores.reduce((sum, score) => sum + score.overallScore, 0) / judgeScores.length).toFixed(1)}
平均分數
{Math.max(...judgeScores.map((s) => s.overallScore)).toFixed(1)}
最高分數
{Math.min(...judgeScores.map((s) => s.overallScore)).toFixed(1)}
最低分數
{judgeScores.length}
評審人數
{/* Individual Judge Scores */} {judgeScores.map((judgeScore, index) => (
{judgeScore.judgeName[0]}
{judgeScore.judgeName} {judgeScore.judgeTitle}
{judgeScore.overallScore} /5.0
評分時間:{judgeScore.submittedAt}
{/* Criteria Scores */}

評分細項

{judgeScore.criteria.map((criterion, criterionIndex) => (
{criterion.name} {criterion.score}/{criterion.maxScore}
))}
{/* Judge Comment */}

評審評語

{judgeScore.comment}

))}
) return ( <> 得獎作品詳情 {competition?.name} - {award.awardName}
獎項概覽 競賽照片 評審團 評分詳情 {renderAwardOverview()} {renderCompetitionPhotos()} {renderJudgePanel()} {renderJudgeScores()}
{/* Photo Gallery Modal */}
{competitionPhotos[currentPhotoIndex]?.title}

{competitionPhotos[currentPhotoIndex]?.title}

{competitionPhotos[currentPhotoIndex]?.description}

{competitionPhotos.map((_, index) => (
{currentPhotoIndex + 1} / {competitionPhotos.length}
) }