import { useState, useEffect } from 'react'; import { useNavigate } from '@remix-run/react'; import { motion, AnimatePresence } from 'framer-motion'; import { useStore } from '@nanostores/react'; import { authStore } from '~/lib/stores/auth'; import { ProtectedRoute } from '~/components/auth/ProtectedRoute'; import { classNames } from '~/utils/classNames'; interface User { id: string; username: string; firstName: string; avatar?: string; createdAt: string; lastLogin?: string; } export default function UserManagement() { const navigate = useNavigate(); const authState = useStore(authStore); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [selectedUser, setSelectedUser] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [deleting, setDeleting] = useState(false); useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { try { const response = await fetch('/api/users', { headers: { Authorization: `Bearer ${authState.token}`, }, }); if (response.ok) { const data = (await response.json()) as { users: User[] }; setUsers(data.users); } } catch (error) { console.error('Failed to fetch users:', error); } finally { setLoading(false); } }; const handleDeleteUser = async () => { if (!selectedUser) { return; } setDeleting(true); try { const response = await fetch(`/api/users/${selectedUser.id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${authState.token}`, }, }); if (response.ok) { setUsers(users.filter((u) => u.id !== selectedUser.id)); setShowDeleteModal(false); setSelectedUser(null); } } catch (error) { console.error('Failed to delete user:', error); } finally { setDeleting(false); } }; const filteredUsers = users.filter( (user) => user.username.toLowerCase().includes(searchQuery.toLowerCase()) || user.firstName.toLowerCase().includes(searchQuery.toLowerCase()), ); return (
{/* Header */}

User Management

Manage system users

setSearchQuery(e.target.value)} className={classNames( 'w-64 px-4 py-2 pl-10 rounded-lg', 'bg-bolt-elements-background-depth-1', 'border border-bolt-elements-borderColor', 'text-bolt-elements-textPrimary placeholder-bolt-elements-textTertiary', 'focus:outline-none focus:ring-2 focus:ring-accent-500', )} />
{/* User Stats */}

Total Users

{users.length}

Active Today

{ users.filter((u) => { if (!u.lastLogin) { return false; } const lastLogin = new Date(u.lastLogin); const today = new Date(); return lastLogin.toDateString() === today.toDateString(); }).length }

New This Week

{ users.filter((u) => { const created = new Date(u.createdAt); const weekAgo = new Date(); weekAgo.setDate(weekAgo.getDate() - 7); return created > weekAgo; }).length }

Storage Used

0 MB

{/* User List */}
{loading ? (
) : filteredUsers.length === 0 ? (

{searchQuery ? 'No users found matching your search' : 'No users yet'}

) : (
{filteredUsers.map((user, index) => (
{user.avatar ? ( {user.firstName} ) : ( {user.firstName[0].toUpperCase()} )}

{user.firstName} {user.id === authState.user?.id && ( You )}

@{user.username}

{user.id !== authState.user?.id && ( )}
Joined {new Date(user.createdAt).toLocaleDateString()}
{user.lastLogin && (
Last active {new Date(user.lastLogin).toLocaleDateString()}
)}
))}
)}
{/* Delete Confirmation Modal */} {showDeleteModal && selectedUser && ( !deleting && setShowDeleteModal(false)} > e.stopPropagation()} >

Delete User

Are you sure you want to delete{' '} @{selectedUser.username}? This action cannot be undone and will permanently remove all user data.

)}
); }