import { useState, useEffect } from 'react'; import { API_BASE_URL } from '../config/api'; interface User { id: string; email: string; name: string; picture: string; role: string; created_at: string; last_sign_in_at?: string; provider: string; } interface UserManagementProps { currentUser: any; } const UserManagement: React.FC = ({ currentUser }) => { const [users, setUsers] = useState([]); const [pendingUsers, setPendingUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [activeTab, setActiveTab] = useState<'all' | 'pending'>('all'); const [updatingUser, setUpdatingUser] = useState(null); // Check if current user is admin if (currentUser?.role !== 'administrator') { return (

Access Denied

You need administrator privileges to access user management.

); } const fetchUsers = async () => { try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Failed to fetch users'); } const userData = await response.json(); setUsers(userData); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch users'); } finally { setLoading(false); } }; const fetchPendingUsers = async () => { try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users/pending/list`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Failed to fetch pending users'); } const pendingData = await response.json(); setPendingUsers(pendingData); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch pending users'); } }; const updateUserRole = async (userEmail: string, newRole: string) => { setUpdatingUser(userEmail); try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users/${userEmail}/role`, { method: 'PATCH', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ role: newRole }) }); if (!response.ok) { throw new Error('Failed to update user role'); } // Refresh users list await fetchUsers(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to update user role'); } finally { setUpdatingUser(null); } }; const deleteUser = async (userEmail: string, userName: string) => { if (!confirm(`Are you sure you want to delete user "${userName}"? This action cannot be undone.`)) { return; } try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users/${userEmail}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Failed to delete user'); } // Refresh users list await fetchUsers(); await fetchPendingUsers(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete user'); } }; const approveUser = async (userEmail: string) => { setUpdatingUser(userEmail); try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users/${userEmail}/approval`, { method: 'PATCH', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'approved' }) }); if (!response.ok) { throw new Error('Failed to approve user'); } // Refresh both lists await fetchUsers(); await fetchPendingUsers(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to approve user'); } finally { setUpdatingUser(null); } }; const denyUser = async (userEmail: string, userName: string) => { if (!confirm(`Are you sure you want to deny access for "${userName}"?`)) { return; } setUpdatingUser(userEmail); try { const token = localStorage.getItem('authToken'); const response = await fetch(`${API_BASE_URL}/auth/users/${userEmail}/approval`, { method: 'PATCH', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'denied' }) }); if (!response.ok) { throw new Error('Failed to deny user'); } // Refresh both lists await fetchUsers(); await fetchPendingUsers(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to deny user'); } finally { setUpdatingUser(null); } }; useEffect(() => { fetchUsers(); fetchPendingUsers(); }, []); useEffect(() => { if (activeTab === 'pending') { fetchPendingUsers(); } }, [activeTab]); const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; const getRoleBadgeColor = (role: string) => { switch (role) { case 'administrator': return 'bg-red-100 text-red-800 border-red-200'; case 'coordinator': return 'bg-blue-100 text-blue-800 border-blue-200'; case 'driver': return 'bg-green-100 text-green-800 border-green-200'; default: return 'bg-gray-100 text-gray-800 border-gray-200'; } }; if (loading) { return (
{[1, 2, 3].map(i => (
))}
); } return (

User Management

Manage user accounts and permissions (PostgreSQL Database)

{error && (

{error}

)} {/* Tab Navigation */}
{/* Content based on active tab */} {activeTab === 'all' && (

All Users ({users.length})

{users.map((user) => (
{user.picture ? ( {user.name} ) : (
{user.name.charAt(0).toUpperCase()}
)}

{user.name}

{user.email}

Joined: {formatDate(user.created_at)} {user.last_sign_in_at && ( Last login: {formatDate(user.last_sign_in_at)} )} via {user.provider}
Role:
{user.email !== currentUser.email && ( )} {user.email === currentUser.email && ( 👤 You )}
))}
{users.length === 0 && (
No users found.
)}
)} {/* Pending Users Tab */} {activeTab === 'pending' && (

Pending Approval ({pendingUsers.length})

Users waiting for administrator approval to access the system

{pendingUsers.map((user) => (
{user.picture ? ( {user.name} ) : (
{user.name.charAt(0).toUpperCase()}
)}

{user.name}

{user.email}

Requested: {formatDate(user.created_at)} via {user.provider} {user.role}
))}
{pendingUsers.length === 0 && (

No pending approvals

All users have been processed.

)}
)}

Role Descriptions:

  • Administrator: Full access to all features including user management
  • Coordinator: Can manage VIPs, drivers, and schedules
  • Driver: Can view assigned schedules and update status

🔐 User Approval System:

New users (except the first administrator) require approval before accessing the system. Users with pending approval will see a "pending approval" message when they try to sign in.

✅ PostgreSQL Database:

User data is stored in your PostgreSQL database with proper indexing and relationships. All user management operations are transactional and fully persistent across server restarts.

); }; export default UserManagement;