basic stracture and auth

in memory db :)
This commit is contained in:
dimitar committed 2025-11-07 20:59:56 +01:00
commit 3a554ba434
71 files changed
+28535

No files matched your search

@@ -0,0 +1,180 @@
'use client'
import { useState, useEffect } from 'react'
import { UserGrid } from '@/components/users/UserGrid'
import { Button } from '@/components/ui/Button'
import { Card, CardHeader, CardContent } from '@/components/ui/Card'
interface User {
id: string
email: string
firstName: string
lastName: string
role: string
phone?: string
createdAt: Date
client?: {
id: string
membershipType: string
membershipStatus: string
joinDate: Date
lastVisit?: Date
}
}
export function UserManagement() {
const [users, setUsers] = useState<User[]>([])
const [loading, setLoading] = useState(true)
const [filter, setFilter] = useState<string>('all')
const [selectedUser, setSelectedUser] = useState<User | null>(null)
useEffect(() => {
fetchUsers()
}, [filter])
const fetchUsers = async () => {
setLoading(true)
try {
const url = filter === 'all'
? '/api/users'
: `/api/users?role=${filter}`
const response = await fetch(url)
const data = await response.json()
setUsers(data.users || [])
} catch (error) {
console.error('Failed to fetch users:', error)
} finally {
setLoading(false)
}
}
const handleUserSelect = (user: User) => {
setSelectedUser(user)
}
const handleExport = () => {
const csvContent = [
['Name', 'Email', 'Role', 'Phone', 'Membership', 'Status', 'Join Date', 'Last Visit'],
...users.map(user => [
`${user.firstName} ${user.lastName}`,
user.email,
user.role,
user.phone || '',
user.client?.membershipType || '',
user.client?.membershipStatus || '',
user.client?.joinDate || user.createdAt,
user.client?.lastVisit || ''
])
].map(row => row.join(',')).join('\n')
const blob = new Blob([csvContent], { type: 'text/csv' })
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `users_${new Date().toISOString().split('T')[0]}.csv`
a.click()
window.URL.revokeObjectURL(url)
}
const handleRefresh = () => {
fetchUsers()
}
return (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold">User Management</h2>
<div className="flex gap-2">
<Button
variant={filter === 'all' ? 'primary' : 'secondary'}
onClick={() => setFilter('all')}
>
All Users
</Button>
<Button
variant={filter === 'client' ? 'primary' : 'secondary'}
onClick={() => setFilter('client')}
>
Clients
</Button>
<Button
variant={filter === 'trainer' ? 'primary' : 'secondary'}
onClick={() => setFilter('trainer')}
>
Trainers
</Button>
<Button
variant={filter === 'admin' ? 'primary' : 'secondary'}
onClick={() => setFilter('admin')}
>
Admins
</Button>
</div>
</div>
<div className="flex justify-between items-center">
<div className="text-sm text-gray-600">
Showing {users.length} users
{selectedUser && (
<span className="ml-4 text-blue-600">
Selected: {selectedUser.firstName} {selectedUser.lastName}
</span>
)}
</div>
<div className="flex gap-2">
<Button variant="secondary" onClick={handleRefresh}>
Refresh
</Button>
<Button variant="secondary" onClick={handleExport}>
Export CSV
</Button>
</div>
</div>
<Card>
<CardContent className="p-0">
<UserGrid
users={users}
onUserSelect={handleUserSelect}
loading={loading}
/>
</CardContent>
</Card>
{selectedUser && (
<Card>
<CardHeader>
<h3 className="text-lg font-semibold">User Details</h3>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-4">
<div>
<h4 className="font-medium mb-2">Basic Information</h4>
<div className="space-y-1 text-sm">
<p><span className="font-medium">Name:</span> {selectedUser.firstName} {selectedUser.lastName}</p>
<p><span className="font-medium">Email:</span> {selectedUser.email}</p>
<p><span className="font-medium">Phone:</span> {selectedUser.phone || 'N/A'}</p>
<p><span className="font-medium">Role:</span> {selectedUser.role}</p>
<p><span className="font-medium">Joined:</span> {selectedUser.createdAt.toLocaleDateString()}</p>
</div>
</div>
{selectedUser.client && (
<div>
<h4 className="font-medium mb-2">Client Information</h4>
<div className="space-y-1 text-sm">
<p><span className="font-medium">Membership:</span> {selectedUser.client.membershipType}</p>
<p><span className="font-medium">Status:</span> {selectedUser.client.membershipStatus}</p>
<p><span className="font-medium">Member Since:</span> {selectedUser.client.joinDate.toLocaleDateString()}</p>
<p><span className="font-medium">Last Visit:</span> {selectedUser.client.lastVisit?.toLocaleDateString() || 'Never'}</p>
</div>
</div>
)}
</div>
</CardContent>
</Card>
)}
</div>
)
}