'use client' import { strokesReceived, scoreColorClass, formatVsPar } from '@/lib/handicap' import type { Hole, Player } from '@/app/(app)/rounds/[id]/scorecard/page' type Props = { holes: Hole[] players: Player[] scores: Record onTapScore: (player: Player, hole: Hole) => void isActive: boolean } export function FullGrid({ holes, players, scores, onTapScore, isActive }: Props) { const totalHoles = holes.length const front = holes.filter((h) => h.hole_number <= 9) const back = holes.filter((h) => h.hole_number > 9) const hasBoth = front.length > 0 && back.length > 0 function getGross(playerId: string, hole: Hole) { return scores[`${playerId}-${hole.id}`] ?? null } function getNet(playerId: string, hole: Hole) { const gross = getGross(playerId, hole) if (gross === null) return null const ch = players.find((p) => p.user_id === playerId)?.course_handicap ?? 0 return gross - strokesReceived(ch, hole.stroke_index, totalHoles) } function subtotal(playerId: string, holeSet: Hole[], fn: (p: string, h: Hole) => number | null) { const values = holeSet.map((h) => fn(playerId, h)).filter((v): v is number => v !== null) return values.length === holeSet.length ? values.reduce((a, b) => a + b, 0) : null } const parFront = front.reduce((s, h) => s + h.par, 0) const parBack = back.reduce((s, h) => s + h.par, 0) const parTotal = parFront + parBack return (
{front.map((h) => ( ))} {hasBoth && ( )} {back.map((h) => ( ))} {hasBoth && ( )} {/* Par row */} {front.map((h) => ( ))} {hasBoth && ( )} {back.map((h) => ( ))} {hasBoth && ( )} {players.map((player, pi) => { const frontOut = subtotal(player.user_id, front, getGross) const backIn = subtotal(player.user_id, back, getGross) const total = frontOut !== null && backIn !== null ? frontOut + backIn : hasBoth ? null : subtotal(player.user_id, holes, getGross) const netTotal = subtotal(player.user_id, holes, getNet) const netVsPar = netTotal !== null ? netTotal - parTotal : null return ( {front.map((h) => { const gross = getGross(player.user_id, h) const grossVsPar = gross !== null ? gross - h.par : null return ( ) })} {hasBoth && ( )} {back.map((h) => { const gross = getGross(player.user_id, h) const grossVsPar = gross !== null ? gross - h.par : null return ( ) })} {hasBoth && ( )} ) })}
Player {h.hole_number} Out {h.hole_number} InTot Net
Par {h.par} {parFront} {h.par} {parBack}{parTotal}
{player.profile?.display_name} isActive && onTapScore(player, h)} > {gross ?? '·'} {frontOut ?? '—'} isActive && onTapScore(player, h)} > {gross ?? '·'} {backIn ?? '—'} {total ?? '—'} {netVsPar !== null ? formatVsPar(netVsPar) : '—'}
) }