新增競賽前台呈現、刪除競賽、修改競賽狀態
This commit is contained in:
@@ -150,6 +150,67 @@ export function CompetitionManagement() {
|
||||
}
|
||||
}
|
||||
|
||||
// 獲取當前競賽
|
||||
const fetchCurrentCompetition = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/admin/competitions/current')
|
||||
const data = await response.json()
|
||||
if (data.success) {
|
||||
setCurrentCompetition(data.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('獲取當前競賽失敗:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 設置當前競賽
|
||||
const setCurrentCompetitionInDb = async (competitionId: string) => {
|
||||
try {
|
||||
const response = await fetch('/api/admin/competitions/current', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ competitionId }),
|
||||
})
|
||||
const data = await response.json()
|
||||
if (data.success) {
|
||||
setCurrentCompetition(data.data)
|
||||
setSuccess('當前競賽設置成功!')
|
||||
setTimeout(() => setSuccess(''), 3000)
|
||||
} else {
|
||||
setError('設置當前競賽失敗: ' + data.message)
|
||||
setTimeout(() => setError(''), 3000)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('設置當前競賽失敗:', error)
|
||||
setError('設置當前競賽失敗')
|
||||
setTimeout(() => setError(''), 3000)
|
||||
}
|
||||
}
|
||||
|
||||
// 取消當前競賽
|
||||
const clearCurrentCompetitionInDb = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/admin/competitions/current', {
|
||||
method: 'DELETE',
|
||||
})
|
||||
const data = await response.json()
|
||||
if (data.success) {
|
||||
setCurrentCompetition(null)
|
||||
setSuccess('當前競賽已取消!')
|
||||
setTimeout(() => setSuccess(''), 3000)
|
||||
} else {
|
||||
setError('取消當前競賽失敗: ' + data.message)
|
||||
setTimeout(() => setError(''), 3000)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('取消當前競賽失敗:', error)
|
||||
setError('取消當前競賽失敗')
|
||||
setTimeout(() => setError(''), 3000)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchCompetitionStats = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/admin/competitions/stats')
|
||||
@@ -630,6 +691,7 @@ export function CompetitionManagement() {
|
||||
// 組件載入時獲取資料
|
||||
useEffect(() => {
|
||||
fetchCompetitions()
|
||||
fetchCurrentCompetition()
|
||||
fetchCompetitionStats()
|
||||
fetchJudges()
|
||||
fetchJudgeStats()
|
||||
@@ -1770,22 +1832,50 @@ export function CompetitionManagement() {
|
||||
if (!selectedCompetitionForAction) return
|
||||
|
||||
setIsLoading(true)
|
||||
await new Promise((resolve) => setTimeout(resolve, 500))
|
||||
|
||||
|
||||
try {
|
||||
// 調用 API 刪除競賽
|
||||
const response = await fetch(`/api/admin/competitions/${selectedCompetitionForAction.id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
// 同時從 context 中刪除
|
||||
deleteCompetition(selectedCompetitionForAction.id)
|
||||
setShowDeleteCompetitionConfirm(false)
|
||||
setSelectedCompetitionForAction(null)
|
||||
setSuccess("競賽刪除成功!")
|
||||
|
||||
// 重新載入競賽列表
|
||||
await fetchCompetitions()
|
||||
} else {
|
||||
setError("競賽刪除失敗: " + data.message)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('刪除競賽失敗:', error)
|
||||
setError("競賽刪除失敗")
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
setTimeout(() => setError(""), 3000)
|
||||
setTimeout(() => setSuccess(""), 3000)
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpdateStatus = async () => {
|
||||
if (!selectedCompetitionForAction) return
|
||||
|
||||
setIsLoading(true)
|
||||
await new Promise((resolve) => setTimeout(resolve, 500))
|
||||
|
||||
|
||||
try {
|
||||
// 更新資料庫
|
||||
const updatedCompetition = await updateCompetitionInDb(selectedCompetitionForAction.id, {
|
||||
status: newStatus,
|
||||
})
|
||||
|
||||
if (updatedCompetition) {
|
||||
// 同時更新 context
|
||||
updateCompetition(selectedCompetitionForAction.id, {
|
||||
...selectedCompetitionForAction,
|
||||
status: newStatus,
|
||||
@@ -1794,8 +1884,16 @@ export function CompetitionManagement() {
|
||||
setShowChangeStatusDialog(false)
|
||||
setSelectedCompetitionForAction(null)
|
||||
setSuccess("競賽狀態更新成功!")
|
||||
} else {
|
||||
setError("競賽狀態更新失敗")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新競賽狀態失敗:', error)
|
||||
setError("競賽狀態更新失敗")
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
setTimeout(() => setSuccess(""), 3000)
|
||||
setTimeout(() => setError(""), 3000)
|
||||
}
|
||||
}
|
||||
|
||||
const getCompetitionTypeIcon = (type: string) => {
|
||||
@@ -1918,6 +2016,8 @@ export function CompetitionManagement() {
|
||||
switch (status) {
|
||||
case "completed":
|
||||
return "bg-green-100 text-green-800 border-green-200"
|
||||
case "ongoing":
|
||||
return "bg-yellow-100 text-yellow-800 border-yellow-200"
|
||||
case "active":
|
||||
return "bg-blue-100 text-blue-800 border-blue-200"
|
||||
case "judging":
|
||||
@@ -1933,6 +2033,7 @@ export function CompetitionManagement() {
|
||||
switch (status) {
|
||||
case "completed":
|
||||
return "已完成"
|
||||
case "ongoing":
|
||||
case "active":
|
||||
return "進行中"
|
||||
case "judging":
|
||||
@@ -2079,7 +2180,7 @@ export function CompetitionManagement() {
|
||||
{isLoadingDb ? (
|
||||
<Loader2 className="w-6 h-6 animate-spin" />
|
||||
) : (
|
||||
dbStats?.active || displayCompetitions.filter((c) => c.status === "active").length
|
||||
dbStats?.active || displayCompetitions.filter((c) => c.status === "active" || c.status === "ongoing").length
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -2245,14 +2346,14 @@ export function CompetitionManagement() {
|
||||
</DropdownMenuItem>
|
||||
|
||||
{!isCurrentCompetition && (
|
||||
<DropdownMenuItem onClick={() => setCurrentCompetition(competition)}>
|
||||
<DropdownMenuItem onClick={() => setCurrentCompetitionInDb(competition.id)}>
|
||||
<Star className="w-4 h-4 mr-2" />
|
||||
設為當前競賽
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{isCurrentCompetition && (
|
||||
<DropdownMenuItem onClick={() => setCurrentCompetition(null)}>
|
||||
<DropdownMenuItem onClick={() => clearCurrentCompetitionInDb()}>
|
||||
<StarOff className="w-4 h-4 mr-2" />
|
||||
取消當前競賽
|
||||
</DropdownMenuItem>
|
||||
@@ -5395,9 +5496,9 @@ export function CompetitionManagement() {
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>當前狀態</Label>
|
||||
<p className="text-sm text-gray-600">
|
||||
<div className="text-sm text-gray-600">
|
||||
<Badge>{getStatusText(selectedCompetitionForAction.status)}</Badge>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="status">新狀態</Label>
|
||||
|
Reference in New Issue
Block a user