Files
euchre_camp/src/app/admin/tournaments/page.tsx
T
david 123df671f5 nextjs-rewrite (#5)
Reviewed-on: #5
Co-authored-by: David Gwilliam <dhgwilliam@gmail.com>
Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
2026-03-30 02:30:13 +00:00

168 lines
6.3 KiB
TypeScript

import { prisma } from "@/lib/prisma"
import Navigation from "@/components/Navigation"
import Link from "next/link"
import { getSession } from "@/lib/auth-simple"
import { redirect } from "next/navigation"
import { getTournamentStatus } from "@/lib/tournamentUtils"
export default async function AdminTournamentsPage() {
const session = await getSession()
if (!session) {
redirect("/auth/login")
}
// Fetch user role from database
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { role: true },
});
const isAdmin = user?.role === "club_admin"
const tournaments = await prisma.event.findMany({
orderBy: { createdAt: "desc" },
include: {
participants: true,
teams: {
include: {
player1: true,
player2: true,
},
},
},
})
// Update tournament statuses based on event date
const updatedTournaments = await Promise.all(
tournaments.map(async (tournament) => {
const calculatedStatus = getTournamentStatus(tournament.eventDate);
// Only update if the calculated status differs from the stored status
if (tournament.status !== calculatedStatus) {
await prisma.event.update({
where: { id: tournament.id },
data: { status: calculatedStatus },
});
return { ...tournament, status: calculatedStatus };
}
return tournament;
})
)
return (
<div className="min-h-screen bg-gray-50">
<Navigation />
<main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
<div className="px-4 py-6 sm:px-0">
<div className="flex justify-between items-center mb-6">
<h1 className="text-3xl font-bold text-gray-900">
{isAdmin ? 'Tournament Management' : 'Tournaments'}
</h1>
{isAdmin && (
<Link
href="/admin/tournaments/new"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700"
>
Create Tournament
</Link>
)}
</div>
<div className="bg-white shadow overflow-hidden sm:rounded-lg">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Tournament
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Format
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Status
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Participants
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{updatedTournaments.map((tournament) => (
<tr key={tournament.id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap">
<Link
href={`/admin/tournaments/${tournament.id}`}
className="text-green-600 hover:text-green-900 font-medium"
>
{tournament.name}
</Link>
{tournament.eventDate && (
<p className="text-sm text-gray-500">
{new Date(tournament.eventDate).toLocaleDateString()}
</p>
)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{tournament.format}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex px-2 py-1 text-xs font-semibold leading-5 rounded-full ${
tournament.status === 'active' || tournament.status === 'in_progress'
? 'bg-green-100 text-green-800'
: tournament.status === 'completed'
? 'bg-gray-100 text-gray-800'
: 'bg-yellow-100 text-yellow-800'
}`}>
{tournament.status}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{tournament.participants.length}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<Link
href={`/admin/tournaments/${tournament.id}`}
className="text-green-600 hover:text-green-900 mr-3"
>
View
</Link>
{isAdmin && (
<Link
href={`/admin/tournaments/${tournament.id}/edit`}
className="text-blue-600 hover:text-blue-900"
>
Edit
</Link>
)}
</td>
</tr>
))}
</tbody>
</table>
{updatedTournaments.length === 0 && (
<div className="text-center py-12">
<p className="text-gray-500">No tournaments found.</p>
{isAdmin && (
<Link
href="/admin/tournaments/new"
className="text-green-600 hover:text-green-900 mt-2 inline-block"
>
Create your first tournament
</Link>
)}
</div>
)}
</div>
</div>
</main>
</div>
)
}