Files
gridpilot.gg/apps/website/components/leagues/LeagueCard.tsx
2026-01-20 01:30:17 +01:00

136 lines
3.7 KiB
TypeScript

'use client';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Image } from '@/ui/Image';
import { PlaceholderImage } from '@/ui/PlaceholderImage';
import { Text } from '@/ui/Text';
import { Box } from '@/ui/Box';
import { Group } from '@/ui/Group';
import { Surface } from '@/ui/Surface';
import { Stack } from '@/ui/Stack';
import { LeagueCard as UILeagueCard, LeagueCardStats, LeagueCardFooter } from '@/ui/LeagueCard';
import { Calendar, Users, Activity } from 'lucide-react';
import React, { ReactNode } from 'react';
interface LeagueCardProps {
name: string;
description?: string;
coverUrl: string;
logoUrl?: string;
badges?: ReactNode;
championshipBadge?: ReactNode;
slotLabel: string;
usedSlots: number;
maxSlots: number | string;
fillPercentage: number;
hasOpenSlots: boolean;
openSlotsCount: number;
isTeamLeague?: boolean;
usedDriverSlots?: number;
maxDrivers?: number | string;
timingSummary?: string;
onClick?: () => void;
}
export function LeagueCard({
name,
description,
coverUrl,
logoUrl,
badges,
championshipBadge,
slotLabel,
usedSlots,
maxSlots,
fillPercentage,
hasOpenSlots,
openSlotsCount,
timingSummary,
onClick,
}: LeagueCardProps) {
return (
<UILeagueCard
onClick={onClick}
coverUrl={coverUrl}
logo={
<Surface
width="3.5rem"
height="3.5rem"
rounded="lg"
overflow="hidden"
border
variant="precision"
>
{logoUrl ? (
<Image
src={logoUrl}
alt={`${name} logo`}
width={56}
height={56}
objectFit="cover"
/>
) : (
<PlaceholderImage size={56} />
)}
</Surface>
}
badges={
<Group gap={2}>
{badges}
{championshipBadge}
</Group>
}
>
<Stack gap={4} fullHeight>
<Stack gap={1}>
<Group gap={2} align="center">
<Box width="2px" height="1rem" bg="var(--ui-color-intent-telemetry)" />
<Heading level={3} weight="bold" truncate>{name}</Heading>
</Group>
<Text size="xs" variant="low" lineClamp={2} block leading="relaxed">
{description || 'No infrastructure description provided.'}
</Text>
</Stack>
<Box>
<LeagueCardStats
label={slotLabel}
value={`${usedSlots} / ${maxSlots || '∞'}`}
percentage={fillPercentage}
intent={fillPercentage >= 90 ? 'warning' : fillPercentage >= 70 ? 'primary' : 'success'}
/>
{hasOpenSlots && (
<Group gap={2} align="center">
<Icon icon={Activity} size={3} intent="success" />
<Text size="xs" variant="success" weight="bold" uppercase font="mono">
{openSlotsCount} slots available
</Text>
</Group>
)}
</Box>
<LeagueCardFooter>
<Stack gap={2}>
{timingSummary && (
<Group gap={2}>
<Icon icon={Calendar} size={3} intent="low" />
<Text size="xs" variant="low" font="mono">
{timingSummary.split('•')[1]?.trim() || timingSummary}
</Text>
</Group>
)}
<Group gap={2}>
<Icon icon={Users} size={3} intent="low" />
<Text size="xs" variant="low" font="mono">
{usedSlots} active participants
</Text>
</Group>
</Stack>
</LeagueCardFooter>
</Stack>
</UILeagueCard>
);
}