Skip to content

Commit 91ae57e

Browse files
authored
Filter groups/admins via query params (#29)
* feat(explorer): filter content using query params Content can now be filtered using either the params groupid or admin re #25 * feat(explorer): filters groups using query parameters Groups and groups belonging to a specified admin can now be filtered via query parameters. Additionally, the query parameters are reflected within the input element. re #25
1 parent d1cb7e9 commit 91ae57e

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

apps/explorer/src/app/[network]/page.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import { GroupResponse, SemaphoreSubgraph } from "@semaphore-protocol/data"
44
import { SupportedNetwork } from "@semaphore-protocol/utils"
5-
import { usePathname } from "next/navigation"
6-
import { useCallback, useEffect, useState } from "react"
5+
import { usePathname, useSearchParams } from "next/navigation"
6+
import { useCallback, useEffect, useState, useMemo } from "react"
77
import SearchBar from "@/components/SearchBar"
88

99
export default function Network() {
@@ -12,9 +12,13 @@ export default function Network() {
1212

1313
const [allGroups, setAllGroups] = useState<GroupResponse[]>([])
1414
const [filteredGroups, setFilteredGroups] = useState<GroupResponse[]>([])
15-
1615
const [loading, setLoading] = useState(false)
1716

17+
const searchParams = useSearchParams()
18+
const adminParam = useMemo(() => new URLSearchParams(searchParams).get("admin"), [searchParams.toString()])
19+
const groupIdParam = useMemo(() => new URLSearchParams(searchParams).get("groupid"), [searchParams.toString()])
20+
const queryParam = adminParam || groupIdParam
21+
1822
useEffect(() => {
1923
const fetchData = async () => {
2024
setLoading(true)
@@ -40,24 +44,34 @@ export default function Network() {
4044
let groups: GroupResponse[]
4145
if (groupIdOrAdmin.startsWith("0x")) {
4246
groupIdOrAdmin = groupIdOrAdmin.toLowerCase()
43-
groups = allGroups.filter((group) => (!groupIdOrAdmin ? true : group.admin?.includes(groupIdOrAdmin)))
47+
groups = allGroups.filter((group) => group.admin?.includes(groupIdOrAdmin))
4448
} else {
45-
groups = allGroups.filter((group) => (!groupIdOrAdmin ? true : group.id.includes(groupIdOrAdmin)))
49+
groups = allGroups.filter(
50+
(group) => group.id.includes(groupIdOrAdmin) || group.admin === groupIdOrAdmin
51+
)
4652
}
47-
4853
setFilteredGroups(groups)
4954
},
5055
[allGroups]
5156
)
5257

58+
useEffect(() => {
59+
filterGroups(adminParam || groupIdParam || "")
60+
}, [adminParam, groupIdParam, filterGroups])
61+
5362
return loading ? (
5463
<div className="flex justify-center items-center h-screen">
5564
<div className="loader" />
5665
</div>
5766
) : (
5867
allGroups && (
5968
<div className="mx-auto max-w-7xl px-4 lg:px-8 pt-20">
60-
<SearchBar className="mb-6" placeholder="Group ID, Admin" onChange={filterGroups} />
69+
<SearchBar
70+
className="mb-6"
71+
placeholder="Group ID, Admin"
72+
onChange={filterGroups}
73+
queryParam={queryParam}
74+
/>
6175

6276
<div className="flex justify-center flex-col pb-10 font-[family-name:var(--font-geist-sans)]">
6377
<ul className="divide-y divide-gray-300 min-w-xl">

apps/explorer/src/components/SearchBar.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
"use client"
22

33
import { FaSearch } from "react-icons/fa"
4+
import { useState, useEffect, ChangeEvent } from "react"
5+
6+
export default function SearchBar({ placeholder, onChange, className, queryParam }: any) {
7+
const [searchQuery, setSearchQuery] = useState("")
8+
useEffect(() => {
9+
if (queryParam) {
10+
setSearchQuery(queryParam)
11+
}
12+
}, [queryParam])
13+
14+
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
15+
const { value } = event.target
16+
setSearchQuery(value)
17+
onChange(value)
18+
}
419

5-
export default function SearchBar({ placeholder, onChange, className }: any) {
620
return (
721
<div className={`relative mt-2 rounded-md shadow-sm ${className}`}>
822
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
923
<FaSearch className="text-gray-600" />
1024
</div>
1125
<input
12-
onChange={(event) => onChange(event.target.value)}
26+
onChange={handleInputChange}
1327
name="search-bar"
1428
type="text"
1529
placeholder={placeholder}
1630
className="block w-full rounded-md border-0 py-1.5 pl-9 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none text-sm sm:leading-6"
31+
value={searchQuery}
1732
/>
1833
</div>
1934
)

0 commit comments

Comments
 (0)