新增競賽前台呈現、刪除競賽、修改競賽狀態
This commit is contained in:
@@ -20,6 +20,13 @@ import {
|
||||
Brain,
|
||||
Zap,
|
||||
ExternalLink,
|
||||
Bot,
|
||||
Code,
|
||||
Database,
|
||||
Palette,
|
||||
Volume2,
|
||||
Search,
|
||||
BarChart3,
|
||||
} from "lucide-react"
|
||||
import { useAuth } from "@/contexts/auth-context"
|
||||
import { LikeButton } from "@/components/like-button"
|
||||
@@ -31,22 +38,68 @@ interface TeamDetailDialogProps {
|
||||
team: any
|
||||
}
|
||||
|
||||
// App data for team apps - empty for production
|
||||
const getAppDetails = (appId: string) => {
|
||||
// 圖標映射函數
|
||||
const getIconComponent = (iconName: string) => {
|
||||
const iconMap: { [key: string]: any } = {
|
||||
'Brain': Brain,
|
||||
'Bot': Bot,
|
||||
'Code': Code,
|
||||
'Database': Database,
|
||||
'Palette': Palette,
|
||||
'Volume2': Volume2,
|
||||
'Search': Search,
|
||||
'BarChart3': BarChart3,
|
||||
'Mic': Mic,
|
||||
'ImageIcon': ImageIcon,
|
||||
'MessageSquare': MessageSquare,
|
||||
'Zap': Zap,
|
||||
'TrendingUp': TrendingUp,
|
||||
};
|
||||
|
||||
return iconMap[iconName] || Brain;
|
||||
}
|
||||
|
||||
// App data for team apps - get from team data
|
||||
const getAppDetails = (appId: string, team: any) => {
|
||||
const appDetail = team.appsDetails?.find((app: any) => app.id === appId);
|
||||
|
||||
if (appDetail) {
|
||||
return {
|
||||
id: appDetail.id,
|
||||
name: appDetail.name || "未命名應用",
|
||||
type: appDetail.type || "未知類型",
|
||||
description: appDetail.description || "無描述",
|
||||
icon: getIconComponent(appDetail.icon) || Brain,
|
||||
fullDescription: appDetail.description || "無描述",
|
||||
features: [],
|
||||
author: appDetail.creator_name || "未知作者",
|
||||
category: appDetail.category || "未分類",
|
||||
tags: [],
|
||||
demoUrl: "",
|
||||
sourceUrl: "",
|
||||
likes: appDetail.likes_count || 0,
|
||||
views: appDetail.views_count || 0,
|
||||
rating: Number(appDetail.rating) || 0
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: appId,
|
||||
name: "",
|
||||
type: "",
|
||||
description: "",
|
||||
icon: null,
|
||||
fullDescription: "",
|
||||
name: "未命名應用",
|
||||
type: "未知類型",
|
||||
description: "無描述",
|
||||
icon: Brain,
|
||||
fullDescription: "無描述",
|
||||
features: [],
|
||||
author: "",
|
||||
category: "",
|
||||
author: "未知作者",
|
||||
category: "未分類",
|
||||
tags: [],
|
||||
demoUrl: "",
|
||||
sourceUrl: "",
|
||||
}
|
||||
likes: 0,
|
||||
views: 0,
|
||||
rating: 0
|
||||
};
|
||||
}
|
||||
|
||||
const getTypeColor = (type: string) => {
|
||||
@@ -67,10 +120,10 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
|
||||
if (!team) return null
|
||||
|
||||
const leader = team.members.find((m: any) => m.id === team.leader)
|
||||
const leader = team.members.find((m: any) => m.user_id === team.leader)
|
||||
|
||||
const handleAppClick = (appId: string) => {
|
||||
const appDetails = getAppDetails(appId)
|
||||
const appDetails = getAppDetails(appId, team)
|
||||
// Create app object that matches AppDetailDialog interface
|
||||
const app = {
|
||||
id: Number.parseInt(appId),
|
||||
@@ -81,14 +134,17 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
icon: appDetails.icon,
|
||||
creator: appDetails.author,
|
||||
featured: false,
|
||||
judgeScore: 0,
|
||||
judgeScore: appDetails.rating || 0,
|
||||
likes: appDetails.likes || 0,
|
||||
views: appDetails.views || 0,
|
||||
}
|
||||
setSelectedApp(app)
|
||||
setAppDetailOpen(true)
|
||||
}
|
||||
|
||||
const totalLikes = team.apps.reduce((sum: number, appId: string) => sum + getLikeCount(appId), 0)
|
||||
const totalViews = team.apps.reduce((sum: number, appId: string) => sum + getViewCount(appId), 0)
|
||||
// 使用從數據庫獲取的真實數據
|
||||
const totalLikes = team.totalLikes || 0
|
||||
const totalViews = team.totalViews || 0
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -179,13 +235,13 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">團隊隊長</label>
|
||||
<p className="text-gray-900">{leader?.name}</p>
|
||||
<p className="text-gray-900">{leader?.name || '未指定'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">聯絡信箱</label>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Mail className="w-4 h-4 text-gray-500" />
|
||||
<p className="text-gray-900">{team.contactEmail}</p>
|
||||
<p className="text-gray-900">{team.contact_email || '未提供'}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -261,11 +317,12 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{team.apps.map((appId: string) => {
|
||||
const app = getAppDetails(appId)
|
||||
const IconComponent = app.icon
|
||||
const likes = getLikeCount(appId)
|
||||
const views = getViewCount(appId)
|
||||
const rating = getAppRating(appId)
|
||||
const app = getAppDetails(appId, team)
|
||||
// 如果沒有圖標,使用默認的 Brain 圖標
|
||||
const IconComponent = app.icon || Brain
|
||||
const likes = app.likes || 0
|
||||
const views = app.views || 0
|
||||
const rating = app.rating || 0
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -299,11 +356,16 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<Star className="w-3 h-3 text-yellow-500" />
|
||||
<span>{rating.toFixed(1)}</span>
|
||||
<span>{Number(rating).toFixed(1)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<LikeButton appId={appId} size="sm" />
|
||||
<LikeButton
|
||||
appId={appId}
|
||||
size="sm"
|
||||
likeCount={likes}
|
||||
showCount={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
Reference in New Issue
Block a user