實作得獎資訊功能、完成作品預覽/文件上傳功能
This commit is contained in:
144
app/api/admin/awards/route.ts
Normal file
144
app/api/admin/awards/route.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
// =====================================================
|
||||||
|
// 獎項管理 API
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { AwardService } from '@/lib/services/database-service';
|
||||||
|
|
||||||
|
// 創建獎項
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
// 驗證必填欄位
|
||||||
|
if (!body.competition_id || !body.award_name || !body.creator) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '缺少必填欄位',
|
||||||
|
error: 'competition_id, award_name, creator 為必填欄位'
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驗證獎項類型
|
||||||
|
const validAwardTypes = ['gold', 'silver', 'bronze', 'popular', 'innovation', 'technical', 'custom'];
|
||||||
|
if (!validAwardTypes.includes(body.award_type)) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '無效的獎項類型',
|
||||||
|
error: `award_type 必須是以下之一: ${validAwardTypes.join(', ')}`
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驗證競賽類型
|
||||||
|
const validCompetitionTypes = ['individual', 'team', 'proposal'];
|
||||||
|
if (!validCompetitionTypes.includes(body.competition_type)) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '無效的競賽類型',
|
||||||
|
error: `competition_type 必須是以下之一: ${validCompetitionTypes.join(', ')}`
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驗證獎項類別
|
||||||
|
const validCategories = ['innovation', 'technical', 'practical', 'popular', 'teamwork', 'solution', 'creativity'];
|
||||||
|
if (!validCategories.includes(body.category)) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '無效的獎項類別',
|
||||||
|
error: `category 必須是以下之一: ${validCategories.join(', ')}`
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 準備獎項資料
|
||||||
|
const awardData = {
|
||||||
|
competition_id: body.competition_id,
|
||||||
|
app_id: body.app_id || null,
|
||||||
|
team_id: body.team_id || null,
|
||||||
|
proposal_id: body.proposal_id || null,
|
||||||
|
app_name: body.app_name || null,
|
||||||
|
team_name: body.team_name || null,
|
||||||
|
proposal_title: body.proposal_title || null,
|
||||||
|
creator: body.creator,
|
||||||
|
award_type: body.award_type,
|
||||||
|
award_name: body.award_name,
|
||||||
|
score: parseFloat(body.score) || 0,
|
||||||
|
year: parseInt(body.year) || new Date().getFullYear(),
|
||||||
|
month: parseInt(body.month) || new Date().getMonth() + 1,
|
||||||
|
icon: body.icon || '🏆',
|
||||||
|
custom_award_type_id: body.custom_award_type_id || null,
|
||||||
|
competition_type: body.competition_type,
|
||||||
|
rank: parseInt(body.rank) || 0,
|
||||||
|
category: body.category,
|
||||||
|
description: body.description || null,
|
||||||
|
judge_comments: body.judge_comments || null,
|
||||||
|
application_links: body.application_links ? JSON.stringify(body.application_links) : null,
|
||||||
|
documents: body.documents ? JSON.stringify(body.documents) : null,
|
||||||
|
photos: body.photos ? JSON.stringify(body.photos) : null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 創建獎項
|
||||||
|
const award = await AwardService.createAward(awardData);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: '獎項創建成功',
|
||||||
|
data: award
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('創建獎項失敗:', error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '創建獎項失敗',
|
||||||
|
error: error instanceof Error ? error.message : '未知錯誤'
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 獲取獎項列表
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const competitionId = searchParams.get('competitionId');
|
||||||
|
const awardType = searchParams.get('awardType');
|
||||||
|
const category = searchParams.get('category');
|
||||||
|
const year = searchParams.get('year');
|
||||||
|
const month = searchParams.get('month');
|
||||||
|
|
||||||
|
let awards;
|
||||||
|
|
||||||
|
if (competitionId) {
|
||||||
|
awards = await AwardService.getAwardsByCompetition(competitionId);
|
||||||
|
} else {
|
||||||
|
awards = await AwardService.getAllAwards();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 應用篩選條件
|
||||||
|
if (awardType) {
|
||||||
|
awards = awards.filter(award => award.award_type === awardType);
|
||||||
|
}
|
||||||
|
if (category) {
|
||||||
|
awards = awards.filter(award => award.category === category);
|
||||||
|
}
|
||||||
|
if (year) {
|
||||||
|
awards = awards.filter(award => award.year === parseInt(year));
|
||||||
|
}
|
||||||
|
if (month) {
|
||||||
|
awards = awards.filter(award => award.month === parseInt(month));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: '獎項列表獲取成功',
|
||||||
|
data: awards
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('獲取獎項列表失敗:', error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '獲取獎項列表失敗',
|
||||||
|
error: error instanceof Error ? error.message : '未知錯誤'
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
37
app/api/admin/competitions/[id]/apps/route.ts
Normal file
37
app/api/admin/competitions/[id]/apps/route.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// =====================================================
|
||||||
|
// 競賽參賽應用 API
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { CompetitionService } from '@/lib/services/database-service';
|
||||||
|
|
||||||
|
// 獲取競賽的參賽應用
|
||||||
|
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||||
|
try {
|
||||||
|
const { id: competitionId } = await params;
|
||||||
|
|
||||||
|
if (!competitionId) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '缺少競賽ID參數'
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 獲取競賽的參賽應用
|
||||||
|
const apps = await CompetitionService.getCompetitionApps(competitionId);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: '參賽應用獲取成功',
|
||||||
|
data: apps
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('獲取參賽應用失敗:', error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '獲取參賽應用失敗',
|
||||||
|
error: error instanceof Error ? error.message : '未知錯誤'
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
53
app/api/admin/competitions/[id]/award-types/route.ts
Normal file
53
app/api/admin/competitions/[id]/award-types/route.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// =====================================================
|
||||||
|
// 競賽獎項類型 API
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { db } from '@/lib/database';
|
||||||
|
|
||||||
|
// 獲取競賽的獎項類型
|
||||||
|
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||||
|
try {
|
||||||
|
const { id: competitionId } = await params;
|
||||||
|
|
||||||
|
if (!competitionId) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '缺少競賽ID參數'
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 獲取競賽的獎項類型
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
competition_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
icon,
|
||||||
|
color,
|
||||||
|
order_index,
|
||||||
|
is_active,
|
||||||
|
created_at
|
||||||
|
FROM competition_award_types
|
||||||
|
WHERE competition_id = ? AND is_active = TRUE
|
||||||
|
ORDER BY order_index ASC, created_at ASC
|
||||||
|
`;
|
||||||
|
|
||||||
|
const awardTypes = await db.query(sql, [competitionId]);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: '獎項類型獲取成功',
|
||||||
|
data: awardTypes
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('獲取獎項類型失敗:', error);
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: '獲取獎項類型失敗',
|
||||||
|
error: error instanceof Error ? error.message : '未知錯誤'
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user