website refactor

This commit is contained in:
2026-01-18 22:55:55 +01:00
parent b43a23a48c
commit aeaa43f4d3
179 changed files with 4736 additions and 6832 deletions

View File

@@ -2,7 +2,8 @@
import { LeagueMemberRow } from '@/components/leagues/LeagueMemberRow';
import { LeagueMemberTable } from '@/components/leagues/LeagueMemberTable';
import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
import { EmptyState } from '@/ui/EmptyState';
import { LoadingWrapper } from '@/ui/LoadingWrapper';
import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
import { useInject } from '@/lib/di/hooks/useInject';
import { DRIVER_SERVICE_TOKEN, LEAGUE_MEMBERSHIP_SERVICE_TOKEN } from '@/lib/di/tokens';
@@ -11,10 +12,11 @@ import type { LeagueMembership } from '@/lib/types/LeagueMembership';
import type { MembershipRole } from '@/lib/types/MembershipRole';
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
import { Button } from '@/ui/Button';
import { Box } from '@/ui/primitives/Box';
import { Select } from '@/ui/Select';
import { Text } from '@/ui/Text';
import { ControlBar } from '@/ui/ControlBar';
import { useCallback, useEffect, useState } from 'react';
import React from 'react';
interface LeagueMembersProps {
leagueId: string;
@@ -83,7 +85,6 @@ export function LeagueMembers({
return null;
};
// eslint-disable-next-line gridpilot-rules/component-no-data-manipulation
const sortedMembers = [...members].sort((a, b) => {
switch (sortBy) {
case 'role':
@@ -120,31 +121,30 @@ export function LeagueMembers({
};
if (loading) {
return (
<Box textAlign="center" py={8}>
<Text color="text-gray-400">Loading members...</Text>
</Box>
);
return <LoadingWrapper variant="spinner" message="Loading members..." />;
}
if (members.length === 0) {
return (
<MinimalEmptyState
<EmptyState
title="No members found"
description="This league doesn't have any members yet."
variant="minimal"
/>
);
}
return (
<Box>
{/* Sort Controls */}
<Box display="flex" alignItems="center" justifyContent="between" mb={4}>
<Text size="sm" color="text-gray-400">
{members.length} {members.length === 1 ? 'member' : 'members'}
</Text>
<Box display="flex" alignItems="center" gap={2}>
<Text as="label" size="sm" color="text-gray-400">Sort by:</Text>
<div>
<ControlBar
leftContent={
<Text size="sm" variant="low">
{members.length} {members.length === 1 ? 'member' : 'members'}
</Text>
}
>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<Text size="sm" variant="low">Sort by:</Text>
<Select
value={sortBy}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setSortBy(e.target.value as typeof sortBy)}
@@ -158,11 +158,10 @@ export function LeagueMembers({
]}
fullWidth={false}
/>
</Box>
</Box>
</div>
</ControlBar>
{/* Members Table */}
<Box overflow="auto">
<div style={{ overflowX: 'auto', marginTop: '1rem' }}>
<LeagueMemberTable showActions={showActions}>
{sortedMembers.map((member, index) => {
const isCurrentUser = member.driverId === currentDriverId;
@@ -191,7 +190,7 @@ export function LeagueMembers({
href={routes.driver.detail(member.driverId)}
meta={ratingAndWinsMeta}
actions={showActions && !cannotModify && !isCurrentUser ? (
<Box display="flex" alignItems="center" justifyContent="end" gap={2}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: '0.5rem' }}>
{onUpdateRole && (
<Select
value={member.role}
@@ -202,8 +201,6 @@ export function LeagueMembers({
{ value: 'admin', label: 'Admin' },
]}
fullWidth={false}
// eslint-disable-next-line gridpilot-rules/component-classification
className="text-xs py-1 px-2"
/>
)}
{onRemoveMember && (
@@ -211,18 +208,17 @@ export function LeagueMembers({
variant="ghost"
onClick={() => onRemoveMember(member.driverId)}
size="sm"
color="text-error-red"
>
Remove
<Text variant="critical">Remove</Text>
</Button>
)}
</Box>
) : (showActions && cannotModify ? <Text size="xs" color="text-gray-500"></Text> : undefined)}
</div>
) : (showActions && cannotModify ? <Text size="xs" variant="low"></Text> : undefined)}
/>
);
})}
</LeagueMemberTable>
</Box>
</Box>
</div>
</div>
);
}