Skip to content

Commit 9cf60f3

Browse files
feat: search and filter
1 parent e1908e3 commit 9cf60f3

1 file changed

Lines changed: 47 additions & 6 deletions

File tree

src/pages/UserManagement.tsx

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ const UserManagement = () => {
2626
const updateUserRole = useUpdateUserRole();
2727
const bulkAssign = useBulkAssignDevices();
2828
const bulkUnassign = useBulkUnassignDevices();
29+
const removeUser = useDeleteUser();
2930

31+
// User Filtering State
32+
const [userSearch, setUserSearch] = useState("");
33+
const [roleFilter, setRoleFilter] = useState<'all' | 'viewer' | 'editor'>('all');
34+
3035
// New User Form State
3136
const [email, setEmail] = useState("");
3237
const [password, setPassword] = useState("");
@@ -37,6 +42,12 @@ const UserManagement = () => {
3742

3843
const isBulkOperating = bulkAssign.isPending || bulkUnassign.isPending;
3944

45+
const filteredUsers = users.filter(user => {
46+
const matchesSearch = user.email.toLowerCase().includes(userSearch.toLowerCase());
47+
const matchesRole = roleFilter === 'all' || user.role === roleFilter;
48+
return matchesSearch && matchesRole;
49+
});
50+
4051
const filteredDevices = allDevices.filter(d =>
4152
d.title.toLowerCase().includes(deviceSearch.toLowerCase()) ||
4253
d.id.toLowerCase().includes(deviceSearch.toLowerCase())
@@ -170,9 +181,35 @@ const UserManagement = () => {
170181
{/* ── Users List & Access Control ── */}
171182
<Card className="lg:col-span-2">
172183
<CardHeader>
173-
<CardTitle className="flex items-center gap-2">
174-
<Users className="h-5 w-5" />
175-
User Directory & Access
184+
<CardTitle className="flex items-center justify-between gap-2">
185+
<div className="flex items-center gap-2">
186+
<Users className="h-5 w-5" />
187+
User Directory & Access
188+
</div>
189+
<div className="flex items-center gap-2">
190+
<div className="relative">
191+
<Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
192+
<Input
193+
placeholder="Search users..."
194+
className="h-8 pl-8 text-xs w-[150px] lg:w-[200px]"
195+
value={userSearch}
196+
onChange={(e) => setUserSearch(e.target.value)}
197+
/>
198+
</div>
199+
<Select
200+
value={roleFilter}
201+
onValueChange={(val: 'all' | 'viewer' | 'editor') => setRoleFilter(val)}
202+
>
203+
<SelectTrigger className="h-8 w-[110px] text-xs">
204+
<SelectValue placeholder="Role" />
205+
</SelectTrigger>
206+
<SelectContent>
207+
<SelectItem value="all">All Roles</SelectItem>
208+
<SelectItem value="viewer">Viewer</SelectItem>
209+
<SelectItem value="editor">Editor</SelectItem>
210+
</SelectContent>
211+
</Select>
212+
</div>
176213
</CardTitle>
177214
<CardDescription>
178215
Assign specific devices to allow non-admin users to view them.
@@ -183,13 +220,17 @@ const UserManagement = () => {
183220
<div className="flex justify-center p-8">
184221
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
185222
</div>
186-
) : users.length === 0 ? (
223+
) : filteredUsers.length === 0 ? (
187224
<div className="text-center p-8 border rounded-lg bg-muted/20">
188-
<p className="text-muted-foreground">No users found.</p>
225+
<p className="text-muted-foreground">
226+
{userSearch || roleFilter !== 'all'
227+
? "No users found matching the criteria."
228+
: "No users found."}
229+
</p>
189230
</div>
190231
) : (
191232
<div className="space-y-4">
192-
{users.map((user) => (
233+
{filteredUsers.map((user) => (
193234
<div key={user.id} className="border rounded-lg p-4 bg-card shadow-sm">
194235
<div className="flex items-start justify-between mb-4">
195236
<div>

0 commit comments

Comments
 (0)