'use client';
import {
FileText,
Users,
Calendar,
Trophy,
Award,
Rocket,
Eye,
EyeOff,
Gamepad2,
User,
UsersRound,
Clock,
Flag,
Zap,
Timer,
TrendingDown,
Check,
Globe,
Medal,
} from 'lucide-react';
import type { LeagueConfigFormModel } from '@gridpilot/racing/application';
import type { LeagueScoringPresetDTO } from '@gridpilot/racing/application/ports/LeagueScoringPresetProvider';
interface LeagueReviewSummaryProps {
form: LeagueConfigFormModel;
presets: LeagueScoringPresetDTO[];
}
// Individual review card component
function ReviewCard({
icon: Icon,
iconColor = 'text-primary-blue',
bgColor = 'bg-primary-blue/10',
title,
children,
}: {
icon: React.ElementType;
iconColor?: string;
bgColor?: string;
title: string;
children: React.ReactNode;
}) {
return (
);
}
// Info row component for consistent layout
function InfoRow({
icon: Icon,
label,
value,
valueClass = '',
}: {
icon?: React.ElementType;
label: string;
value: React.ReactNode;
valueClass?: string;
}) {
return (
{Icon && }
{label}
{value}
);
}
// Badge component for enabled features
function FeatureBadge({
icon: Icon,
label,
enabled,
color = 'primary-blue',
}: {
icon: React.ElementType;
label: string;
enabled: boolean;
color?: string;
}) {
if (!enabled) return null;
return (
{label}
);
}
export default function LeagueReviewSummary({ form, presets }: LeagueReviewSummaryProps) {
const { basics, structure, timings, scoring, championships, dropPolicy, stewarding } = form;
const seasonName = (form as LeagueConfigFormModel & { seasonName?: string }).seasonName;
const modeLabel =
structure.mode === 'solo'
? 'Solo drivers'
: 'Team-based';
const modeDescription =
structure.mode === 'solo'
? 'Individual competition'
: 'Teams with fixed rosters';
const capacityValue = (() => {
if (structure.mode === 'solo') {
return typeof structure.maxDrivers === 'number' ? structure.maxDrivers : '—';
}
return typeof structure.maxTeams === 'number' ? structure.maxTeams : '—';
})();
const capacityLabel = structure.mode === 'solo' ? 'drivers' : 'teams';
const formatMinutes = (value: number | undefined) => {
if (typeof value !== 'number' || value <= 0) return '—';
return `${value} min`;
};
const getDropRuleInfo = () => {
if (dropPolicy.strategy === 'none') {
return { emoji: '✓', label: 'All count', description: 'Every race counts' };
}
if (dropPolicy.strategy === 'bestNResults') {
return {
emoji: '🏆',
label: `Best ${dropPolicy.n ?? 'N'}`,
description: `Only best ${dropPolicy.n ?? 'N'} results count`,
};
}
if (dropPolicy.strategy === 'dropWorstN') {
return {
emoji: '🗑️',
label: `Drop ${dropPolicy.n ?? 'N'}`,
description: `Worst ${dropPolicy.n ?? 'N'} dropped`,
};
}
return { emoji: '✓', label: 'All count', description: 'Every race counts' };
};
const dropRuleInfo = getDropRuleInfo();
const preset = presets.find((p) => p.id === scoring.patternId) ?? null;
const seasonStartLabel =
timings.seasonStartDate
? new Date(timings.seasonStartDate).toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
})
: null;
const stewardingLabel = (() => {
switch (stewarding.decisionMode) {
case 'admin_only':
return 'Admin-only decisions';
case 'steward_vote':
return 'Steward panel voting';
default:
return stewarding.decisionMode;
}
})();
const getScoringEmoji = () => {
if (!preset) return '🏁';
const name = preset.name.toLowerCase();
if (name.includes('sprint') || name.includes('double')) return '⚡';
if (name.includes('endurance') || name.includes('long')) return '🏆';
if (name.includes('club') || name.includes('casual')) return '🏅';
return '🏁';
};
// Normalize visibility to new terminology
const isRanked = basics.visibility === 'ranked' || basics.visibility === 'public';
const visibilityLabel = isRanked ? 'Ranked' : 'Unranked';
const visibilityDescription = isRanked
? 'Competitive • Affects ratings'
: 'Casual • Friends only';
// Calculate total weekend duration
const totalWeekendMinutes = (timings.practiceMinutes ?? 0) +
(timings.qualifyingMinutes ?? 0) +
(timings.sprintRaceMinutes ?? 0) +
(timings.mainRaceMinutes ?? 0);
return (
{/* League Summary */}
League summary
{/* Background decoration */}
{basics.name || 'Your New League'}
{basics.description || 'Ready to launch your racing series!'}
{/* Ranked/Unranked Badge */}
{isRanked ? : }
{visibilityLabel}
• {visibilityDescription}
iRacing
{structure.mode === 'solo' ? : }
{modeLabel}
{/* Season Summary */}
First season summary
{seasonName || 'First season of this league'}
{seasonStartLabel && (
<>
•
Starts {seasonStartLabel}
>
)}
{typeof timings.roundsPlanned === 'number' && (
<>
•
{timings.roundsPlanned} rounds planned
>
)}
•
Stewarding: {stewardingLabel}
{/* Stats Grid */}
{/* Capacity */}
{capacityValue}
{capacityLabel}
{/* Rounds */}
{timings.roundsPlanned ?? '—'}
rounds
{/* Weekend Duration */}
{totalWeekendMinutes > 0 ? `${totalWeekendMinutes}` : '—'}
min/weekend
{/* Championships */}
{[championships.enableDriverChampionship, championships.enableTeamChampionship, championships.enableNationsChampionship, championships.enableTrophyChampionship].filter(Boolean).length}
championships
{/* Detail Cards Grid */}
{/* Schedule Card */}
{timings.practiceMinutes && timings.practiceMinutes > 0 && (
)}
{timings.sprintRaceMinutes && timings.sprintRaceMinutes > 0 && (
)}
{/* Scoring Card */}
{/* Scoring Preset */}
{getScoringEmoji()}
{preset?.name ?? 'Custom'}
{preset?.sessionSummary ?? 'Custom scoring enabled'}
{scoring.customScoringEnabled && (
Custom
)}
{/* Drop Rule */}
{dropRuleInfo.emoji}
{dropRuleInfo.label}
{dropRuleInfo.description}
{/* Championships Section */}
{championships.enableDriverChampionship && (
Driver Championship
)}
{championships.enableTeamChampionship && (
Team Championship
)}
{championships.enableNationsChampionship && (
Nations Cup
)}
{championships.enableTrophyChampionship && (
Trophy Championship
)}
{![championships.enableDriverChampionship, championships.enableTeamChampionship, championships.enableNationsChampionship, championships.enableTrophyChampionship].some(Boolean) && (
No championships enabled
)}
{/* Ready to launch message */}
Ready to launch!
Click "Create League" to launch your racing series. You can modify all settings later.
);
}