"use client"; import { useEffect, useMemo, useState } from "react"; import { AppShell } from "@/components/AppShell"; import { EmptyState } from "@/components/EmptyState"; import { SectionCard } from "@/components/SectionCard"; import { Alert } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { fetchJson } from "@/lib/client"; import type { GamePlayerStatsInput, GameRecord, LineupRecord } from "@/lib/types"; const battingFields = [ ["atBats", "AB"], ["runs", "R"], ["hits", "H"], ["doubles", "2B"], ["triples", "3B"], ["homeRuns", "HR"], ["runsBattedIn", "RBI"], ["walks", "BB"], ["strikeouts", "SO"], ["stolenBases", "SB"] ] as const; const pitchingFields = [ ["pitchCount", "Pitches"], ["inningsPitchedOuts", "IP Outs"], ["earnedRunsAllowed", "ER"], ["hitsAllowed", "H Allowed"], ["walksAllowed", "BB Allowed"], ["strikeoutsPitched", "Pitching K"] ] as const; function pickDefaultLineupId(gameDate: string, lineups: LineupRecord[]) { const exactDate = lineups.find((lineup) => lineup.gameDate === gameDate); return exactDate?._id ?? lineups[0]?._id ?? ""; } export function GameScoringClient() { const [gameDate, setGameDate] = useState(new Date().toISOString().slice(0, 10)); const [lineups, setLineups] = useState([]); const [selectedLineupId, setSelectedLineupId] = useState(""); const [opponent, setOpponent] = useState(""); const [teamScore, setTeamScore] = useState(""); const [opponentScore, setOpponentScore] = useState(""); const [notes, setNotes] = useState(""); const [playerStats, setPlayerStats] = useState>({}); const [isScoring, setIsScoring] = useState(false); const [message, setMessage] = useState(null); const [error, setError] = useState(null); async function loadLineups() { try { const response = await fetchJson("/api/lineups"); setLineups(response); setSelectedLineupId((current) => current && response.some((lineup) => lineup._id === current) ? current : pickDefaultLineupId(gameDate, response) ); } catch (loadError) { setError(loadError instanceof Error ? loadError.message : "Failed to load lineups."); } } useEffect(() => { void loadLineups(); }, []); useEffect(() => { setSelectedLineupId((current) => { if (current && lineups.some((lineup) => lineup._id === current)) { return current; } return pickDefaultLineupId(gameDate, lineups); }); }, [gameDate, lineups]); const selectedLineup = useMemo( () => lineups.find((lineup) => lineup._id === selectedLineupId) ?? null, [lineups, selectedLineupId] ); useEffect(() => { if (!selectedLineup) { setPlayerStats({}); setIsScoring(false); return; } setPlayerStats((current) => Object.fromEntries( selectedLineup.battingOrder.map((slot) => [ slot.playerId, current[slot.playerId] ?? { playerId: slot.playerId, playerName: slot.playerName } ]) ) ); }, [selectedLineup]); function updatePlayerStat( playerId: string, playerName: string, field: keyof Omit, value: string ) { setPlayerStats((current) => ({ ...current, [playerId]: { ...(current[playerId] ?? { playerId, playerName }), playerId, playerName, [field]: value === "" ? null : Number(value) } })); } async function saveGame() { if (!selectedLineup || !selectedLineup._id) { setError("Select a saved lineup before scoring the game."); return; } try { const payload = { gameDate, lineupId: selectedLineup._id, opponent, teamScore: teamScore === "" ? null : Number(teamScore), opponentScore: opponentScore === "" ? null : Number(opponentScore), notes, playerStats: selectedLineup.battingOrder.map( (slot) => playerStats[slot.playerId] ?? { playerId: slot.playerId, playerName: slot.playerName } ) }; const saved = await fetchJson("/api/games", { method: "POST", body: JSON.stringify(payload) }); setMessage(`Saved game #${saved.gameNumber} for ${saved.gameDate}.`); setOpponent(""); setTeamScore(""); setOpponentScore(""); setNotes(""); setPlayerStats({}); setIsScoring(false); } catch (saveError) { setError(saveError instanceof Error ? saveError.message : "Unable to save game."); } } return ( {message ? {message} : null} {error ? {error} : null} {lineups.length > 0 ? (