Update license year, enhance user management with last booking date, and improve admin dashboard navigation
This commit is contained in:
@@ -30,6 +30,7 @@ interface User {
|
||||
email: string;
|
||||
role: 'user' | 'admin';
|
||||
createdAt: string;
|
||||
lastBookingDate: string | null;
|
||||
}
|
||||
|
||||
interface UserFormData {
|
||||
@@ -387,58 +388,151 @@ export function AdminUserManagement() {
|
||||
<CardTitle>All Users ({filteredUsers.length})</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Role</TableHead>
|
||||
<TableHead>Created</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredUsers.map((user) => (
|
||||
<TableRow key={user.id}>
|
||||
<TableCell className='font-medium'>
|
||||
{user.name} {user.surname}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Mail className='h-4 w-4 text-gray-500' />
|
||||
{user.email}
|
||||
{/* Desktop Table */}
|
||||
<div className='hidden md:block'>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Role</TableHead>
|
||||
<TableHead>Created</TableHead>
|
||||
<TableHead>Last Played</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredUsers.map((user) => (
|
||||
<TableRow key={user.id}>
|
||||
<TableCell className='font-medium'>
|
||||
{user.name} {user.surname}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Mail className='h-4 w-4 text-gray-500' />
|
||||
{user.email}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={user.role === 'admin' ? 'default' : 'secondary'}>
|
||||
{user.role}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Calendar className='h-4 w-4 text-gray-500' />
|
||||
{new Date(user.createdAt).toLocaleDateString('en-IE')}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{user.lastBookingDate ? (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Calendar className='h-4 w-4 text-green-600' />
|
||||
{new Date(user.lastBookingDate).toLocaleDateString('en-IE')}
|
||||
</div>
|
||||
) : (
|
||||
<div className='flex items-center gap-2 text-gray-500'>
|
||||
<Calendar className='h-4 w-4' />
|
||||
Never played
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex gap-2'>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => openEditDialog(user)}
|
||||
>
|
||||
<Edit className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => openDeleteDialog(user)}
|
||||
className='text-red-600 hover:text-red-700'
|
||||
>
|
||||
<Trash2 className='h-4 w-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
{/* Mobile Card Layout */}
|
||||
<div className='md:hidden space-y-4'>
|
||||
{filteredUsers.map((user) => (
|
||||
<Card key={user.id} className='p-4'>
|
||||
<div className='space-y-3'>
|
||||
<div className='flex items-start justify-between'>
|
||||
<div>
|
||||
<h3 className='font-medium text-sm'>
|
||||
{user.name} {user.surname}
|
||||
</h3>
|
||||
<p className='text-xs text-muted-foreground flex items-center gap-1 mt-1'>
|
||||
<Mail className='h-3 w-3' />
|
||||
{user.email}
|
||||
</p>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={user.role === 'admin' ? 'default' : 'secondary'}>
|
||||
<Badge
|
||||
variant={user.role === 'admin' ? 'default' : 'secondary'}
|
||||
className='text-xs'
|
||||
>
|
||||
{user.role}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Calendar className='h-4 w-4 text-gray-500' />
|
||||
{new Date(user.createdAt).toLocaleDateString('en-IE')}
|
||||
</div>
|
||||
|
||||
<div className='grid grid-cols-2 gap-3 text-xs'>
|
||||
<div>
|
||||
<span className='text-muted-foreground block'>Created</span>
|
||||
<span className='flex items-center gap-1 mt-1'>
|
||||
<Calendar className='h-3 w-3 text-gray-500' />
|
||||
{new Date(user.createdAt).toLocaleDateString('en-IE')}
|
||||
</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className='flex gap-2'>
|
||||
<Button variant='outline' size='sm' onClick={() => openEditDialog(user)}>
|
||||
<Edit className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => openDeleteDialog(user)}
|
||||
className='text-red-600 hover:text-red-700'
|
||||
>
|
||||
<Trash2 className='h-4 w-4' />
|
||||
</Button>
|
||||
<div>
|
||||
<span className='text-muted-foreground block'>Last Played</span>
|
||||
{user.lastBookingDate ? (
|
||||
<span className='flex items-center gap-1 mt-1'>
|
||||
<Calendar className='h-3 w-3 text-green-600' />
|
||||
{new Date(user.lastBookingDate).toLocaleDateString('en-IE')}
|
||||
</span>
|
||||
) : (
|
||||
<span className='flex items-center gap-1 mt-1 text-gray-500'>
|
||||
<Calendar className='h-3 w-3' />
|
||||
Never played
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<div className='flex gap-2 pt-2'>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => openEditDialog(user)}
|
||||
className='flex-1'
|
||||
>
|
||||
<Edit className='h-3 w-3 mr-1' />
|
||||
Edit
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => openDeleteDialog(user)}
|
||||
className='flex-1 text-red-600 hover:text-red-700'
|
||||
>
|
||||
<Trash2 className='h-3 w-3 mr-1' />
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
{filteredUsers.length === 0 && (
|
||||
<div className='text-center py-8 text-gray-500'>
|
||||
No users found matching your search criteria
|
||||
|
||||
Reference in New Issue
Block a user