86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
'use client';
|
||
|
||
import { Calendar, Users, Trophy, Gamepad2, Eye, Hash, Award } from 'lucide-react';
|
||
import type { LeagueConfigFormModel } from '@gridpilot/racing/application';
|
||
import type { League } from '@gridpilot/racing/domain/entities/League';
|
||
|
||
interface ReadonlyLeagueInfoProps {
|
||
league: League;
|
||
configForm: LeagueConfigFormModel;
|
||
}
|
||
|
||
export function ReadonlyLeagueInfo({ league, configForm }: ReadonlyLeagueInfoProps) {
|
||
const basics = configForm.basics;
|
||
const structure = configForm.structure;
|
||
const timings = configForm.timings;
|
||
const scoring = configForm.scoring;
|
||
|
||
const infoItems = [
|
||
{
|
||
icon: Hash,
|
||
label: 'League Name',
|
||
value: basics.name,
|
||
},
|
||
{
|
||
icon: Eye,
|
||
label: 'Visibility',
|
||
value: basics.visibility === 'ranked' || basics.visibility === 'public' ? 'Ranked' : 'Unranked',
|
||
},
|
||
{
|
||
icon: Users,
|
||
label: 'Structure',
|
||
value: structure.mode === 'solo'
|
||
? `Solo • ${structure.maxDrivers} drivers`
|
||
: `Teams • ${structure.maxTeams} × ${structure.driversPerTeam} drivers`,
|
||
},
|
||
{
|
||
icon: Gamepad2,
|
||
label: 'Platform',
|
||
value: 'iRacing',
|
||
},
|
||
{
|
||
icon: Award,
|
||
label: 'Scoring',
|
||
value: scoring.patternId ?? 'Standard',
|
||
},
|
||
{
|
||
icon: Calendar,
|
||
label: 'Created',
|
||
value: new Date(league.createdAt).toLocaleDateString('en-US', {
|
||
month: 'short',
|
||
day: 'numeric',
|
||
year: 'numeric',
|
||
}),
|
||
},
|
||
{
|
||
icon: Trophy,
|
||
label: 'Season',
|
||
value: `${timings.roundsPlanned ?? '—'} rounds`,
|
||
},
|
||
];
|
||
|
||
return (
|
||
<div className="rounded-xl border border-charcoal-outline bg-gradient-to-br from-iron-gray/40 to-iron-gray/20 p-5">
|
||
<h3 className="text-sm font-semibold text-gray-400 mb-4">League Information</h3>
|
||
|
||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
|
||
{infoItems.map((item, index) => {
|
||
const Icon = item.icon;
|
||
return (
|
||
<div key={index} className="flex items-start gap-2.5">
|
||
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-iron-gray/60 shrink-0">
|
||
<Icon className="w-3.5 h-3.5 text-gray-500" />
|
||
</div>
|
||
<div className="min-w-0 flex-1">
|
||
<div className="text-[10px] text-gray-500 mb-0.5">{item.label}</div>
|
||
<div className="text-xs font-medium text-gray-300 truncate">
|
||
{item.value}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
);
|
||
} |