website refactor
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user