feat: add match management admin panel with delete functionality

This commit is contained in:
2026-03-31 16:16:13 -07:00
parent 222fb0bdc3
commit a22c801f0c
3 changed files with 352 additions and 0 deletions
+99
View File
@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { getSession } from "@/lib/auth-simple";
import { hasRole, canManageMatch } from "@/lib/permissions";
import { calculateTeamElo, calculateTeamEloChange } from "@/lib/elo-utils";
import { calculateOpenSkillRatings, fromOpenSkillRating } from "@/lib/openskill-utils";
@@ -8,6 +9,104 @@ import { calculateGlicko2Ratings } from "@/lib/glicko2-utils";
const K_FACTOR = 32; // Standard K-factor for Elo calculations
/**
* GET /api/matches
*
* Get matches (admin only)
* Requires: club_admin, site_admin, or tournament_admin role
*/
export async function GET() {
try {
const session = await getSession();
if (!session) {
return NextResponse.json(
{ error: "Not authenticated" },
{ status: 403 }
);
}
const userId = session.user?.id;
if (!userId) {
return NextResponse.json(
{ error: "User ID not found in session" },
{ status: 403 }
);
}
// Fetch user from database to get current role
const user = await prisma.user.findUnique({
where: { id: userId },
select: { role: true }
});
if (!user) {
return NextResponse.json(
{ error: "User not found" },
{ status: 403 }
);
}
const userRole = user.role as 'player' | 'tournament_admin' | 'club_admin' | 'site_admin';
let matches;
if (userRole === 'club_admin' || userRole === 'site_admin') {
// Club admins and site admins can see all matches
matches = await prisma.match.findMany({
include: {
event: {
select: {
id: true,
name: true,
},
},
team1P1: { select: { id: true, name: true } },
team1P2: { select: { id: true, name: true } },
team2P1: { select: { id: true, name: true } },
team2P2: { select: { id: true, name: true } },
},
orderBy: { playedAt: 'desc' },
});
} else if (userRole === 'tournament_admin') {
// Tournament admins can only see matches in their own tournaments
matches = await prisma.match.findMany({
where: {
event: {
ownerId: userId,
},
},
include: {
event: {
select: {
id: true,
name: true,
},
},
team1P1: { select: { id: true, name: true } },
team1P2: { select: { id: true, name: true } },
team2P1: { select: { id: true, name: true } },
team2P2: { select: { id: true, name: true } },
},
orderBy: { playedAt: 'desc' },
});
} else {
// Regular players cannot view matches via this API (should not happen if UI is protected)
return NextResponse.json(
{ error: "Insufficient permissions to view matches" },
{ status: 403 }
);
}
return NextResponse.json(matches);
} catch (error: unknown) {
console.error("Error fetching matches:", error);
const message = error instanceof Error ? error.message : "Failed to fetch matches";
return NextResponse.json(
{ error: message },
{ status: 500 }
);
}
}
/**
* POST /api/matches
*