Files
ai-showcase-platform/components/admin/judge-list-dialog.tsx
2025-09-18 18:34:31 +08:00

181 lines
7.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Badge } from "@/components/ui/badge"
import { Copy, Users } from "lucide-react"
import { useToast } from "@/hooks/use-toast"
interface Judge {
id: string
name: string
specialty: string
expertise?: string[]
title?: string
department?: string
email?: string
phone?: string
organization?: string
totalScores?: number
completedScores?: number
}
interface JudgeListDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
judges: Judge[]
}
export function JudgeListDialog({ open, onOpenChange, judges }: JudgeListDialogProps) {
const { toast } = useToast()
const handleCopyJudgeId = async (judgeId: string, judgeName: string) => {
try {
await navigator.clipboard.writeText(judgeId)
toast({
title: "ID已複製",
description: `${judgeName}的ID已複製到剪貼簿`,
})
} catch (err) {
toast({
title: "複製失敗",
description: "無法複製ID請手動複製",
variant: "destructive",
})
}
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="flex items-center space-x-2">
<Users className="w-5 h-5" />
<span></span>
</DialogTitle>
<DialogDescription>
ID和基本資訊
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
{judges.length === 0 ? (
<div className="text-center py-8">
<Users className="w-12 h-12 mx-auto text-gray-400 mb-4" />
<p className="text-gray-500"></p>
</div>
) : (
judges.map((judge) => (
<Card key={judge.id} className="hover:shadow-md transition-shadow">
<CardContent className="p-6">
<div className="flex items-start justify-between">
{/* 左側:頭像和基本資訊 */}
<div className="flex items-start space-x-4">
<Avatar className="w-14 h-14">
<AvatarFallback className="text-lg font-semibold bg-blue-100 text-blue-700">
{judge.name.charAt(0)}
</AvatarFallback>
</Avatar>
<div className="flex-1">
<h3 className="font-semibold text-xl mb-1">{judge.name}</h3>
<p className="text-sm text-gray-600 mb-2">{judge.specialty}</p>
{/* 職位和部門 */}
{(judge.title && judge.title !== judge.name) || judge.department ? (
<div className="flex items-center space-x-2 mb-3">
{judge.title && judge.title !== judge.name && (
<Badge variant="secondary" className="text-xs">
{judge.title}
</Badge>
)}
{judge.department && (
<span className="text-xs text-gray-500">
{judge.department}
</span>
)}
</div>
) : null}
{/* 評審能力 */}
{judge.expertise && judge.expertise.length > 0 && (
<div className="mb-3">
<p className="text-sm font-medium text-gray-700 mb-2"></p>
<div className="flex flex-wrap gap-1">
{judge.expertise.map((skill, index) => (
<Badge
key={index}
variant="outline"
className="text-xs bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100"
>
{skill}
</Badge>
))}
</div>
</div>
)}
{/* 額外資訊 */}
<div className="space-y-1 text-sm text-gray-500">
{judge.organization && (
<p>🏢 {judge.organization}</p>
)}
{judge.email && (
<p>📧 {judge.email}</p>
)}
{judge.phone && (
<p>📞 {judge.phone}</p>
)}
</div>
{/* 評分進度 */}
{judge.totalScores !== undefined && judge.completedScores !== undefined && (
<div className="mt-3">
<div className="flex items-center justify-between text-sm mb-1">
<span className="text-gray-600"></span>
<span className="font-medium">
{judge.completedScores}/{judge.totalScores}
</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
style={{
width: `${judge.totalScores > 0 ? (judge.completedScores / judge.totalScores) * 100 : 0}%`
}}
/>
</div>
</div>
)}
</div>
</div>
{/* 右側ID和操作按鈕 */}
<div className="flex flex-col items-end space-y-3">
<div className="bg-gray-100 px-4 py-2 rounded-lg">
<span className="text-sm font-medium text-gray-700">
ID: {judge.id}
</span>
</div>
<Button
onClick={() => handleCopyJudgeId(judge.id, judge.name)}
variant="outline"
size="sm"
className="flex items-center space-x-2"
>
<Copy className="w-4 h-4" />
<span>ID</span>
</Button>
</div>
</div>
</CardContent>
</Card>
))
)}
</div>
</DialogContent>
</Dialog>
)
}