website refactor
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Select } from '@/ui/Select';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Shield, UserPlus, UserMinus } from 'lucide-react';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from '@/ui/Table';
|
||||
import type { MembershipRole } from '@/lib/types/MembershipRole';
|
||||
import type { LeagueRosterAdminViewData } from '@/lib/view-data/LeagueRosterAdminViewData';
|
||||
|
||||
@@ -36,119 +37,131 @@ export function RosterAdminTemplate({
|
||||
const { joinRequests, members } = viewData;
|
||||
|
||||
return (
|
||||
<Stack gap={6}>
|
||||
<Card>
|
||||
<Stack gap={6}>
|
||||
<Box>
|
||||
<Heading level={1}>Roster Admin</Heading>
|
||||
<Text size="sm" color="text-gray-400" block mt={1}>
|
||||
Manage join requests and member roles.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Stack direction="row" align="center" justify="between" mb={4}>
|
||||
<Heading level={2}>Pending join requests</Heading>
|
||||
<Text size="xs" color="text-gray-500">
|
||||
{pendingCountLabel}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
{loading ? (
|
||||
<Text size="sm" color="text-gray-400">Loading…</Text>
|
||||
) : joinRequests.length > 0 ? (
|
||||
<Stack gap={3}>
|
||||
{joinRequests.map((req) => (
|
||||
<Surface
|
||||
key={req.id}
|
||||
variant="muted"
|
||||
rounded="lg"
|
||||
border
|
||||
padding={3}
|
||||
>
|
||||
<Stack direction="row" align="center" justify="between">
|
||||
<Box>
|
||||
<Text weight="medium" color="text-white" block>{req.driver.name}</Text>
|
||||
<Text size="xs" color="text-gray-400" block mt={1}>{req.requestedAt}</Text>
|
||||
{req.message && (
|
||||
<Text size="xs" color="text-gray-500" block mt={1} truncate>{req.message}</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Stack direction="row" gap={2}>
|
||||
<Button
|
||||
onClick={() => onApprove(req.id)}
|
||||
variant="primary"
|
||||
size="sm"
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => onReject(req.id)}
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Surface>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Text size="sm" color="text-gray-500">No pending join requests.</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box pt={6} borderTop borderColor="border-neutral-800">
|
||||
<Box mb={4}>
|
||||
<Heading level={2}>Members</Heading>
|
||||
</Box>
|
||||
|
||||
{loading ? (
|
||||
<Text size="sm" color="text-gray-400">Loading…</Text>
|
||||
) : members.length > 0 ? (
|
||||
<Stack gap={3}>
|
||||
{members.map((member) => (
|
||||
<Surface
|
||||
key={member.driverId}
|
||||
variant="muted"
|
||||
rounded="lg"
|
||||
border
|
||||
padding={3}
|
||||
>
|
||||
<Stack direction="row" align="center" justify="between" wrap gap={4}>
|
||||
<Box>
|
||||
<Text weight="medium" color="text-white" block>{member.driver.name}</Text>
|
||||
<Text size="xs" color="text-gray-400" block mt={1}>{member.joinedAt}</Text>
|
||||
</Box>
|
||||
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Box>
|
||||
<Select
|
||||
value={member.role}
|
||||
onChange={(e) => onRoleChange(member.driverId, e.target.value as MembershipRole)}
|
||||
options={roleOptions.map((role) => ({ value: role, label: role }))}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
onClick={() => onRemove(member.driverId)}
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Surface>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Text size="sm" color="text-gray-500">No members found.</Text>
|
||||
)}
|
||||
<Stack gap={8}>
|
||||
{/* Join Requests Section */}
|
||||
<Box>
|
||||
<Stack direction="row" align="center" justify="between" mb={4}>
|
||||
<Stack direction="row" align="center" gap={2}>
|
||||
<Icon icon={UserPlus} size={4} color="text-primary-blue" />
|
||||
<Heading level={5} color="text-primary-blue">PENDING JOIN REQUESTS</Heading>
|
||||
</Stack>
|
||||
<Box px={2} py={0.5} rounded="md" bg="bg-primary-blue/10" border borderColor="border-primary-blue/20">
|
||||
<Text size="xs" color="text-primary-blue" weight="bold">{pendingCountLabel}</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
{loading ? (
|
||||
<Surface variant="dark" border rounded="lg" padding={12} center>
|
||||
<Text color="text-gray-500">Loading requests...</Text>
|
||||
</Surface>
|
||||
) : joinRequests.length > 0 ? (
|
||||
<Surface variant="dark" border rounded="lg" overflow="hidden">
|
||||
<Stack gap={0}>
|
||||
{joinRequests.map((req) => (
|
||||
<Box key={req.id} p={4} borderBottom borderColor="border-charcoal-outline" hoverBg="bg-white/5" transition>
|
||||
<Stack direction={{ base: 'col', md: 'row' }} align="center" justify="between" gap={4}>
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold" color="text-white">{req.driver.name}</Text>
|
||||
<Text size="xs" color="text-gray-500">{new Date(req.requestedAt).toLocaleString()}</Text>
|
||||
{req.message && (
|
||||
<Text size="sm" color="text-gray-400" mt={1}>"{req.message}"</Text>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row" gap={2}>
|
||||
<Button onClick={() => onApprove(req.id)} variant="primary" size="sm">
|
||||
Approve
|
||||
</Button>
|
||||
<Button onClick={() => onReject(req.id)} variant="secondary" size="sm">
|
||||
Reject
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Surface>
|
||||
) : (
|
||||
<Surface variant="dark" border rounded="lg" padding={8} center>
|
||||
<Text color="text-gray-500">No pending join requests.</Text>
|
||||
</Surface>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Members Section */}
|
||||
<Box>
|
||||
<Stack direction="row" align="center" gap={2} mb={4}>
|
||||
<Icon icon={Shield} size={4} color="text-performance-green" />
|
||||
<Heading level={5} color="text-performance-green">ACTIVE ROSTER</Heading>
|
||||
</Stack>
|
||||
|
||||
{loading ? (
|
||||
<Surface variant="dark" border rounded="lg" padding={12} center>
|
||||
<Text color="text-gray-500">Loading members...</Text>
|
||||
</Surface>
|
||||
) : members.length > 0 ? (
|
||||
<Surface variant="dark" border rounded="lg" overflow="hidden">
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeader>Driver</TableHeader>
|
||||
<TableHeader>Joined</TableHeader>
|
||||
<TableHeader>Role</TableHeader>
|
||||
<TableHeader textAlign="right">Actions</TableHeader>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{members.map((member) => (
|
||||
<TableRow key={member.driverId}>
|
||||
<TableCell>
|
||||
<Text weight="bold" color="text-white">{member.driver.name}</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text size="sm" color="text-gray-400">{new Date(member.joinedAt).toLocaleDateString()}</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Box
|
||||
as="select"
|
||||
value={member.role}
|
||||
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => onRoleChange(member.driverId, e.target.value as MembershipRole)}
|
||||
bg="bg-iron-gray"
|
||||
border
|
||||
borderColor="border-charcoal-outline"
|
||||
rounded="md"
|
||||
px={2}
|
||||
py={1}
|
||||
fontSize="xs"
|
||||
weight="bold"
|
||||
color="text-white"
|
||||
>
|
||||
{roleOptions.map((role) => (
|
||||
<Box as="option" key={role} value={role}>{role.toUpperCase()}</Box>
|
||||
))}
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell textAlign="right">
|
||||
<Button
|
||||
onClick={() => onRemove(member.driverId)}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
>
|
||||
<Stack direction="row" align="center" gap={1.5}>
|
||||
<Icon icon={UserMinus} size={3.5} color="text-error-red" />
|
||||
<Text size="xs" weight="bold" color="text-error-red">REMOVE</Text>
|
||||
</Stack>
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Surface>
|
||||
) : (
|
||||
<Surface variant="dark" border rounded="lg" padding={8} center>
|
||||
<Text color="text-gray-500">No members found.</Text>
|
||||
</Surface>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user