113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
'use client';
|
|
|
|
import { ChevronRight } from 'lucide-react';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { Card } from '@/ui/Card';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { Link } from '@/ui/Link';
|
|
import { Text } from '@/ui/Text';
|
|
import { routes } from '@/lib/routing/RouteConfig';
|
|
|
|
interface RaceResultCardProps {
|
|
raceId: string;
|
|
track: string;
|
|
car: string;
|
|
scheduledAt: string | Date;
|
|
position: number;
|
|
startPosition: number;
|
|
incidents: number;
|
|
leagueName?: string;
|
|
showLeague?: boolean;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
export function RaceResultCard({
|
|
raceId,
|
|
track,
|
|
car,
|
|
scheduledAt,
|
|
position,
|
|
startPosition,
|
|
incidents,
|
|
leagueName,
|
|
showLeague = true,
|
|
onClick,
|
|
}: RaceResultCardProps) {
|
|
const getPositionStyles = (pos: number) => {
|
|
if (pos === 1) return { color: 'text-warning-amber', bg: 'bg-warning-amber', bgOpacity: 0.2 };
|
|
if (pos === 2) return { color: 'text-gray-300', bg: 'bg-gray-400', bgOpacity: 0.2 };
|
|
if (pos === 3) return { color: 'text-amber-600', bg: 'bg-amber-600', bgOpacity: 0.2 };
|
|
return { color: 'text-gray-400', bg: 'bg-base-black', bgOpacity: 0.5 };
|
|
};
|
|
|
|
const positionStyles = getPositionStyles(position);
|
|
|
|
return (
|
|
<Link
|
|
href={routes.race.detail(raceId)}
|
|
variant="ghost"
|
|
block
|
|
onClick={onClick}
|
|
>
|
|
<Card p={4} hoverBorderColor="border-primary-accent" transition group bg="bg-surface-charcoal" border borderColor="border-outline-steel">
|
|
<Stack display="flex" alignItems="center" justifyContent="between" mb={2}>
|
|
<Stack direction="row" align="center" gap={3}>
|
|
<Stack
|
|
width="8"
|
|
height="8"
|
|
rounded="md"
|
|
display="flex"
|
|
center
|
|
weight="bold"
|
|
size="sm"
|
|
color={positionStyles.color}
|
|
bg={positionStyles.bg}
|
|
bgOpacity={positionStyles.bgOpacity}
|
|
border
|
|
borderColor="border-outline-steel"
|
|
>
|
|
P{position}
|
|
</Stack>
|
|
<Stack>
|
|
<Text color="text-white" weight="medium" block groupHoverTextColor="text-primary-accent" transition>
|
|
{track}
|
|
</Text>
|
|
<Text size="sm" color="text-gray-400" block>{car}</Text>
|
|
</Stack>
|
|
</Stack>
|
|
<Stack direction="row" align="center" gap={3}>
|
|
<Stack textAlign="right">
|
|
<Text size="sm" color="text-gray-400" block>
|
|
{new Date(scheduledAt).toLocaleDateString('en-US', {
|
|
month: 'short',
|
|
day: 'numeric',
|
|
year: 'numeric',
|
|
})}
|
|
</Text>
|
|
{showLeague && leagueName && (
|
|
<Text size="xs" color="text-gray-500" block>{leagueName}</Text>
|
|
)}
|
|
</Stack>
|
|
<Icon icon={ChevronRight} size={5} color="text-gray-500" groupHoverTextColor="text-primary-accent" transition />
|
|
</Stack>
|
|
</Stack>
|
|
<Stack direction="row" align="center" gap={4}>
|
|
<Text size="xs" color="text-gray-500">Started P{startPosition}</Text>
|
|
<Text size="xs" color="text-gray-500">•</Text>
|
|
<Text size="xs" color={incidents === 0 ? 'text-success-green' : incidents > 2 ? 'text-error-red' : 'text-gray-500'}>
|
|
{incidents}x incidents
|
|
</Text>
|
|
{position < startPosition && (
|
|
<>
|
|
<Text size="xs" color="text-gray-500">•</Text>
|
|
<Text size="xs" color="text-success-green">
|
|
+{startPosition - position} positions
|
|
</Text>
|
|
</>
|
|
)}
|
|
</Stack>
|
|
</Card>
|
|
</Link>
|
|
);
|
|
}
|