修正競賽團隊編輯、個人賽顯示、團體賽顯示 bug
This commit is contained in:
@@ -703,6 +703,7 @@ export function CompetitionManagement() {
|
||||
fetchJudgeStats()
|
||||
fetchTeams()
|
||||
fetchTeamStats()
|
||||
fetchAvailableApps()
|
||||
}, [])
|
||||
|
||||
// 當競賽列表載入完成後,載入每個競賽的評分進度
|
||||
@@ -859,11 +860,33 @@ export function CompetitionManagement() {
|
||||
|
||||
// Get participants based on competition type
|
||||
const getParticipants = (competitionType: string) => {
|
||||
console.log('🔍 getParticipants 調用:', {
|
||||
competitionType,
|
||||
dbTeamsLength: dbTeams.length,
|
||||
teamsLength: teams.length,
|
||||
isLoadingTeams
|
||||
})
|
||||
switch (competitionType) {
|
||||
case "individual":
|
||||
return mockIndividualApps
|
||||
console.log('🔍 個人賽APP數據:', {
|
||||
availableAppsLength: availableApps.length,
|
||||
availableApps: availableApps.slice(0, 2)
|
||||
})
|
||||
return availableApps
|
||||
case "team":
|
||||
return dbTeams.length > 0 ? dbTeams : teams
|
||||
// 總是使用 dbTeams,如果為空則返回空數組
|
||||
console.log('🔍 getParticipants 團隊數據:', {
|
||||
dbTeamsLength: dbTeams.length,
|
||||
dbTeams: dbTeams.slice(0, 2), // 只顯示前2個
|
||||
firstTeam: dbTeams[0] ? {
|
||||
id: dbTeams[0].id,
|
||||
name: dbTeams[0].name,
|
||||
leader_name: dbTeams[0].leader_name,
|
||||
member_count: dbTeams[0].member_count,
|
||||
submissionDate: dbTeams[0].submissionDate
|
||||
} : null
|
||||
})
|
||||
return dbTeams
|
||||
default:
|
||||
return []
|
||||
}
|
||||
@@ -875,15 +898,22 @@ export function CompetitionManagement() {
|
||||
let searchTerm = participantSearchTerm
|
||||
let departmentFilterValue = departmentFilter
|
||||
|
||||
console.log('🔍 getFilteredParticipants 調用:', {
|
||||
competitionType,
|
||||
participantsLength: participants.length,
|
||||
searchTerm,
|
||||
departmentFilterValue
|
||||
})
|
||||
|
||||
// Use separate search terms for mixed competitions
|
||||
if (newCompetition.type === "mixed") {
|
||||
searchTerm = competitionType === "individual" ? individualParticipantSearchTerm : teamParticipantSearchTerm
|
||||
departmentFilterValue = competitionType === "individual" ? individualDepartmentFilter : teamDepartmentFilter
|
||||
}
|
||||
|
||||
return participants.filter((participant) => {
|
||||
const filtered = participants.filter((participant) => {
|
||||
const searchField = competitionType === "team" ? participant.name : participant.name
|
||||
const creatorField = competitionType === "team" ? participant.leader : participant.creator
|
||||
const creatorField = competitionType === "team" ? (participant.leader_name || participant.leader) : (participant.creator_name || participant.creator_id || participant.creator)
|
||||
|
||||
const matchesSearch =
|
||||
searchField.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
@@ -891,6 +921,21 @@ export function CompetitionManagement() {
|
||||
const matchesDepartment = departmentFilterValue === "all" || participant.department === departmentFilterValue
|
||||
return matchesSearch && matchesDepartment
|
||||
})
|
||||
|
||||
console.log('🔍 getFilteredParticipants 結果:', {
|
||||
competitionType,
|
||||
filteredLength: filtered.length,
|
||||
filtered: filtered.slice(0, 2).map(f => ({
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
leader_name: f.leader_name,
|
||||
leader: f.leader,
|
||||
member_count: f.member_count,
|
||||
submissionDate: f.submissionDate
|
||||
}))
|
||||
})
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
@@ -2522,7 +2567,7 @@ export function CompetitionManagement() {
|
||||
<TableRow key={competition.id} className={isCurrentCompetition ? "bg-purple-50" : ""}>
|
||||
<TableCell>
|
||||
<div className="flex items-center space-x-2">
|
||||
{isCurrentCompetition && <Star className="w-4 h-4 text-purple-600 fill-current" />}
|
||||
{isCurrentCompetition && <Star className="w-12 h-12 text-purple-600 fill-current" />}
|
||||
<div>
|
||||
<p className="font-medium">{competition.name}</p>
|
||||
<p className="text-sm text-gray-500">{competition.description}</p>
|
||||
@@ -3092,6 +3137,7 @@ export function CompetitionManagement() {
|
||||
const matchesExpertise = judgeExpertiseFilter === "all" ||
|
||||
judge.expertise.some(exp => exp.includes(judgeExpertiseFilter))
|
||||
|
||||
|
||||
const matchesStatus = judgeStatusFilter === "all" ||
|
||||
(judgeStatusFilter === "active" && judge.is_active === true) ||
|
||||
(judgeStatusFilter === "inactive" && judge.is_active === false)
|
||||
@@ -3124,7 +3170,7 @@ export function CompetitionManagement() {
|
||||
<CardContent className="p-4">
|
||||
<div className="flex items-center space-x-3 mb-3">
|
||||
<Avatar>
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className={`${!judge.is_active ? 'bg-orange-100 text-orange-700' : 'bg-purple-100 text-purple-700'}`}>
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -3974,7 +4020,7 @@ export function CompetitionManagement() {
|
||||
}}
|
||||
/>
|
||||
<Avatar className="w-8 h-8">
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-blue-100 text-blue-700 text-sm">
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -4386,7 +4432,7 @@ export function CompetitionManagement() {
|
||||
}}
|
||||
/>
|
||||
<Avatar className="w-8 h-8">
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-green-100 text-green-700 text-sm">
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -4789,7 +4835,7 @@ export function CompetitionManagement() {
|
||||
}}
|
||||
/>
|
||||
<Avatar className="w-8 h-8">
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700 text-sm">
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -5205,8 +5251,8 @@ export function CompetitionManagement() {
|
||||
{participant.department}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600 mt-1">創作者:{participant.creator}</p>
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate || participant.created_at || '未知'}</p>
|
||||
<p className="text-xs text-gray-600 mt-1">創作者:{participant.creator_name || participant.creator_id || participant.creator || '未知'}</p>
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate ? new Date(participant.submissionDate).toLocaleDateString('zh-TW', { timeZone: 'Asia/Taipei', year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/-/g, '/') : '未知'}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -5263,8 +5309,32 @@ export function CompetitionManagement() {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 max-h-64 overflow-y-auto border rounded-lg p-4 bg-white">
|
||||
{getFilteredParticipants("team").map((participant) => {
|
||||
{isLoadingTeams ? (
|
||||
<div className="col-span-2 flex items-center justify-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-2"></div>
|
||||
<p className="text-sm text-gray-600">載入團隊數據中...</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
getFilteredParticipants("team").map((participant) => {
|
||||
const isSelected = newCompetition.participatingTeams.includes(participant.id)
|
||||
console.log('🔍 團隊數據調試 - 完整對象:', participant)
|
||||
console.log('🔍 團隊數據調試 - 關鍵欄位:', {
|
||||
name: participant.name,
|
||||
leader_name: participant.leader_name,
|
||||
leader: participant.leader,
|
||||
member_count: participant.member_count,
|
||||
submissionDate: participant.submissionDate,
|
||||
hasLeaderName: 'leader_name' in participant,
|
||||
hasMemberCount: 'member_count' in participant,
|
||||
allKeys: Object.keys(participant)
|
||||
})
|
||||
console.log('🔍 渲染測試:', {
|
||||
leaderDisplay: participant.leader_name || participant.leader || '未知',
|
||||
memberDisplay: participant.member_count || participant.memberCount || 0,
|
||||
dateDisplay: participant.submissionDate ? new Date(participant.submissionDate).toLocaleDateString('zh-TW', { timeZone: 'Asia/Taipei', year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/-/g, '/') : '未知'
|
||||
})
|
||||
return (
|
||||
<div
|
||||
key={participant.id}
|
||||
@@ -5318,11 +5388,12 @@ export function CompetitionManagement() {
|
||||
{participant.description && (
|
||||
<p className="text-xs text-gray-500 line-clamp-2">{participant.description}</p>
|
||||
)}
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate || participant.created_at || '未知'}</p>
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate ? new Date(participant.submissionDate).toLocaleDateString('zh-TW', { timeZone: 'Asia/Taipei', year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/-/g, '/') : '未知'}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 bg-green-100 rounded-lg">
|
||||
@@ -5432,11 +5503,11 @@ export function CompetitionManagement() {
|
||||
<div className="flex items-center space-x-4 text-xs text-gray-600">
|
||||
<div className="flex items-center space-x-1">
|
||||
<User className="w-3 h-3" />
|
||||
<span>隊長:{participant.leader}</span>
|
||||
<span>隊長:{participant.leader_name || participant.leader || '未知'}</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<Users className="w-3 h-3" />
|
||||
<span>{participant.memberCount}人</span>
|
||||
<span>{participant.member_count || participant.memberCount || 0}人</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5497,10 +5568,16 @@ export function CompetitionManagement() {
|
||||
|
||||
{/* Individual information */}
|
||||
{newCompetition.type === "individual" && (
|
||||
<p className="text-xs text-gray-600 mt-1">創作者:{participant.creator}</p>
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs text-gray-600">創作者:{participant.creator_name || participant.creator_id || participant.creator || '未知'}</p>
|
||||
<p className="text-xs text-gray-500">類型:{participant.type || participant.category || '未知'}</p>
|
||||
{participant.description && (
|
||||
<p className="text-xs text-gray-500 line-clamp-2">{participant.description}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate}</p>
|
||||
<p className="text-xs text-gray-500">提交日期:{participant.submissionDate ? new Date(participant.submissionDate).toLocaleDateString('zh-TW', { timeZone: 'Asia/Taipei', year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/-/g, '/') : '未知'}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@@ -60,10 +60,15 @@ export function TeamManagement() {
|
||||
|
||||
const [newMember, setNewMember] = useState({
|
||||
name: "",
|
||||
user_id: "",
|
||||
department: "HQBU",
|
||||
role: "成員",
|
||||
})
|
||||
|
||||
// 可用用戶狀態
|
||||
const [availableUsers, setAvailableUsers] = useState<any[]>([])
|
||||
const [isLoadingUsers, setIsLoadingUsers] = useState(false)
|
||||
|
||||
// 獲取團隊數據
|
||||
const fetchTeams = async () => {
|
||||
try {
|
||||
@@ -87,8 +92,30 @@ export function TeamManagement() {
|
||||
|
||||
useEffect(() => {
|
||||
fetchTeams()
|
||||
fetchAvailableUsers()
|
||||
}, [])
|
||||
|
||||
// 獲取可用用戶列表
|
||||
const fetchAvailableUsers = async () => {
|
||||
try {
|
||||
setIsLoadingUsers(true)
|
||||
const response = await fetch('/api/admin/users/available')
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
setAvailableUsers(data.data)
|
||||
} else {
|
||||
console.error('獲取用戶列表失敗:', data.message)
|
||||
setError('獲取用戶列表失敗')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('獲取用戶列表失敗:', error)
|
||||
setError('獲取用戶列表失敗')
|
||||
} finally {
|
||||
setIsLoadingUsers(false)
|
||||
}
|
||||
}
|
||||
|
||||
const filteredTeams = apiTeams.filter((team) => {
|
||||
const matchesSearch =
|
||||
team.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
@@ -102,31 +129,46 @@ export function TeamManagement() {
|
||||
setShowTeamDetail(true)
|
||||
}
|
||||
|
||||
const handleEditTeam = (team: any) => {
|
||||
const handleEditTeam = async (team: any) => {
|
||||
setSelectedTeam(team)
|
||||
|
||||
// 確保成員數據結構正確
|
||||
const members = team.members && Array.isArray(team.members)
|
||||
? team.members.map((member: any) => ({
|
||||
id: member.user_id || member.id,
|
||||
user_id: member.user_id || member.id,
|
||||
name: member.name,
|
||||
department: member.department,
|
||||
role: member.role || '成員'
|
||||
}))
|
||||
: []
|
||||
|
||||
setNewTeam({
|
||||
name: team.name,
|
||||
department: team.department,
|
||||
contactEmail: team.contact_email || team.contactEmail,
|
||||
description: team.description || '',
|
||||
members: members,
|
||||
leader: team.leader_id || team.leader,
|
||||
apps: team.apps || [],
|
||||
totalLikes: team.total_likes || team.totalLikes || 0,
|
||||
})
|
||||
setShowEditTeam(true)
|
||||
try {
|
||||
// 獲取團隊的詳細信息,包括成員
|
||||
const response = await fetch(`/api/admin/teams/${team.id}`)
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
const teamDetails = data.data
|
||||
|
||||
// 確保成員數據結構正確
|
||||
const members = teamDetails.members && Array.isArray(teamDetails.members)
|
||||
? teamDetails.members.map((member: any) => ({
|
||||
id: member.user_id || member.id,
|
||||
user_id: member.user_id || member.id,
|
||||
name: member.name,
|
||||
department: member.department,
|
||||
role: member.role || '成員'
|
||||
}))
|
||||
: []
|
||||
|
||||
setNewTeam({
|
||||
name: teamDetails.name,
|
||||
department: teamDetails.department,
|
||||
contactEmail: teamDetails.contact_email || teamDetails.contactEmail,
|
||||
description: teamDetails.description || '',
|
||||
members: members,
|
||||
leader: teamDetails.leader_id || teamDetails.leader,
|
||||
apps: teamDetails.apps || [],
|
||||
totalLikes: teamDetails.total_likes || teamDetails.totalLikes || 0,
|
||||
})
|
||||
setShowEditTeam(true)
|
||||
} else {
|
||||
setError('獲取團隊詳情失敗')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('獲取團隊詳情失敗:', error)
|
||||
setError('獲取團隊詳情失敗')
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeleteTeam = (team: Team) => {
|
||||
@@ -145,13 +187,20 @@ export function TeamManagement() {
|
||||
}
|
||||
|
||||
const handleAddMember = () => {
|
||||
if (!newMember.name.trim()) {
|
||||
setError("請輸入成員姓名")
|
||||
if (!newMember.user_id || !newMember.name.trim()) {
|
||||
setError("請選擇成員")
|
||||
return
|
||||
}
|
||||
|
||||
// 檢查是否已經添加過這個成員
|
||||
if (newTeam.members.some(member => member.user_id === newMember.user_id)) {
|
||||
setError("該成員已經在團隊中")
|
||||
return
|
||||
}
|
||||
|
||||
const member: TeamMember = {
|
||||
id: `m${Date.now()}`,
|
||||
id: newMember.user_id, // 使用真實的用戶 ID
|
||||
user_id: newMember.user_id,
|
||||
name: newMember.name,
|
||||
department: newMember.department,
|
||||
role: newMember.role,
|
||||
@@ -173,6 +222,7 @@ export function TeamManagement() {
|
||||
|
||||
setNewMember({
|
||||
name: "",
|
||||
user_id: "",
|
||||
department: "HQBU",
|
||||
role: "成員",
|
||||
})
|
||||
@@ -262,6 +312,9 @@ export function TeamManagement() {
|
||||
}))
|
||||
}
|
||||
|
||||
console.log('🔍 準備更新的團隊數據:', updateData)
|
||||
console.log('🔍 成員數據:', newTeam.members)
|
||||
|
||||
// 調用 API 更新團隊
|
||||
const response = await fetch(`/api/admin/teams/${selectedTeam.id}`, {
|
||||
method: 'PUT',
|
||||
@@ -731,13 +784,30 @@ export function TeamManagement() {
|
||||
<h4 className="font-semibold">新增成員</h4>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="editMemberName">成員姓名</Label>
|
||||
<Input
|
||||
id="editMemberName"
|
||||
value={newMember.name}
|
||||
onChange={(e) => setNewMember({ ...newMember, name: e.target.value })}
|
||||
placeholder="輸入成員姓名"
|
||||
/>
|
||||
<Label htmlFor="editMemberSelect">選擇成員</Label>
|
||||
<Select
|
||||
value={newMember.user_id}
|
||||
onValueChange={(value) => {
|
||||
const selectedUser = availableUsers.find(user => user.id === value)
|
||||
setNewMember({
|
||||
...newMember,
|
||||
user_id: value,
|
||||
name: selectedUser?.name || "",
|
||||
department: selectedUser?.department || "HQBU"
|
||||
})
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="選擇團隊成員" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{availableUsers.map((user) => (
|
||||
<SelectItem key={user.id} value={user.id}>
|
||||
{user.name} ({user.department})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="editMemberDepartment">部門</Label>
|
||||
|
@@ -79,7 +79,7 @@ export function ProfileDialog({ open, onOpenChange }: ProfileDialogProps) {
|
||||
<div className="flex items-center space-x-6">
|
||||
<div className="relative">
|
||||
<Avatar className="w-24 h-24">
|
||||
<AvatarImage src={user?.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={user?.avatar} />
|
||||
<AvatarFallback className="text-2xl bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
{user?.name?.charAt(0) || "U"}
|
||||
</AvatarFallback>
|
||||
|
@@ -427,7 +427,7 @@ export function AwardDetailDialog({ open, onOpenChange, award }: AwardDetailDial
|
||||
return (
|
||||
<div key={judge.id} className="flex items-center space-x-3 p-3 bg-gray-50 rounded-lg">
|
||||
<Avatar>
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg?height=40&width=40"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700">{judge.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
@@ -495,7 +495,7 @@ export function AwardDetailDialog({ open, onOpenChange, award }: AwardDetailDial
|
||||
<CardHeader>
|
||||
<div className="flex items-center space-x-4">
|
||||
<Avatar className="w-12 h-12">
|
||||
<AvatarImage src={judgeScore.judgeAvatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judgeScore.judgeAvatar} />
|
||||
<AvatarFallback className="bg-blue-100 text-blue-700">{judgeScore.judgeName[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
|
@@ -192,7 +192,7 @@ export function CompetitionDetailDialog({
|
||||
<div key={score.judgeId} className="border rounded-lg p-6">
|
||||
<div className="flex items-center space-x-4 mb-4">
|
||||
<Avatar className="w-12 h-12">
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700 text-lg">
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -377,7 +377,7 @@ export function CompetitionDetailDialog({
|
||||
>
|
||||
<div className="flex items-center space-x-3">
|
||||
<Avatar>
|
||||
<AvatarImage src={`/placeholder-40x40.png?height=40&width=40&text=${member.name[0]}`} />
|
||||
<AvatarImage src={member.avatar} />
|
||||
<AvatarFallback className="bg-green-100 text-green-700">{member.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
@@ -586,7 +586,7 @@ export function CompetitionDetailDialog({
|
||||
<div key={score.judgeId} className="border rounded-lg p-6">
|
||||
<div className="flex items-center space-x-4 mb-4">
|
||||
<Avatar className="w-12 h-12">
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700 text-lg">
|
||||
{judge.name[0]}
|
||||
</AvatarFallback>
|
||||
@@ -677,7 +677,7 @@ export function CompetitionDetailDialog({
|
||||
>
|
||||
<div className="flex items-center space-x-3">
|
||||
<Avatar>
|
||||
<AvatarImage src={`/placeholder-40x40.png?height=40&width=40&text=${member.name[0]}`} />
|
||||
<AvatarImage src={member.avatar} />
|
||||
<AvatarFallback className="bg-green-100 text-green-700">{member.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
|
@@ -145,7 +145,7 @@ export function JudgeScoringDialog({ open, onOpenChange, appId, appName, judgeId
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Avatar>
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700">{judge.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
|
@@ -693,7 +693,7 @@ export function PopularityRankings() {
|
||||
{competitionJudges.map((judge) => (
|
||||
<div key={judge.id} className="flex items-center space-x-3 p-3 bg-gray-50 rounded-lg">
|
||||
<Avatar>
|
||||
<AvatarImage src={judge.avatar || "/placeholder.svg"} />
|
||||
<AvatarImage src={judge.avatar} />
|
||||
<AvatarFallback className="bg-purple-100 text-purple-700">{judge.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1">
|
||||
|
@@ -309,7 +309,7 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
{team.members.map((member: any, index: number) => (
|
||||
<div key={member.id} className="flex items-center space-x-3 p-4 border rounded-lg">
|
||||
<Avatar className="w-12 h-12">
|
||||
<AvatarImage src={`/placeholder-40x40.png`} />
|
||||
<AvatarImage src={member.avatar} />
|
||||
<AvatarFallback className="bg-green-100 text-green-700 font-medium">
|
||||
{member.name[0]}
|
||||
</AvatarFallback>
|
||||
|
Reference in New Issue
Block a user