119 lines
4.3 KiB
TypeScript
119 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import { Box } from '@/ui/Box';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { Text } from '@/ui/Text';
|
|
import { Surface } from '@/ui/Surface';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from '@/ui/Table';
|
|
import { Trophy, TrendingUp } from 'lucide-react';
|
|
|
|
interface StandingsEntry {
|
|
position: number;
|
|
driverName: string;
|
|
points: number;
|
|
wins: number;
|
|
podiums: number;
|
|
change?: number;
|
|
}
|
|
|
|
interface StandingsTableShellProps {
|
|
standings: StandingsEntry[];
|
|
title?: string;
|
|
}
|
|
|
|
export function StandingsTableShell({ standings, title = 'Championship Standings' }: StandingsTableShellProps) {
|
|
return (
|
|
<Surface variant="dark" border rounded="lg" overflow="hidden">
|
|
<Box px={6} py={4} borderBottom borderColor="border-charcoal-outline" bg="bg-iron-gray/20">
|
|
<Stack direction="row" align="center" justify="between">
|
|
<Stack direction="row" align="center" gap={2}>
|
|
<Icon icon={Trophy} size={4} color="text-warning-amber" />
|
|
<Text weight="bold" letterSpacing="wider" size="sm" display="block">
|
|
{title.toUpperCase()}
|
|
</Text>
|
|
</Stack>
|
|
<Box px={2} py={0.5} rounded="md" bg="bg-charcoal-outline/50">
|
|
<Text size="xs" color="text-gray-400" weight="medium">{standings.length} Drivers</Text>
|
|
</Box>
|
|
</Stack>
|
|
</Box>
|
|
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableHeader w="4rem">Pos</TableHeader>
|
|
<TableHeader>Driver</TableHeader>
|
|
<TableHeader textAlign="center">Wins</TableHeader>
|
|
<TableHeader textAlign="center">Podiums</TableHeader>
|
|
<TableHeader textAlign="right">Points</TableHeader>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{standings.map((entry) => (
|
|
<TableRow key={entry.driverName}>
|
|
<TableCell>
|
|
<PositionBadge position={entry.position} />
|
|
</TableCell>
|
|
<TableCell>
|
|
<Stack direction="row" align="center" gap={3}>
|
|
<Text weight="bold" color="text-white">{entry.driverName}</Text>
|
|
{entry.change !== undefined && entry.change !== 0 && (
|
|
<Stack direction="row" align="center" gap={0.5}>
|
|
<Icon
|
|
icon={TrendingUp}
|
|
size={3}
|
|
color={entry.change > 0 ? 'text-performance-green' : 'text-error-red'}
|
|
transform={entry.change < 0 ? 'rotate(180deg)' : undefined}
|
|
/>
|
|
<Text size="xs" color={entry.change > 0 ? 'text-performance-green' : 'text-error-red'}>
|
|
{Math.abs(entry.change)}
|
|
</Text>
|
|
</Stack>
|
|
)}
|
|
</Stack>
|
|
</TableCell>
|
|
<TableCell textAlign="center">
|
|
<Text size="sm" color={entry.wins > 0 ? 'text-white' : 'text-gray-500'}>{entry.wins}</Text>
|
|
</TableCell>
|
|
<TableCell textAlign="center">
|
|
<Text size="sm" color={entry.podiums > 0 ? 'text-white' : 'text-gray-500'}>{entry.podiums}</Text>
|
|
</TableCell>
|
|
<TableCell textAlign="right">
|
|
<Text weight="bold" color="text-primary-blue">{entry.points}</Text>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</Surface>
|
|
);
|
|
}
|
|
|
|
function PositionBadge({ position }: { position: number }) {
|
|
const isPodium = position <= 3;
|
|
const colors = {
|
|
1: 'text-warning-amber bg-warning-amber/10 border-warning-amber/20',
|
|
2: 'text-gray-300 bg-gray-300/10 border-gray-300/20',
|
|
3: 'text-orange-400 bg-orange-400/10 border-orange-400/20',
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
center
|
|
w={8}
|
|
h={8}
|
|
rounded="md"
|
|
border={isPodium}
|
|
bg={isPodium ? colors[position as keyof typeof colors].split(' ')[1] : undefined}
|
|
color={isPodium ? colors[position as keyof typeof colors].split(' ')[0] : 'text-gray-500'}
|
|
borderColor={isPodium ? colors[position as keyof typeof colors].split(' ')[2] : undefined}
|
|
>
|
|
<Text size="sm" weight="bold">
|
|
{position}
|
|
</Text>
|
|
</Box>
|
|
);
|
|
}
|