"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, Download, } from "lucide-react" import type { Award as AwardType } from "@/types/competition" interface AwardDetailDialogProps { open: boolean onOpenChange: (open: boolean) => void award: AwardType } 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([]) const [judgeScores, setJudgeScores] = useState([]) const [loadingScores, setLoadingScores] = useState(false) // 添加調試資訊 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) // 載入競賽評審團資訊 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); const response = await fetch(`/api/competitions/${award.competitionId}/judges?t=${Date.now()}`, { method: 'GET', headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('📊 評審團API回應:', data); if (data.success) { console.log('✅ 載入評審團成功:', data.data.judges.length, '位'); setCompetitionJudges(data.data.judges); } else { console.error('❌ 載入評審團失敗:', data.message); setCompetitionJudges([]); } } catch (error) { console.error('❌ 載入評審團錯誤:', error); if (retryCount < 2) { console.log('🔄 重試載入評審團...', retryCount + 1); setTimeout(() => loadCompetitionJudges(retryCount + 1), 1000); } else { setCompetitionJudges([]); } } }; loadCompetitionJudges(); } else { console.log('❌ useEffect 條件不滿足:', { open, competitionId: award.competitionId, hasCompetitionId: !!award.competitionId }); } }, [open, award.competitionId]); // 載入評分詳情 useEffect(() => { if (open && award.id) { const loadJudgeScores = async () => { try { setLoadingScores(true); console.log('🔍 載入評分詳情:', award.id); const response = await fetch(`/api/awards/${award.id}/scores`); const data = await response.json(); if (data.success) { console.log('✅ 載入評分詳情成功:', data.data.length, '筆'); setJudgeScores(data.data); } else { console.error('❌ 載入評分詳情失敗:', data.message); setJudgeScores([]); } } catch (error) { console.error('❌ 載入評分詳情錯誤:', error); setJudgeScores([]); } finally { setLoadingScores(false); } }; loadJudgeScores(); } else { setJudgeScores([]); } }, [open, award.id]); // 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) => { // 獲取當前照片數組 let photos = []; if (award.photos) { photos = award.photos; } else if (award.photos) { try { photos = typeof award.photos === 'string' ? JSON.parse(award.photos) : award.photos; } catch (e) { console.warn('解析 photos JSON 失敗:', e); photos = []; } } if (photos.length === 0) return 0; return (prev + 1) % photos.length; }) } const prevPhoto = () => { setCurrentPhotoIndex((prev) => { // 獲取當前照片數組 let photos = []; if (award.photos) { photos = award.photos; } else if (award.photos) { try { photos = typeof award.photos === 'string' ? JSON.parse(award.photos) : award.photos; } catch (e) { console.warn('解析 photos JSON 失敗:', e); photos = []; } } if (photos.length === 0) return 0; return (prev - 1 + photos.length) % photos.length; }) } const handlePreview = (report: any) => { // Open preview in new window window.open(report.previewUrl, "_blank") } const renderAwardOverview = () => (
{award.icon}
{award.awardName} {award.competitionType === "team" ? (award.teamName || award.appName || "團隊名稱") : (award.appName || award.proposalTitle || award.teamName) }
{getCompetitionTypeIcon(award.competitionType)} {getCompetitionTypeText(award.competitionType)} {award.awardName}
{award.score}
評審評分
{award.year}年{award.month}月
獲獎時間
{award.competitionType === "team" ? (award.appName || award.teamName || "應用名稱") : (award.teamName || award.creator || "創作者") }
{award.competitionType === "team" ? "應用名稱" : "創作者"}

競賽資訊

競賽名稱: {award.competitionName || competition?.name || '未知競賽'}

競賽描述: {award.competitionDescription || competition?.description || '暫無描述'}

競賽期間: {award.competitionStartDate && award.competitionEndDate ? `${new Date(award.competitionStartDate).toLocaleDateString('zh-TW', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '/')} ~ ${new Date(award.competitionEndDate).toLocaleDateString('zh-TW', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '/')}` : competition?.startDate && competition?.endDate ? `${new Date(competition.startDate).toLocaleDateString('zh-TW', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '/')} ~ ${new Date(competition.endDate).toLocaleDateString('zh-TW', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '/')}` : '暫無時間資訊' }

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

{/* App Links Section */} 應用連結 相關應用和資源連結
{(() => { // 解析 application_links 資料 let applicationLinks = null; if (award.applicationLinks) { applicationLinks = award.applicationLinks; } else if (award.application_links) { try { applicationLinks = typeof award.application_links === 'string' ? JSON.parse(award.application_links) : award.application_links; } catch (e) { console.error('解析 application_links 失敗:', e); } } if (!applicationLinks) { return (

暫無應用連結

); } return ( <> {applicationLinks.production && (

正式應用

APP 連結

)} {applicationLinks.demo && (

演示版本

體驗環境

)} {applicationLinks.github && (

源碼倉庫

GitHub

)} ); })()}
{/* Reports Section */} 相關報告 技術文檔和報告資料(僅供預覽)
{(() => { // 解析 documents 資料 let documents = []; if (award.documents) { documents = award.documents; } else if (award.documents) { try { documents = typeof award.documents === 'string' ? JSON.parse(award.documents) : award.documents; } catch (e) { console.error('解析 documents 失敗:', e); } } if (!documents || documents.length === 0) { return (

暫無相關文件

); } return documents.map((doc, index) => (
{getFileIcon(doc.type)}

{doc.name || doc.title}

{doc.description}

大小:{doc.size} 上傳:{doc.uploadDate || doc.upload_date} {doc.type}
{doc.previewUrl && ( )} {doc.downloadUrl && ( )} {doc.url && ( )}
)); })()}
) const renderJudgePanel = () => { // 確保 competitionJudges 是陣列 const judges = Array.isArray(competitionJudges) ? competitionJudges : []; if (judges.length === 0) { return ( 評審團 本次競賽的專業評審團隊

暫無評審信息

) } return ( 評審團 本次競賽的專業評審團隊
{judges.map((judge, index) => (
{judge.name ? judge.name[0] : 'J'}

{judge.name}

{judge.title}

{judge.expertise && judge.expertise.map((skill, skillIndex) => ( {skill} ))}
))}
) } const renderJudgeScores = () => { // 確保 judgeScores 是陣列 const scores = Array.isArray(judgeScores) ? judgeScores : []; return (
{/* Overall Statistics */} 評分統計 評審團整體評分概況 {loadingScores ? (

載入評分資料中...

) : scores.length === 0 ? (

暫無評分資料

) : (
{scores.length > 0 ? (scores.reduce((sum, score) => sum + Number(score.overallScore), 0) / scores.length).toFixed(1) : '0.0'}
平均分數
{scores.length > 0 ? Math.max(...scores.map((s) => Number(s.overallScore))).toFixed(1) : '0.0'}
最高分數
{scores.length > 0 ? Math.min(...scores.map((s) => Number(s.overallScore))).toFixed(1) : '0.0'}
最低分數
{scores.length}
評審人數
)}
{/* Individual Judge Scores */} {loadingScores ? (

載入評審評分中...

) : scores.length === 0 ? (

暫無評審評分資料

) : ( scores.map((judgeScore, index) => (
{judgeScore.judgeName[0]}
{judgeScore.judgeName} {judgeScore.judgeTitle}
{Number(judgeScore.overallScore).toFixed(1)} /100
評分時間:{new Date(judgeScore.submittedAt).toLocaleDateString('zh-TW', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '/')}
{/* Criteria Scores */}

評分細項

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

評審評語

{judgeScore.comment}

)) )}
) } const renderCompetitionPhotos = () => { // 解析 photos 資料 let photos = []; if (award.photos) { photos = award.photos; } else if (award.photos) { try { photos = typeof award.photos === 'string' ? JSON.parse(award.photos) : award.photos; } catch (e) { console.error('解析 photos 失敗:', e); } } console.log('🖼️ 競賽照片資料:', { hasPhotos: !!photos, photosType: typeof photos, photosLength: photos?.length, photosData: photos }); return ( 競賽照片 競賽活動精彩瞬間 {!photos || !Array.isArray(photos) || photos.length === 0 ? (

暫無競賽照片

) : (
{photos.map((photo: any, index: number) => { console.log('📸 處理照片:', { index, photo }); return (
{ setCurrentPhotoIndex(index); setShowPhotoGallery(true); }}> {photo.url ? ( {photo.caption { console.log('❌ 圖片載入失敗:', photo.url); e.currentTarget.style.display = 'none'; e.currentTarget.nextElementSibling?.classList.remove('hidden'); }} onLoad={() => { console.log('✅ 圖片載入成功:', photo.url); }} /> ) : (
🖼️
)}
🖼️
{(photo.caption || photo.name) && (

{photo.caption || photo.name}

)}
); })}
)}
); } return ( <> 得獎作品詳情 {award.competitionName} - {award.awardName}
獎項概覽 競賽照片 評審團 評分詳情 {renderAwardOverview()} {renderCompetitionPhotos()} {renderJudgePanel()} {renderJudgeScores()}
{/* Photo Gallery Modal */} {showPhotoGallery && (() => { // 解析 photos 資料 let photos = []; if (award.photos) { photos = award.photos; } else if (award.photos) { try { photos = typeof award.photos === 'string' ? JSON.parse(award.photos) : award.photos; } catch (e) { console.error('解析 photos 失敗:', e); } } if (!photos || !Array.isArray(photos) || photos.length === 0) { return null; } const currentPhoto = photos[isNaN(currentPhotoIndex) ? 0 : currentPhotoIndex]; return ( 照片畫廊
{/* Close Button */} {/* Main Photo */}
{currentPhoto?.url ? ( {currentPhoto.caption ) : (
🖼️
)} {/* Navigation Arrows */} {photos.length > 1 && ( <> )} {/* Photo Counter */}
{isNaN(currentPhotoIndex) ? 1 : currentPhotoIndex + 1} / {photos.length}
{/* Photo Caption */} {(currentPhoto?.caption || currentPhoto?.name) && (

{currentPhoto.caption || currentPhoto.name}

)} {/* Thumbnail Strip */} {photos.length > 1 && (
{photos.map((photo: any, index: number) => ( ))}
)}
); })()} ) }