'use client'; import { Trophy, Award, Star, Target } from 'lucide-react'; import type { LeagueScoringPresetDTO } from '@gridpilot/racing/application/ports/LeagueScoringPresetProvider'; import type { LeagueConfigFormModel } from '@gridpilot/racing/application'; import Button from '@/components/ui/Button'; import PresetCard from '@/components/ui/PresetCard'; interface LeagueScoringSectionProps { form: LeagueConfigFormModel; presets: LeagueScoringPresetDTO[]; onChange?: (form: LeagueConfigFormModel) => void; readOnly?: boolean; /** * When true, only render the scoring pattern panel. */ patternOnly?: boolean; /** * When true, only render the championships panel. */ championshipsOnly?: boolean; } interface ScoringPatternSectionProps { scoring: LeagueConfigFormModel['scoring']; presets: LeagueScoringPresetDTO[]; readOnly?: boolean; patternError?: string; onChangePatternId?: (patternId: string) => void; onToggleCustomScoring?: () => void; } interface ChampionshipsSectionProps { form: LeagueConfigFormModel; onChange?: (form: LeagueConfigFormModel) => void; readOnly?: boolean; } export function LeagueScoringSection({ form, presets, onChange, readOnly, patternOnly, championshipsOnly, }: LeagueScoringSectionProps) { const disabled = readOnly || !onChange; const updateScoring = ( patch: Partial, ) => { if (!onChange) return; onChange({ ...form, scoring: { ...form.scoring, ...patch, }, }); }; const updateChampionships = ( patch: Partial, ) => { if (!onChange) return; onChange({ ...form, championships: { ...form.championships, ...patch, }, }); }; const handleSelectPreset = (presetId: string) => { if (disabled) return; updateScoring({ patternId: presetId, customScoringEnabled: false, }); }; const handleToggleCustomScoring = () => { if (disabled) return; const current = !!form.scoring.customScoringEnabled; updateScoring({ customScoringEnabled: !current, }); }; const currentPreset = presets.find((p) => p.id === form.scoring.patternId) ?? null; const isTeamsMode = form.structure.mode === 'fixedTeams'; const renderPrimaryChampionshipLabel = () => { if (!currentPreset) { return '—'; } switch (currentPreset.primaryChampionshipType) { case 'driver': return 'Driver championship'; case 'team': return 'Team championship'; case 'nations': return 'Nations championship'; case 'trophy': return 'Trophy championship'; default: return currentPreset.primaryChampionshipType; } }; const selectedPreset = currentPreset ?? (presets.length > 0 ? presets.find((p) => p.id === form.scoring.patternId) ?? null : null); const patternPanel = ( handleSelectPreset(id) : undefined } onToggleCustomScoring={disabled ? undefined : handleToggleCustomScoring} /> ); const championshipsPanel = ( ); if (patternOnly) { return
{patternPanel}
; } if (championshipsOnly) { return
{championshipsPanel}
; } return (
{patternPanel} {championshipsPanel}
); } /** * Step 4 – scoring pattern preset picker used by the wizard. */ export function ScoringPatternSection({ scoring, presets, readOnly, patternError, onChangePatternId, onToggleCustomScoring, }: ScoringPatternSectionProps) { const disabled = readOnly || !onChangePatternId; const currentPreset = presets.find((p) => p.id === scoring.patternId) ?? null; const renderPrimaryLabel = (preset: LeagueScoringPresetDTO) => { switch (preset.primaryChampionshipType) { case 'driver': return 'Driver focus'; case 'team': return 'Team focus'; case 'nations': return 'Nations focus'; case 'trophy': return 'Trophy / cup focus'; default: return preset.primaryChampionshipType; } }; const handleSelect = (presetId: string) => { if (disabled) return; onChangePatternId?.(presetId); }; return (

Scoring pattern

Choose a preset that matches your race weekend format

{presets.length === 0 ? (

No presets available.

) : (
{presets.map((preset) => ( handleSelect(preset.id)} /> ))}
)} {patternError && (

{patternError}

)}
Selected pattern
{currentPreset ? (
{currentPreset.name}
Sessions
{currentPreset.sessionSummary}
Points focus
{renderPrimaryLabel(currentPreset)}
Default drops
{currentPreset.dropPolicySummary}
) : (

No pattern selected yet. Pick a card above to define your scoring style.

)}

Custom scoring (advanced)

In this alpha, presets still define the actual scoring; this flag marks intent only.

{readOnly ? ( {scoring.customScoringEnabled ? 'Custom scoring flagged' : 'Using preset scoring'} ) : ( )}
); } /** * Step 5 – championships-only panel used by the wizard. */ export function ChampionshipsSection({ form, onChange, readOnly, }: ChampionshipsSectionProps) { const disabled = readOnly || !onChange; const isTeamsMode = form.structure.mode === 'fixedTeams'; const updateChampionships = ( patch: Partial, ) => { if (!onChange) return; onChange({ ...form, championships: { ...form.championships, ...patch, }, }); }; return (

Championships

Select which championship standings to track this season

{/* Driver championship */}
Driver championship

Per-driver season standings across all points-scoring sessions.

{readOnly ? ( {form.championships.enableDriverChampionship ? 'On' : 'Off'} ) : ( )}
{/* Team championship */}
Team championship

Aggregated season standings for fixed teams.

{!isTeamsMode && (

Enable team mode in Structure to activate this

)}
{readOnly ? ( {isTeamsMode && form.championships.enableTeamChampionship ? 'On' : 'Off'} ) : ( )}
{/* Nations championship */}
Nations Cup

Standings grouped by drivers' nationality or country flag.

{readOnly ? ( {form.championships.enableNationsChampionship ? 'On' : 'Off'} ) : ( )}
{/* Trophy championship */}
Trophy / cup

Extra cup-style standings for special categories or invite-only groups.

{readOnly ? ( {form.championships.enableTrophyChampionship ? 'On' : 'Off'} ) : ( )}

ℹ️ For this alpha, only driver standings are fully calculated. These toggles express intent for future seasons.

); }