diff --git a/frontend/src/components/pages/AdminPage.js b/frontend/src/components/pages/AdminPage.js index da85787..f79a10d 100644 --- a/frontend/src/components/pages/AdminPage.js +++ b/frontend/src/components/pages/AdminPage.js @@ -117,6 +117,10 @@ function UserManagementPanel() { const [formError, setFormError] = useState(''); const [successMessage, setSuccessMessage] = useState(''); const [pendingConfirm, setPendingConfirm] = useState(null); + const [searchTerm, setSearchTerm] = useState(''); + const [groupFilter, setGroupFilter] = useState(''); + const [sortField, setSortField] = useState('username'); + const [sortDir, setSortDir] = useState('asc'); const fetchUsers = useCallback(async () => { setLoading(true); @@ -148,6 +152,43 @@ function UserManagementPanel() { } }, [successMessage]); + // Filtered and sorted user list + const filteredUsers = users + .filter(u => { + if (searchTerm) { + const term = searchTerm.toLowerCase(); + const matchesName = u.username?.toLowerCase().includes(term); + const matchesEmail = u.email?.toLowerCase().includes(term); + const matchesTeam = (u.teams || []).some(t => t.toLowerCase().includes(term)); + if (!matchesName && !matchesEmail && !matchesTeam) return false; + } + if (groupFilter === 'no-teams') return !u.teams || u.teams.length === 0; + if (groupFilter && u.group !== groupFilter) return false; + return true; + }) + .sort((a, b) => { + let aVal, bVal; + switch (sortField) { + case 'username': aVal = a.username || ''; bVal = b.username || ''; break; + case 'email': aVal = a.email || ''; bVal = b.email || ''; break; + case 'group': aVal = a.group || ''; bVal = b.group || ''; break; + case 'active': aVal = a.is_active ? 'a' : 'z'; bVal = b.is_active ? 'a' : 'z'; break; + case 'last_login': aVal = a.last_login || ''; bVal = b.last_login || ''; break; + default: aVal = a.username || ''; bVal = b.username || ''; + } + const cmp = String(aVal).localeCompare(String(bVal)); + return sortDir === 'asc' ? cmp : -cmp; + }); + + const handleSort = (field) => { + if (sortField === field) { + setSortDir(d => d === 'asc' ? 'desc' : 'asc'); + } else { + setSortField(field); + setSortDir('asc'); + } + }; + const handleAddClick = () => { setEditingUser(null); setFormData({ username: '', email: '', password: '', group: 'Read_Only' }); @@ -433,6 +474,48 @@ function UserManagementPanel() { {/* User table */} {!loading && !error && ( +