// frontend/src/components/Forms/TournamentForm.tsx import { Loader2 } from 'lucide-react'; import React, { useEffect, useState } from 'react'; import api from '../../services/api'; interface TournamentSettings { id: string | number; name: string; code: string; type: string; timestamp: string; duration: number; courts: { name?: string }[]; teams: { name?: string }[]; } interface TournamentFormProps { tournamentId?: string | number | null; onSuccess: () => void; onDelete?: (id: string | number) => void; } export default function TournamentForm({ tournamentId, onSuccess, onDelete }: TournamentFormProps) { const [initialData, setInitialData] = useState(null); const [isLoading, setIsLoading] = useState(!!tournamentId); const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); useEffect(() => { if (!tournamentId) { setInitialData(null); setIsLoading(false); return; } const fetchSettings = async () => { try { const data = await api.get(`/tournaments/${tournamentId}/settings`); setInitialData(data); } catch (err) { console.error(err); setError("Failed to load tournament settings."); } finally { setIsLoading(false); } }; fetchSettings(); }, [tournamentId]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); setError(null); const formData = new FormData(e.currentTarget); const rawTeams = formData.get('teams') as string; const rawCourts = formData.get('courts') as string; const date = formData.get('date') as string; const startTime = formData.get('start_time') as string; const typeRaw = formData.get('type') as string; const duration = formData.get('duration') as string; const name = formData.get('name') as string; const code = formData.get('code') as string; const teams = rawTeams.split('\n').map(t => t.trim()).filter(t => t.length > 0); const courts = rawCourts.split(',').map(c => c.trim()).filter(c => c.length > 0); if (teams.length < 2) { setError("At least 2 teams required."); setIsSubmitting(false); return; } const timestamp = `${date}T${startTime}:00`; const formattedType = typeRaw.charAt(0).toUpperCase() + typeRaw.slice(1); const parsedDuration = parseInt(duration, 10); try { if (tournamentId) { const basePayload = { name, code, type: formattedType, timestamp, duration: parsedDuration }; await Promise.all([ api.patch(`/tournaments/${tournamentId}`, basePayload), api.patch(`/tournaments/${tournamentId}/teams`, teams), api.patch(`/tournaments/${tournamentId}/courts`, courts) ]); } else { const fullPayload = { name, code, type: formattedType, timestamp, duration: parsedDuration, teams, courts }; await api.post('/tournaments', fullPayload); } onSuccess(); } catch (err: unknown) { console.error(err); const error = err as { detail?: string | Array<{ loc: string[]; msg: string }> }; if (Array.isArray(error.detail)) { setError(error.detail.map((e) => `${e.loc.join('.')}: ${e.msg}`).join(', ')); } else { setError(typeof error.detail === 'string' ? error.detail : "Error saving tournament"); } } finally { setIsSubmitting(false); } }; if (isLoading) { return (
); } let defaultDate = new Date().toISOString().split('T')[0]; let defaultTime = "09:00"; if (initialData?.timestamp) { const [d, t] = initialData.timestamp.split('T'); defaultDate = d; defaultTime = t ? t.substring(0, 5) : "09:00"; } return (
{error && (
{error}
)}
c.name || c).join(', ')} required className="w-full bg-zinc-50 dark:bg-zinc-950 border border-zinc-300 dark:border-zinc-600 rounded p-2 focus:border-orange-500 outline-none transition text-zinc-900 dark:text-white" />