競賽資訊完整版 ( 只剩評分、競賽得獎 )
This commit is contained in:
@@ -77,8 +77,8 @@ export async function GET(request: NextRequest, { params }: { params: { id: stri
|
|||||||
likes_count: app.likes_count || 0,
|
likes_count: app.likes_count || 0,
|
||||||
views_count: app.views_count || 0,
|
views_count: app.views_count || 0,
|
||||||
rating: Math.round(avgRating * 10) / 10, // 四捨五入到小數點後一位
|
rating: Math.round(avgRating * 10) / 10, // 四捨五入到小數點後一位
|
||||||
creator_name: "未知作者",
|
creator_name: app.creator_name || "未知作者",
|
||||||
creator_department: "未知部門",
|
creator_department: app.creator_department || "未知部門",
|
||||||
team_name: team.name,
|
team_name: team.name,
|
||||||
created_at: app.created_at
|
created_at: app.created_at
|
||||||
};
|
};
|
||||||
|
@@ -39,6 +39,11 @@ import {
|
|||||||
Trophy,
|
Trophy,
|
||||||
Award,
|
Award,
|
||||||
Medal,
|
Medal,
|
||||||
|
Bot,
|
||||||
|
Code,
|
||||||
|
Database,
|
||||||
|
Palette,
|
||||||
|
Volume2,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { FavoriteButton } from "./favorite-button"
|
import { FavoriteButton } from "./favorite-button"
|
||||||
import { ReviewSystem } from "./reviews/review-system"
|
import { ReviewSystem } from "./reviews/review-system"
|
||||||
@@ -48,15 +53,21 @@ interface AppDetailDialogProps {
|
|||||||
open: boolean
|
open: boolean
|
||||||
onOpenChange: (open: boolean) => void
|
onOpenChange: (open: boolean) => void
|
||||||
app: {
|
app: {
|
||||||
id: number
|
id: string
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
department: string
|
department: string
|
||||||
description: string
|
description: string
|
||||||
icon: any
|
icon: any
|
||||||
|
iconColor?: string
|
||||||
creator: string
|
creator: string
|
||||||
featured: boolean
|
featured: boolean
|
||||||
judgeScore: number
|
judgeScore: number
|
||||||
|
likesCount?: number
|
||||||
|
viewsCount?: number
|
||||||
|
rating?: number
|
||||||
|
reviewsCount?: number
|
||||||
|
createdAt?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,11 +123,17 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
|
|||||||
// 圖標映射函數
|
// 圖標映射函數
|
||||||
const getIconComponent = (iconName: string) => {
|
const getIconComponent = (iconName: string) => {
|
||||||
const iconMap: { [key: string]: any } = {
|
const iconMap: { [key: string]: any } = {
|
||||||
'Bot': Brain,
|
'Brain': Brain,
|
||||||
'ImageIcon': ImageIcon,
|
'Bot': Bot,
|
||||||
|
'Code': Code,
|
||||||
|
'Database': Database,
|
||||||
|
'Palette': Palette,
|
||||||
|
'Volume2': Volume2,
|
||||||
|
'Search': Search,
|
||||||
|
'BarChart3': BarChart3,
|
||||||
'Mic': Mic,
|
'Mic': Mic,
|
||||||
|
'ImageIcon': ImageIcon,
|
||||||
'MessageSquare': MessageSquare,
|
'MessageSquare': MessageSquare,
|
||||||
'Settings': Settings,
|
|
||||||
'Zap': Zap,
|
'Zap': Zap,
|
||||||
'TrendingUp': TrendingUp,
|
'TrendingUp': TrendingUp,
|
||||||
'Star': Star,
|
'Star': Star,
|
||||||
@@ -128,21 +145,23 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
|
|||||||
'Target': Target,
|
'Target': Target,
|
||||||
'Users': Users,
|
'Users': Users,
|
||||||
'Lightbulb': Lightbulb,
|
'Lightbulb': Lightbulb,
|
||||||
'Search': Search,
|
|
||||||
'Plus': Plus,
|
'Plus': Plus,
|
||||||
'X': X,
|
'X': X,
|
||||||
'ChevronLeft': ChevronLeft,
|
'ChevronLeft': ChevronLeft,
|
||||||
'ChevronRight': ChevronRight,
|
'ChevronRight': ChevronRight,
|
||||||
'ArrowLeft': ArrowLeft
|
'ArrowLeft': ArrowLeft,
|
||||||
|
'Settings': Settings
|
||||||
}
|
}
|
||||||
return iconMap[iconName] || Brain // 預設使用 Brain 圖標
|
return iconMap[iconName] || Brain // 預設使用 Brain 圖標
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconComponent = getIconComponent(app.icon || 'Bot')
|
const IconComponent = getIconComponent(app.icon || 'Bot')
|
||||||
const likes = (app as any).likesCount || 0
|
// 優先使用從 API 載入的實際數據,如果沒有則使用 app 對象的數據
|
||||||
const views = (app as any).viewsCount || 0
|
const likes = appStats.basic?.likes || (app as any).likesCount || 0
|
||||||
const rating = (app as any).rating || 0
|
const views = appStats.basic?.views || (app as any).viewsCount || 0
|
||||||
const reviewsCount = (app as any).reviewsCount || 0
|
const rating = appStats.basic?.rating || (app as any).rating || 0
|
||||||
|
const reviewsCount = appStats.basic?.reviewCount || (app as any).reviewsCount || 0
|
||||||
|
const favorites = appStats.basic?.favorites || 0
|
||||||
// 使用從 API 載入的實際數據
|
// 使用從 API 載入的實際數據
|
||||||
const usageStats = appStats.usage
|
const usageStats = appStats.usage
|
||||||
|
|
||||||
@@ -169,13 +188,27 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
|
|||||||
if (department) params.append('department', department)
|
if (department) params.append('department', department)
|
||||||
|
|
||||||
const url = `/api/apps/${app.id}/stats${params.toString() ? `?${params.toString()}` : ''}`
|
const url = `/api/apps/${app.id}/stats${params.toString() ? `?${params.toString()}` : ''}`
|
||||||
|
console.log('🔍 調用統計 API:', url)
|
||||||
|
console.log('🔍 應用 ID:', app.id)
|
||||||
|
|
||||||
const response = await fetch(url)
|
const response = await fetch(url)
|
||||||
|
console.log('🔍 API 響應狀態:', response.status, response.statusText)
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error('❌ API 響應錯誤:', response.status, response.statusText)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
console.log('🔍 API 響應數據:', data)
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
|
console.log('📊 應用統計數據加載成功:', data.data)
|
||||||
setAppStats(data.data)
|
setAppStats(data.data)
|
||||||
setCurrentRating(data.data.basic.rating)
|
setCurrentRating(data.data.basic.rating)
|
||||||
setReviewCount(data.data.basic.reviewCount)
|
setReviewCount(data.data.basic.reviewCount)
|
||||||
|
} else {
|
||||||
|
console.error('❌ 應用統計數據加載失敗:', data)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('載入應用統計數據錯誤:', error)
|
console.error('載入應用統計數據錯誤:', error)
|
||||||
@@ -489,7 +522,7 @@ export function AppDetailDialog({ open, onOpenChange, app }: AppDetailDialogProp
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold text-purple-600">
|
<div className="text-2xl font-bold text-purple-600">
|
||||||
{isLoadingStats ? '...' : (appStats.basic as any).favorites || 0}
|
{isLoadingStats ? '...' : favorites}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">用戶收藏數量</p>
|
<p className="text-xs text-muted-foreground">用戶收藏數量</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
@@ -70,16 +70,19 @@ const getAppDetails = (appId: string, team: any) => {
|
|||||||
type: appDetail.type || "未知類型",
|
type: appDetail.type || "未知類型",
|
||||||
description: appDetail.description || "無描述",
|
description: appDetail.description || "無描述",
|
||||||
icon: getIconComponent(appDetail.icon) || Brain,
|
icon: getIconComponent(appDetail.icon) || Brain,
|
||||||
|
iconColor: appDetail.icon_color || "from-blue-500 to-purple-500",
|
||||||
fullDescription: appDetail.description || "無描述",
|
fullDescription: appDetail.description || "無描述",
|
||||||
features: [],
|
features: [],
|
||||||
author: appDetail.creator_name || "未知作者",
|
author: appDetail.creator_name || "未知作者",
|
||||||
|
department: appDetail.creator_department || "未知部門",
|
||||||
category: appDetail.category || "未分類",
|
category: appDetail.category || "未分類",
|
||||||
tags: [],
|
tags: [],
|
||||||
demoUrl: "",
|
demoUrl: "",
|
||||||
sourceUrl: "",
|
sourceUrl: "",
|
||||||
likes: appDetail.likes_count || 0,
|
likes: appDetail.likes_count || 0,
|
||||||
views: appDetail.views_count || 0,
|
views: appDetail.views_count || 0,
|
||||||
rating: Number(appDetail.rating) || 0
|
rating: Number(appDetail.rating) || 0,
|
||||||
|
createdAt: appDetail.created_at
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,17 +129,22 @@ export function TeamDetailDialog({ open, onOpenChange, team }: TeamDetailDialogP
|
|||||||
const appDetails = getAppDetails(appId, team)
|
const appDetails = getAppDetails(appId, team)
|
||||||
// Create app object that matches AppDetailDialog interface
|
// Create app object that matches AppDetailDialog interface
|
||||||
const app = {
|
const app = {
|
||||||
id: Number.parseInt(appId),
|
id: appId, // 保持為字符串,API 期望字符串 ID
|
||||||
name: appDetails.name,
|
name: appDetails.name,
|
||||||
type: appDetails.type,
|
type: appDetails.type,
|
||||||
department: team.department, // Use team's department
|
department: appDetails.department, // Use app's creator department
|
||||||
description: appDetails.description,
|
description: appDetails.description,
|
||||||
icon: appDetails.icon,
|
icon: appDetails.icon,
|
||||||
|
iconColor: appDetails.iconColor, // Pass icon color
|
||||||
creator: appDetails.author,
|
creator: appDetails.author,
|
||||||
featured: false,
|
featured: false,
|
||||||
judgeScore: appDetails.rating || 0,
|
judgeScore: appDetails.rating || 0,
|
||||||
likes: appDetails.likes || 0,
|
// 使用 AppDetailDialog 期望的屬性名
|
||||||
views: appDetails.views || 0,
|
likesCount: appDetails.likes || 0,
|
||||||
|
viewsCount: appDetails.views || 0,
|
||||||
|
rating: appDetails.rating || 0,
|
||||||
|
reviewsCount: 0, // 可以從 API 獲取,暫時設為 0
|
||||||
|
createdAt: appDetails.createdAt, // Pass creation date
|
||||||
}
|
}
|
||||||
setSelectedApp(app)
|
setSelectedApp(app)
|
||||||
setAppDetailOpen(true)
|
setAppDetailOpen(true)
|
||||||
|
@@ -1151,10 +1151,14 @@ export class TeamService {
|
|||||||
static async getTeamApps(teamId: string): Promise<any[]> {
|
static async getTeamApps(teamId: string): Promise<any[]> {
|
||||||
console.log('🔍 TeamService.getTeamApps 被調用, teamId:', teamId);
|
console.log('🔍 TeamService.getTeamApps 被調用, teamId:', teamId);
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT id, name, description, category, type, icon, icon_color, app_url, likes_count, views_count, rating
|
SELECT
|
||||||
FROM apps
|
a.id, a.name, a.description, a.category, a.type, a.icon, a.icon_color,
|
||||||
WHERE team_id = ? AND is_active = TRUE
|
a.app_url, a.likes_count, a.views_count, a.rating, a.created_at,
|
||||||
ORDER BY created_at DESC
|
u.name as creator_name, u.department as creator_department
|
||||||
|
FROM apps a
|
||||||
|
LEFT JOIN users u ON a.creator_id = u.id
|
||||||
|
WHERE a.team_id = ? AND a.is_active = TRUE
|
||||||
|
ORDER BY a.created_at DESC
|
||||||
`;
|
`;
|
||||||
console.log('📝 getTeamApps SQL:', sql);
|
console.log('📝 getTeamApps SQL:', sql);
|
||||||
console.log('📝 getTeamApps 參數:', [teamId]);
|
console.log('📝 getTeamApps 參數:', [teamId]);
|
||||||
|
Reference in New Issue
Block a user