import React, { useState, useEffect } from 'react'
import api from '../api.js'
import { useAuth } from '../AuthContext.jsx'
import { Plus, Trash2, Edit2, X, Check, Users, Shield, User, KeyRound } from 'lucide-react'
function UserModal({ user, onClose, onSave }) {
const [form, setForm] = useState({
username: user?.username || '',
password: '',
role: user?.role || 'user',
})
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const handleSubmit = async (e) => {
e.preventDefault()
setError('')
setLoading(true)
try {
if (user) {
const payload = { role: form.role }
if (form.username !== user.username) payload.username = form.username
if (form.password) payload.password = form.password
const { data } = await api.put(`/users/${user.id}`, payload)
onSave(data, 'edit')
} else {
if (!form.password) return setError('Password is required')
const { data } = await api.post('/users', form)
onSave(data, 'add')
}
onClose()
} catch (err) {
setError(err.response?.data?.error || 'Failed to save user')
} finally {
setLoading(false)
}
}
return (
{user ? 'Edit User' : 'New User'}
)
}
export default function Admin() {
const { user: currentUser } = useAuth()
const [users, setUsers] = useState([])
const [loading, setLoading] = useState(true)
const [modal, setModal] = useState(null)
const [deleteConfirm, setDeleteConfirm] = useState(null)
const [toast, setToast] = useState('')
useEffect(() => {
api.get('/users').then(({ data }) => { setUsers(data); setLoading(false) }).catch(() => setLoading(false))
}, [])
const showToast = (msg) => { setToast(msg); setTimeout(() => setToast(''), 3000) }
const handleSave = (data, type) => {
if (type === 'add') setUsers(prev => [data, ...prev])
else setUsers(prev => prev.map(u => u.id === data.id ? data : u))
showToast(type === 'add' ? 'User created' : 'User updated')
}
const handleDelete = async (id) => {
try {
await api.delete(`/users/${id}`)
setUsers(prev => prev.filter(u => u.id !== id))
setDeleteConfirm(null)
showToast('User deleted')
} catch (err) {
showToast(err.response?.data?.error || 'Failed to delete')
}
}
const adminCount = users.filter(u => u.role === 'admin').length
const userCount = users.filter(u => u.role === 'user').length
return (
{toast && (
{toast}
)}
Admin Panel
Manage user accounts and permissions
{/* Stats */}
{[
{ label: 'Total Users', value: users.length, icon: Users, color: 'indigo' },
{ label: 'Admins', value: adminCount, icon: Shield, color: 'amber' },
{ label: 'Regular Users', value: userCount, icon: User, color: 'blue' },
].map(({ label, value, icon: Icon, color }) => (
))}
{/* Users table */}
{loading ? (
Loading...
) : (
| Username |
Role |
MFA |
Status |
Created |
Actions |
{users.map(u => (
{u.role === 'admin' ? : }
{u.username}
{u.id === currentUser.id && (you)}
|
{u.role}
|
{u.mfa_enabled ? 'Enabled' : 'Disabled'}
|
{u.must_change_password ? (
Must change pw
) : (
Active
)}
|
{new Date(u.created_at).toLocaleDateString()} |
{u.id !== currentUser.id && (
)}
|
))}
)}
{modal && (
setModal(null)}
onSave={handleSave}
/>
)}
{deleteConfirm && (
Delete User
Delete {deleteConfirm.username}? This cannot be undone.
)}
)
}