website refactor
This commit is contained in:
113
apps/website/components/races/RaceResultCard.tsx
Normal file
113
apps/website/components/races/RaceResultCard.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
'use client';
|
||||
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Link } from '@/ui/Link';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
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">
|
||||
<Box display="flex" alignItems="center" justifyContent="between" mb={2}>
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Box
|
||||
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}
|
||||
</Box>
|
||||
<Box>
|
||||
<Text color="text-white" weight="medium" block groupHoverTextColor="text-primary-accent" transition>
|
||||
{track}
|
||||
</Text>
|
||||
<Text size="sm" color="text-gray-400" block>{car}</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Box 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>
|
||||
)}
|
||||
</Box>
|
||||
<Icon icon={ChevronRight} size={5} color="text-gray-500" groupHoverTextColor="text-primary-accent" transition />
|
||||
</Stack>
|
||||
</Box>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user