修正獎勵專區評審團資料異常 bug
This commit is contained in:
@@ -2143,11 +2143,17 @@ export function CompetitionManagement() {
|
||||
|
||||
if (teamsData.success && teamsData.data && teamsData.data.teams) {
|
||||
console.log('✅ 競賽團隊載入成功:', teamsData.data.teams.length, '個團隊')
|
||||
updatedCompetition.teams = teamsData.data.teams
|
||||
// 同時更新dbTeams
|
||||
// 確保團隊數據的唯一性,避免重複的ID
|
||||
const uniqueTeams = teamsData.data.teams.filter((team: any, index: number, self: any[]) =>
|
||||
self.findIndex(t => t.id === team.id) === index
|
||||
)
|
||||
updatedCompetition.teams = uniqueTeams
|
||||
console.log('🔍 去重後的團隊數量:', uniqueTeams.length)
|
||||
|
||||
// 同時更新dbTeams,確保不重複添加
|
||||
setDbTeams(prev => {
|
||||
const existingIds = prev.map(t => t.id)
|
||||
const newTeams = teamsData.data.teams.filter((t: any) => !existingIds.includes(t.id))
|
||||
const newTeams = uniqueTeams.filter((t: any) => !existingIds.includes(t.id))
|
||||
return [...prev, ...newTeams]
|
||||
})
|
||||
} else {
|
||||
@@ -3195,8 +3201,8 @@ export function CompetitionManagement() {
|
||||
)
|
||||
}
|
||||
|
||||
return paginatedTeams.map((team) => (
|
||||
<Card key={team.id} className="relative h-fit">
|
||||
return paginatedTeams.map((team, index) => (
|
||||
<Card key={`${team.id}-${index}`} className="relative h-fit">
|
||||
<CardContent className="p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start justify-between">
|
||||
@@ -4067,7 +4073,7 @@ export function CompetitionManagement() {
|
||||
if (links && links.production) {
|
||||
linkItems.push(
|
||||
<div key="production" className="flex items-center space-x-1">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full" title="生產環境"></div>
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full" title="APP 連結"></div>
|
||||
<a
|
||||
href={links.production}
|
||||
target="_blank"
|
||||
@@ -4075,7 +4081,7 @@ export function CompetitionManagement() {
|
||||
className="text-xs text-blue-600 hover:text-blue-800 underline truncate max-w-24"
|
||||
title={links.production}
|
||||
>
|
||||
生產環境
|
||||
APP 連結
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
@@ -4538,7 +4544,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-4">
|
||||
<Label className="text-xs">評比項目名稱</Label>
|
||||
<Input
|
||||
value={rule.name || ""}
|
||||
value={rule.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.individualConfig.rules]
|
||||
updatedRules[index] = { ...rule, name: e.target.value }
|
||||
@@ -4557,7 +4563,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">描述</Label>
|
||||
<Input
|
||||
value={rule.description || ""}
|
||||
value={rule.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.individualConfig.rules]
|
||||
updatedRules[index] = { ...rule, description: e.target.value }
|
||||
@@ -4579,7 +4585,7 @@ export function CompetitionManagement() {
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
value={rule.weight || 0}
|
||||
value={rule.weight ?? 0}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.individualConfig.rules]
|
||||
updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 }
|
||||
@@ -4672,7 +4678,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-1">
|
||||
<Label className="text-xs">圖示</Label>
|
||||
<Select
|
||||
value={awardType.icon || "🏆"}
|
||||
value={awardType.icon ?? "🏆"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, icon: value }
|
||||
@@ -4706,7 +4712,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-3">
|
||||
<Label className="text-xs">獎項名稱</Label>
|
||||
<Input
|
||||
value={awardType.name || ""}
|
||||
value={awardType.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, name: e.target.value }
|
||||
@@ -4725,7 +4731,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">獎項描述</Label>
|
||||
<Input
|
||||
value={awardType.description || ""}
|
||||
value={awardType.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, description: e.target.value }
|
||||
@@ -4744,7 +4750,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-2">
|
||||
<Label className="text-xs">顏色主題</Label>
|
||||
<Select
|
||||
value={awardType.color || "text-yellow-600"}
|
||||
value={awardType.color ?? "text-yellow-600"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.individualConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, color: value }
|
||||
@@ -4950,7 +4956,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-4">
|
||||
<Label className="text-xs">評比項目名稱</Label>
|
||||
<Input
|
||||
value={rule.name || ""}
|
||||
value={rule.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.teamConfig.rules]
|
||||
updatedRules[index] = { ...rule, name: e.target.value }
|
||||
@@ -4969,7 +4975,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">描述</Label>
|
||||
<Input
|
||||
value={rule.description || ""}
|
||||
value={rule.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.teamConfig.rules]
|
||||
updatedRules[index] = { ...rule, description: e.target.value }
|
||||
@@ -4991,7 +4997,7 @@ export function CompetitionManagement() {
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
value={rule.weight || 0}
|
||||
value={rule.weight ?? 0}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.teamConfig.rules]
|
||||
updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 }
|
||||
@@ -5084,7 +5090,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-1">
|
||||
<Label className="text-xs">圖示</Label>
|
||||
<Select
|
||||
value={awardType.icon || "🏆"}
|
||||
value={awardType.icon ?? "🏆"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, icon: value }
|
||||
@@ -5119,7 +5125,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-3">
|
||||
<Label className="text-xs">獎項名稱</Label>
|
||||
<Input
|
||||
value={awardType.name || ""}
|
||||
value={awardType.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, name: e.target.value }
|
||||
@@ -5138,7 +5144,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">獎項描述</Label>
|
||||
<Input
|
||||
value={awardType.description || ""}
|
||||
value={awardType.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, description: e.target.value }
|
||||
@@ -5157,7 +5163,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-2">
|
||||
<Label className="text-xs">顏色主題</Label>
|
||||
<Select
|
||||
value={awardType.color || "text-yellow-600"}
|
||||
value={awardType.color ?? "text-yellow-600"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.teamConfig.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, color: value }
|
||||
@@ -5350,7 +5356,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-4">
|
||||
<Label className="text-xs">評比項目名稱</Label>
|
||||
<Input
|
||||
value={rule.name || ""}
|
||||
value={rule.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.rules]
|
||||
updatedRules[index] = { ...rule, name: e.target.value }
|
||||
@@ -5363,7 +5369,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">描述</Label>
|
||||
<Input
|
||||
value={rule.description || ""}
|
||||
value={rule.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.rules]
|
||||
updatedRules[index] = { ...rule, description: e.target.value }
|
||||
@@ -5379,7 +5385,7 @@ export function CompetitionManagement() {
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
value={rule.weight || 0}
|
||||
value={rule.weight ?? 0}
|
||||
onChange={(e) => {
|
||||
const updatedRules = [...newCompetition.rules]
|
||||
updatedRules[index] = { ...rule, weight: Number.parseInt(e.target.value) || 0 }
|
||||
@@ -5468,7 +5474,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-1">
|
||||
<Label className="text-xs">圖示</Label>
|
||||
<Select
|
||||
value={awardType.icon || "🏆"}
|
||||
value={awardType.icon ?? "🏆"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, icon: value }
|
||||
@@ -5497,7 +5503,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-3">
|
||||
<Label className="text-xs">獎項名稱</Label>
|
||||
<Input
|
||||
value={awardType.name || ""}
|
||||
value={awardType.name ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, name: e.target.value }
|
||||
@@ -5510,7 +5516,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-5">
|
||||
<Label className="text-xs">獎項描述</Label>
|
||||
<Input
|
||||
value={awardType.description || ""}
|
||||
value={awardType.description ?? ""}
|
||||
onChange={(e) => {
|
||||
const updatedAwardTypes = [...newCompetition.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, description: e.target.value }
|
||||
@@ -5523,7 +5529,7 @@ export function CompetitionManagement() {
|
||||
<div className="col-span-2">
|
||||
<Label className="text-xs">顏色主題</Label>
|
||||
<Select
|
||||
value={awardType.color || "text-yellow-600"}
|
||||
value={awardType.color ?? "text-yellow-600"}
|
||||
onValueChange={(value) => {
|
||||
const updatedAwardTypes = [...newCompetition.awardTypes]
|
||||
updatedAwardTypes[index] = { ...awardType, color: value }
|
||||
@@ -6175,8 +6181,12 @@ export function CompetitionManagement() {
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{(selectedCompetitionForAction.teams && selectedCompetitionForAction.teams.length > 0) ?
|
||||
selectedCompetitionForAction.teams.map((team: any) => (
|
||||
<div key={team.id} className="p-4 border rounded-lg bg-white space-y-2">
|
||||
selectedCompetitionForAction.teams
|
||||
.filter((team: any, index: number, self: any[]) =>
|
||||
self.findIndex(t => t.id === team.id) === index
|
||||
)
|
||||
.map((team: any, index: number) => (
|
||||
<div key={`${team.id}-${index}`} className="p-4 border rounded-lg bg-white space-y-2">
|
||||
<h5 className="font-medium text-gray-900">{team.name}</h5>
|
||||
<p className="text-sm text-gray-600">隊長:{team.leader_name || team.leader_id || '未知'}</p>
|
||||
<p className="text-sm text-gray-600">部門:{team.department || '未知'}</p>
|
||||
@@ -6485,12 +6495,16 @@ export function CompetitionManagement() {
|
||||
(() => {
|
||||
// 使用selectedCompetition.teams數據,顯示為「團隊名 - APP名」格式
|
||||
const teamsData = selectedCompetition?.teams || []
|
||||
return teamsData.length > 0 ? teamsData.map((team: any) => {
|
||||
return teamsData.length > 0 ? teamsData
|
||||
.filter((team: any, index: number, self: any[]) =>
|
||||
self.findIndex(t => t.id === team.id) === index
|
||||
)
|
||||
.map((team: any, index: number) => {
|
||||
// 檢查團隊是否有APP
|
||||
const teamApps = team.apps || []
|
||||
if (teamApps.length === 0) {
|
||||
return (
|
||||
<SelectItem key={team.id} value={team.id} disabled>
|
||||
<SelectItem key={`${team.id}-${index}`} value={team.id} disabled>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Users className="w-4 h-4 text-gray-400" />
|
||||
<span className="text-gray-400">{team.name}</span>
|
||||
@@ -6503,7 +6517,7 @@ export function CompetitionManagement() {
|
||||
// 顯示團隊和其第一個APP
|
||||
const firstApp = teamApps[0]
|
||||
return (
|
||||
<SelectItem key={team.id} value={team.id}>
|
||||
<SelectItem key={`${team.id}-${index}`} value={team.id}>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Users className="w-4 h-4 text-green-600" />
|
||||
<span>{team.name}</span>
|
||||
@@ -7813,7 +7827,7 @@ export function CompetitionManagement() {
|
||||
<div className="space-y-2">
|
||||
<Label>獎項類型</Label>
|
||||
<Select
|
||||
value={newAward.customAwardTypeId || newAward.awardType}
|
||||
value={newAward.customAwardTypeId ?? newAward.awardType}
|
||||
onValueChange={(value: any) => {
|
||||
// 檢查是否為自定義獎項類型
|
||||
const customAwardType = competitionAwardTypes.find(type => type.id === value)
|
||||
@@ -8095,8 +8109,12 @@ export function CompetitionManagement() {
|
||||
} else if (shouldShowTeam) {
|
||||
// 團體賽:只顯示團隊,不顯示 app
|
||||
return competitionTeams.length > 0 ? (
|
||||
competitionTeams.map((team) => (
|
||||
<SelectItem key={team.id} value={team.id}>
|
||||
competitionTeams
|
||||
.filter((team: any, index: number, self: any[]) =>
|
||||
self.findIndex(t => t.id === team.id) === index
|
||||
)
|
||||
.map((team: any, index: number) => (
|
||||
<SelectItem key={`${team.id}-${index}`} value={team.id}>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{team.name}</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
@@ -8226,7 +8244,7 @@ export function CompetitionManagement() {
|
||||
})}
|
||||
placeholder="https://app.example.com"
|
||||
/>
|
||||
<p className="text-xs text-gray-500">生產環境應用連結</p>
|
||||
<p className="text-xs text-gray-500">APP 應用連結</p>
|
||||
</div>
|
||||
|
||||
{/* 網站預覽內容 */}
|
||||
@@ -8574,7 +8592,7 @@ export function CompetitionManagement() {
|
||||
{/* 照片說明 */}
|
||||
<Input
|
||||
placeholder="輸入照片說明..."
|
||||
value={photo.caption || ''}
|
||||
value={photo.caption ?? ''}
|
||||
onChange={(e) => {
|
||||
const updatedPhotos = newAward.photos.map(p =>
|
||||
p.id === photo.id ? { ...p, caption: e.target.value } : p
|
||||
@@ -8925,7 +8943,7 @@ export function CompetitionManagement() {
|
||||
<div key="production" className="p-3 bg-green-50 border border-green-200 rounded-lg">
|
||||
<div className="flex items-center space-x-2 mb-2">
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
<span className="text-sm font-medium text-green-900">生產環境</span>
|
||||
<span className="text-sm font-medium text-green-900">APP 連結</span>
|
||||
</div>
|
||||
<a
|
||||
href={links.production}
|
||||
|
Reference in New Issue
Block a user