Files
gridpilot.gg/apps/website/components/leagues/ScheduleTable.tsx
2026-01-18 23:24:30 +01:00

117 lines
3.7 KiB
TypeScript

'use client';
import { routes } from '@/lib/routing/RouteConfig';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/ui/Table';
import { Text } from '@/ui/Text';
import { Calendar, ChevronRight, MapPin } from 'lucide-react';
interface RaceEntry {
id: string;
name: string;
track: string;
scheduledAt: string;
status: 'upcoming' | 'live' | 'completed';
}
interface ScheduleTableProps {
races: RaceEntry[];
}
export function ScheduleTable({ races }: ScheduleTableProps) {
return (
<Surface variant="dark" border rounded="lg" overflow="hidden">
<Table>
<TableHead>
<TableRow>
<TableHeader>Race</TableHeader>
<TableHeader>Track</TableHeader>
<TableHeader>Date</TableHeader>
<TableHeader>Status</TableHeader>
<TableHeader textAlign="right">Actions</TableHeader>
</TableRow>
</TableHead>
<TableBody>
{races.length === 0 ? (
<TableRow>
<TableCell colSpan={5} textAlign="center" py={12}>
<Text color="text-gray-500">No races scheduled yet.</Text>
</TableCell>
</TableRow>
) : (
races.map((race) => (
<TableRow key={race.id}>
<TableCell>
<Text weight="medium" color="text-white">{race.name}</Text>
</TableCell>
<TableCell>
<Stack direction="row" align="center" gap={2}>
<Icon icon={MapPin} size={3.5} color="text-gray-500" />
<Text size="sm" color="text-gray-400">{race.track}</Text>
</Stack>
</TableCell>
<TableCell>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Calendar} size={3.5} color="text-gray-500" />
<Text size="sm" color="text-gray-400">
{new Date(race.scheduledAt).toLocaleDateString()}
</Text>
</Stack>
</TableCell>
<TableCell>
<StatusBadge status={race.status} />
</TableCell>
<TableCell textAlign="right">
<Link
href={routes.race.detail(race.id)}
variant="primary"
size="xs"
weight="bold"
letterSpacing="wider"
>
<Stack direction="row" align="center" gap={1}>
<Text>DETAILS</Text>
<Icon icon={ChevronRight} size={3} />
</Stack>
</Link>
</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</Surface>
);
}
function StatusBadge({ status }: { status: RaceEntry['status'] }) {
const styles = {
upcoming: 'bg-gray-500/10 text-gray-500 border-gray-500/20',
live: 'bg-performance-green/10 text-performance-green border-performance-green/20 animate-pulse',
completed: 'bg-primary-blue/10 text-primary-blue border-primary-blue/20',
};
return (
<Stack
as="span"
px={2}
py={0.5}
rounded="full"
fontSize="10px"
border
bg={styles[status].split(' ')[0]}
color={styles[status].split(' ')[1]}
borderColor={styles[status].split(' ')[2]}
animate={status === 'live' ? 'pulse' : 'none'}
letterSpacing="widest"
weight="bold"
display="inline-block"
>
{status.toUpperCase()}
</Stack>
);
}