MCPcopy Create free account
hub / github.com/FrodeHus/EntraRoleReaper / SearchUsers

Function SearchUsers

web/src/app/SearchUsers.tsx:13–173  ·  view source on GitHub ↗
({
  accessToken,
  selected,
  onChange,
}: {
  accessToken: string | null;
  selected: DirectoryItem[];
  onChange: (v: DirectoryItem[]) => void;
})

Source from the content-addressed store, hash-verified

11};
12
13export function SearchUsers({
14 accessToken,
15 selected,
16 onChange,
17}: {
18 accessToken: string | null;
19 selected: DirectoryItem[];
20 onChange: (v: DirectoryItem[]) => void;
21}) {
22 const [q, setQ] = useState("");
23 const [debouncedQ, setDebouncedQ] = useState("");
24 const [includeGroups, setIncludeGroups] = useState(true);
25 const [results, setResults] = useState<DirectoryItem[]>([]);
26 const [loading, setLoading] = useState(false);
27
28 // Debounce the query to avoid excessive API calls while typing
29 useEffect(() => {
30 const handle = setTimeout(() => setDebouncedQ(q), 300);
31 return () => clearTimeout(handle);
32 }, [q]);
33
34 useEffect(() => {
35 const ctrl = new AbortController();
36 let canceled = false;
37 const run = async () => {
38 if (!accessToken || debouncedQ.trim().length < 2) {
39 setResults([]);
40 return;
41 }
42 const url = new URL("/api/search", import.meta.env.VITE_API_URL);
43 url.searchParams.set("q", debouncedQ);
44 url.searchParams.set("includeGroups", String(includeGroups));
45 try {
46 setLoading(true);
47 const res = await fetch(url, {
48 headers: { Authorization: `Bearer ${accessToken}` },
49 signal: ctrl.signal,
50 });
51 if (!res.ok) return;
52 const data = await res.json();
53 if (!canceled) setResults(data);
54 } finally {
55 if (!canceled) setLoading(false);
56 }
57 };
58 run();
59 return () => {
60 canceled = true;
61 ctrl.abort();
62 };
63 }, [debouncedQ, includeGroups, accessToken]);
64
65 const add = (item: DirectoryItem) => {
66 if (selected.some((s) => s.id === item.id && s.type === item.type)) return;
67 onChange([...selected, item]);
68 };
69 const remove = (id: string, type: "user" | "group") =>
70 onChange(selected.filter((s) => !(s.id === id && s.type === type)));

Callers

nothing calls this directly

Calls 4

isSelectedFunction · 0.85
removeFunction · 0.85
addFunction · 0.85
runFunction · 0.70

Tested by

no test coverage detected