Files
gridpilot.gg/apps/website/components/leagues/LeagueCard.tsx
2026-01-17 15:46:55 +01:00

184 lines
5.7 KiB
TypeScript

'use client';
import React from 'react';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
import { Image } from '@/ui/Image';
import { Trophy, Users, Calendar, ChevronRight } from 'lucide-react';
interface LeagueCardProps {
id: string;
name: string;
description?: string;
coverUrl: string;
logoUrl?: string;
gameName?: string;
memberCount: number;
maxMembers?: number;
nextRaceDate?: string;
championshipType: 'driver' | 'team' | 'nations' | 'trophy';
onClick?: () => void;
}
export function LeagueCard({
name,
description,
coverUrl,
logoUrl,
gameName,
memberCount,
maxMembers,
nextRaceDate,
championshipType,
onClick,
}: LeagueCardProps) {
const fillPercentage = maxMembers ? (memberCount / maxMembers) * 100 : 0;
return (
<Box
as="article"
onClick={onClick}
position="relative"
display="flex"
flexDirection="col"
overflow="hidden"
border
borderColor="zinc-800"
bg="zinc-900/50"
hoverBorderColor="blue-500/30"
hoverBg="zinc-900"
transition
cursor="pointer"
group
>
{/* Cover Image */}
<Box position="relative" h="32" overflow="hidden">
<Box fullWidth fullHeight opacity={0.6}>
<Image
src={coverUrl}
alt={`${name} cover`}
fullWidth
fullHeight
objectFit="cover"
// eslint-disable-next-line gridpilot-rules/component-classification
className="transition-transform duration-500 group-hover:scale-105"
/>
</Box>
<Box position="absolute" inset="0" bg="linear-gradient(to top, #09090b, transparent)" />
{/* Game Badge */}
{gameName && (
<Box
position="absolute"
top="3"
left="3"
px={2}
py={1}
bg="zinc-900/80"
border
borderColor="white/10"
blur="sm"
>
<Text weight="bold" color="text-zinc-300" uppercase letterSpacing="0.05em" fontSize="10px">
{gameName}
</Text>
</Box>
)}
{/* Championship Icon */}
<Box
position="absolute"
top="3"
right="3"
p={1.5}
bg="zinc-900/80"
color="text-zinc-400"
border
borderColor="white/10"
blur="sm"
>
{championshipType === 'driver' && <Trophy size={14} />}
{championshipType === 'team' && <Users size={14} />}
</Box>
</Box>
{/* Content */}
<Box position="relative" display="flex" flexDirection="col" flexGrow={1} p={4} pt={6}>
{/* Logo */}
<Box
position="absolute"
top="-6"
left="4"
w="12"
h="12"
border
borderColor="zinc-800"
bg="zinc-950"
shadow="xl"
overflow="hidden"
>
{logoUrl ? (
<Image src={logoUrl} alt={`${name} logo`} fullWidth fullHeight objectFit="cover" />
) : (
<Box fullWidth fullHeight display="flex" alignItems="center" justifyContent="center" bg="zinc-900" color="text-zinc-700">
<Trophy size={20} />
</Box>
)}
</Box>
<Box display="flex" flexDirection="col" gap={1} mb={4}>
<Heading level={3} fontSize="lg" weight="bold" color="text-white"
// eslint-disable-next-line gridpilot-rules/component-classification
className="group-hover:text-blue-400 transition-colors truncate"
>
{name}
</Heading>
<Text size="xs" color="text-zinc-500" lineClamp={2} leading="relaxed" h="8">
{description || 'No description available'}
</Text>
</Box>
{/* Stats */}
<Box display="flex" flexDirection="col" gap={3} mt="auto">
<Box display="flex" flexDirection="col" gap={1.5}>
<Box display="flex" justifyContent="between">
<Text weight="bold" color="text-zinc-500" uppercase letterSpacing="widest" fontSize="10px">Drivers</Text>
<Text color="text-zinc-400" font="mono" fontSize="10px">{memberCount}/{maxMembers || '∞'}</Text>
</Box>
<Box h="1" bg="zinc-800" overflow="hidden">
<Box
h="full"
transition
bg={fillPercentage > 90 ? 'bg-amber-500' : 'bg-blue-500'}
w={`${Math.min(fillPercentage, 100)}%`}
/>
</Box>
</Box>
<Box display="flex" alignItems="center" justifyContent="between" pt={3} borderTop borderColor="zinc-800/50">
<Box display="flex" alignItems="center" gap={2} color="text-zinc-500">
<Calendar size={12} />
<Text weight="bold" uppercase font="mono" fontSize="10px">
{nextRaceDate || 'TBD'}
</Text>
</Box>
<Box display="flex" alignItems="center" gap={1} color="text-zinc-500"
// eslint-disable-next-line gridpilot-rules/component-classification
className="group-hover:text-blue-400 transition-colors"
>
<Text weight="bold" uppercase letterSpacing="widest" fontSize="10px">View</Text>
<Box
// eslint-disable-next-line gridpilot-rules/component-classification
className="transition-transform group-hover:translate-x-0.5"
>
<ChevronRight size={12} />
</Box>
</Box>
</Box>
</Box>
</Box>
</Box>
);
}