website refactor

This commit is contained in:
2026-01-18 16:18:18 +01:00
parent 0b301feb61
commit 13567d51af
329 changed files with 4701 additions and 4750 deletions

View File

@@ -5,11 +5,10 @@ import { Link } from '@/ui/Link';
import { Image } from '@/ui/Image';
import { CountryFlag } from '@/ui/CountryFlag';
import { PlaceholderImage } from '@/ui/PlaceholderImage';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from '@/ui/Table';
import { Badge } from '@/ui/Badge';
import { Stack } from '@/ui/Stack';
import { routes } from '@/lib/routing/RouteConfig';
import { Icon } from '@/ui/Icon';
import { User, Edit } from 'lucide-react';
@@ -172,7 +171,7 @@ export function StandingsTable({
const hasMembership = !!membership;
return (
<Box
<Stack
ref={menuRef}
position="absolute"
right="0"
@@ -196,7 +195,7 @@ export function StandingsTable({
<>
{/* Role Management for existing members */}
{membership!.role !== 'admin' && membership!.role !== 'owner' && (
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRoleChange(driverId, 'admin'); }}
display="flex"
@@ -214,10 +213,10 @@ export function StandingsTable({
>
<Text>🛡</Text>
<Text>Promote to Admin</Text>
</Box>
</Stack>
)}
{membership!.role === 'admin' && (
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRoleChange(driverId, 'member'); }}
display="flex"
@@ -235,10 +234,10 @@ export function StandingsTable({
>
<Text></Text>
<Text>Demote to Member</Text>
</Box>
</Stack>
)}
{membership!.role === 'member' && (
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRoleChange(driverId, 'steward'); }}
display="flex"
@@ -256,10 +255,10 @@ export function StandingsTable({
>
<Text>🏁</Text>
<Text>Make Steward</Text>
</Box>
</Stack>
)}
{membership!.role === 'steward' && (
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRoleChange(driverId, 'member'); }}
display="flex"
@@ -277,10 +276,10 @@ export function StandingsTable({
>
<Text>🏁</Text>
<Text>Remove Steward</Text>
</Box>
</Stack>
)}
<Box borderTop borderColor="border-charcoal-outline" my={1} />
<Box
<Stack borderTop borderColor="border-charcoal-outline" my={1} />
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRemove(driverId); }}
display="flex"
@@ -298,15 +297,15 @@ export function StandingsTable({
>
<Text>🚫</Text>
<Text>Remove from League</Text>
</Box>
</Stack>
</>
) : (
<>
{/* Options for drivers without membership (participating but not formal members) */}
<Box bg="bg-yellow-500/10" rounded px={2} py={1} mb={1}>
<Stack bg="bg-yellow-500/10" rounded px={2} py={1} mb={1}>
<Text size="xs" color="text-yellow-400/80">Driver not a formal member</Text>
</Box>
<Box
</Stack>
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); alert('Add as member - feature coming soon'); }}
display="flex"
@@ -324,8 +323,8 @@ export function StandingsTable({
>
<Text></Text>
<Text>Add as Member</Text>
</Box>
<Box
</Stack>
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleRemove(driverId); }}
display="flex"
@@ -343,17 +342,17 @@ export function StandingsTable({
>
<Text>🚫</Text>
<Text>Remove from Standings</Text>
</Box>
</Stack>
</>
)}
</Stack>
</Box>
</Stack>
);
};
const PointsActionMenu = () => {
return (
<Box
<Stack
ref={menuRef}
position="absolute"
right="0"
@@ -373,7 +372,7 @@ export function StandingsTable({
Score Actions
</Text>
<Stack gap={1}>
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); alert('View detailed stats - feature coming soon'); }}
display="flex"
@@ -391,8 +390,8 @@ export function StandingsTable({
>
<Text>📊</Text>
<Text>View Details</Text>
</Box>
<Box
</Stack>
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); alert('Manual adjustment - feature coming soon'); }}
display="flex"
@@ -410,8 +409,8 @@ export function StandingsTable({
>
<Text></Text>
<Text>Adjust Points</Text>
</Box>
<Box
</Stack>
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); alert('Race history - feature coming soon'); }}
display="flex"
@@ -429,22 +428,22 @@ export function StandingsTable({
>
<Text>📝</Text>
<Text>Race History</Text>
</Box>
</Stack>
</Stack>
</Box>
</Stack>
);
};
if (standings.length === 0) {
return (
<Box textAlign="center" py={8}>
<Stack textAlign="center" py={8}>
<Text color="text-gray-400">No standings available</Text>
</Box>
</Stack>
);
}
return (
<Box overflow="auto">
<Stack overflow="auto">
<Table>
<TableHead>
<TableRow>
@@ -489,7 +488,7 @@ export function StandingsTable({
>
{/* Position */}
<TableCell textAlign="center" w="14">
<Box
<Stack
display="inline-flex"
alignItems="center"
justifyContent="center"
@@ -510,15 +509,15 @@ export function StandingsTable({
}
>
{row.position}
</Box>
</Stack>
</TableCell>
{/* Driver with Rating and Nationality */}
<TableCell position="relative">
<Box display="flex" alignItems="center" gap={3}>
<Stack display="flex" alignItems="center" gap={3}>
{/* Avatar */}
<Box position="relative">
<Box
<Stack position="relative">
<Stack
w="10"
h="10"
rounded="full"
@@ -544,18 +543,18 @@ export function StandingsTable({
<PlaceholderImage size={40} />
)
)}
</Box>
</Stack>
{/* Nationality flag */}
{driver && driver.country && (
<Box position="absolute" bottom="-1" right="-1">
<Stack position="absolute" bottom="-1" right="-1">
<CountryFlag countryCode={driver.country} size="sm" />
</Box>
</Stack>
)}
</Box>
</Stack>
{/* Name and Rating */}
<Box flexGrow={1} minWidth="0">
<Box display="flex" alignItems="center" gap={2}>
<Stack flexGrow={1} minWidth="0">
<Stack display="flex" alignItems="center" gap={2}>
<Link
href={routes.driver.detail(row.driverId)}
weight="medium"
@@ -570,7 +569,7 @@ export function StandingsTable({
<Badge variant="primary">You</Badge>
)}
{roleDisplay && roleDisplay.text !== 'Member' && (
<Box
<Stack
as="span"
px={2}
py={0.5}
@@ -583,14 +582,14 @@ export function StandingsTable({
borderColor={roleDisplay.borderColor}
>
{roleDisplay.text}
</Box>
</Stack>
)}
</Box>
</Box>
</Stack>
</Stack>
{/* Hover Actions for Member Management */}
{isAdmin && canModify && (
<Box
<Stack
display="flex"
alignItems="center"
gap={1}
@@ -598,7 +597,7 @@ export function StandingsTable({
transition
visibility={isRowHovered || isMemberMenuOpen ? 'visible' : 'hidden'}
>
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); setActiveMenu(isMemberMenuOpen ? null : { driverId: row.driverId, type: 'member' }); }}
p={1.5}
@@ -611,10 +610,10 @@ export function StandingsTable({
title="Manage member"
>
<Icon icon={User} size={4} />
</Box>
</Box>
</Stack>
</Stack>
)}
</Box>
</Stack>
{isMemberMenuOpen && <MemberActionMenu driverId={row.driverId} />}
</TableCell>
@@ -625,10 +624,10 @@ export function StandingsTable({
{/* Total Points with Hover Action */}
<TableCell textAlign="right" position="relative">
<Box display="flex" alignItems="center" justifyContent="end" gap={2}>
<Stack display="flex" alignItems="center" justifyContent="end" gap={2}>
<Text color="text-white" weight="bold" size="lg">{row.totalPoints}</Text>
{isAdmin && canModify && (
<Box
<Stack
as="button"
onClick={(e: React.MouseEvent) => { e.stopPropagation(); setActiveMenu(isPointsMenuOpen ? null : { driverId: row.driverId, type: 'points' }); }}
p={1}
@@ -643,9 +642,9 @@ export function StandingsTable({
title="Score actions"
>
<Icon icon={Edit} size={3} />
</Box>
</Stack>
)}
</Box>
</Stack>
{isPointsMenuOpen && <PointsActionMenu />}
</TableCell>
@@ -680,6 +679,6 @@ export function StandingsTable({
})}
</TableBody>
</Table>
</Box>
</Stack>
);
}