"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import Navigation from "@/components/Navigation" interface Player { id: number name: string currentElo: number } interface Tournament { id: number name: string eventDate: string | null format: string participants: { player: Player }[] } interface GameEntry { round: number table: string player1: string player2: string score1: number player3: string player4: string score2: number } export default function TournamentEntryPage({ params }: { params: Promise<{ id: string }> }) { const router = useRouter() const [tournament, setTournament] = useState(null) const [tournamentId, setTournamentId] = useState(null) const [gameText, setGameText] = useState("") const [parsedGames, setParsedGames] = useState([]) const [error, setError] = useState("") const [success, setSuccess] = useState("") const [isLoading, setIsLoading] = useState(false) // Parse params and validate tournamentId useEffect(() => { async function parseParams() { const { id } = await params const parsedId = parseInt(id, 10) if (isNaN(parsedId)) { router.push('/admin/tournaments') } else { setTournamentId(parsedId) } } parseParams() }, [params, router]) // Load tournament when tournamentId is available useEffect(() => { if (tournamentId) { loadTournament() } // eslint-disable-next-line react-hooks/exhaustive-deps }, [tournamentId]) const loadTournament = async () => { try { const response = await fetch(`/api/tournaments/${tournamentId}`) const data = await response.json() if (response.ok) { setTournament(data.tournament) } } catch (err) { console.error("Failed to load tournament:", err) } } const parseGameText = (text: string): GameEntry[] => { const lines = text.trim().split("\n") const games: GameEntry[] = [] for (const line of lines) { // Skip empty lines and comments if (!line.trim() || line.trim().startsWith("#")) continue // Parse tab-separated or comma-separated values const parts = line.split(/[,\t]/).map(p => p.trim()) if (parts.length >= 7) { games.push({ round: parseInt(parts[0]) || 1, table: parts[1] || "", player1: parts[2], player2: parts[3], score1: parseInt(parts[4]) || 0, player3: parts[5], player4: parts[6], score2: parseInt(parts[7]) || 0, }) } } return games } const handleTextChange = (e: React.ChangeEvent) => { const text = e.target.value setGameText(text) const games = parseGameText(text) setParsedGames(games) } const submitGames = async () => { if (parsedGames.length === 0) { setError("No valid games to submit") return } setError("") setSuccess("") setIsLoading(true) try { const response = await fetch(`/api/tournaments/${tournamentId}/games/bulk`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ games: parsedGames, }), }) const data = await response.json() if (!response.ok) { throw new Error(data.error || "Failed to submit games") } setSuccess(`Successfully imported ${data.importedCount} games`) setGameText("") setParsedGames([]) } catch (err) { if (err instanceof Error) { setError(err.message) } else { setError("An unknown error occurred") } } finally { setIsLoading(false) } } if (!tournament) { return (
) } return (

Game Entry: {tournament.name}

{tournament.eventDate && (

{new Date(tournament.eventDate).toLocaleDateString()}

)}
{error && (
{error}
)} {success && (
{success}
)}
{/* Participants Panel */}

Participants ({tournament.participants.length})

{tournament.participants.map(({ player }) => (
{player.name}
))}
{/* Game Entry Panel */}

Enter Games

Tab or comma-separated format:

Round Table Player1 Player2 Score1 Player3 Player4 Score2

Example: 1 1 John Smith Jane Doe 10 Mike Johnson Sarah Brown 5

Lines starting with # are treated as comments