Skip to content

Commit 2d949d1

Browse files
gregfromstlClaude
and
Claude
committed
fix: update routes page to use server-side pagination and filtering
- Updated getRoutes to use server-side parameters for filtering and pagination - Modified routes-table to work with API pagination response format - Changed search placeholder text to be more specific 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 23029db commit 2d949d1

File tree

3 files changed

+61
-81
lines changed

3 files changed

+61
-81
lines changed

apps/dashboard/src/app/(app)/(dashboard)/(bridge)/routes/components/client/search.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const SearchInput: React.FC = () => {
4747
<div className="group relative w-full">
4848
<SearchIcon className="-translate-y-1/2 absolute top-[50%] left-3 size-4 text-muted-foreground" />
4949
<Input
50-
placeholder="Search with anything!"
50+
placeholder="Search by token name or symbol"
5151
className="h-10 rounded-lg bg-card py-2 pl-9 lg:min-w-[300px]"
5252
defaultValue={searchParams?.get("query") || ""}
5353
onChange={(e) => handleSearch(e.target.value)}

apps/dashboard/src/app/(app)/(dashboard)/(bridge)/routes/components/server/routes-table.tsx

Lines changed: 15 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
TableRow,
88
} from "@/components/ui/table";
99
import type { Address } from "thirdweb";
10-
import { checksumAddress } from "thirdweb/utils";
1110
import { getRoutes } from "../../../utils";
1211
import { ChainlistPagination } from "../client/pagination";
1312
import { RouteListCard } from "./routelist-card";
@@ -25,18 +24,15 @@ export type SearchParams = Partial<{
2524

2625
// 120 is divisible by 2, 3, and 4 so card layout looks nice
2726
const DEFAULT_PAGE_SIZE = 120;
28-
const DEFAULT_PAGE = 1;
2927

3028
async function getRoutesToRender(params: SearchParams) {
3129
const filters: Partial<{
32-
limit: number;
33-
offset: number;
30+
originQuery?: string;
31+
destinationQuery?: string;
3432
originChainId?: number;
3533
originTokenAddress?: Address;
3634
destinationChainId?: number;
3735
destinationTokenAddress?: Address;
38-
originTextQuery?: string;
39-
destinationTextQuery?: string;
4036
}> = {};
4137

4238
if (params.type === "origin" || typeof params.type === "undefined") {
@@ -45,77 +41,28 @@ async function getRoutesToRender(params: SearchParams) {
4541
} else if (Number.isInteger(Number(params.query))) {
4642
filters.originChainId = Number(params.query);
4743
} else if (params.query) {
48-
filters.originTextQuery = params.query;
44+
filters.originQuery = params.query;
4945
}
5046
} else if (params.type === "destination") {
5147
if (params.query?.startsWith("0x")) {
5248
filters.destinationTokenAddress = params.query as Address;
5349
} else if (Number.isInteger(Number(params.query))) {
5450
filters.destinationChainId = Number(params.query);
5551
} else if (params.query) {
56-
filters.destinationTextQuery = params.query;
52+
filters.destinationQuery = params.query;
5753
}
5854
}
59-
// Temporary, will update this after the /routes endpoint
60-
let routes = await getRoutes({ limit: 500_000 });
61-
62-
const totalCount = routes.length;
63-
64-
if (filters.originChainId) {
65-
routes = routes.filter(
66-
(route) => route.originToken.chainId === filters.originChainId,
67-
);
68-
}
69-
if (filters.originTokenAddress) {
70-
const originTokenAddress = filters.originTokenAddress;
71-
routes = routes.filter(
72-
(route) =>
73-
checksumAddress(route.originToken.address) ===
74-
checksumAddress(originTokenAddress),
75-
);
76-
}
77-
if (filters.destinationChainId) {
78-
routes = routes.filter(
79-
(route) => route.destinationToken.chainId === filters.destinationChainId,
80-
);
81-
}
82-
if (filters.destinationTokenAddress) {
83-
const destinationTokenAddress = filters.destinationTokenAddress;
84-
routes = routes.filter(
85-
(route) =>
86-
checksumAddress(route.destinationToken.address) ===
87-
checksumAddress(destinationTokenAddress),
88-
);
89-
}
90-
91-
if (filters.originTextQuery) {
92-
const originTextQuery = filters.originTextQuery.toLowerCase();
93-
routes = routes.filter((route) => {
94-
return (
95-
route.originToken.name.toLowerCase().includes(originTextQuery) ||
96-
route.originToken.symbol.toLowerCase().includes(originTextQuery)
97-
);
98-
});
99-
}
100-
101-
if (filters.destinationTextQuery) {
102-
const destinationTextQuery = filters.destinationTextQuery.toLowerCase();
103-
routes = routes.filter((route) => {
104-
return (
105-
route.destinationToken.name
106-
.toLowerCase()
107-
.includes(destinationTextQuery) ||
108-
route.destinationToken.symbol
109-
.toLowerCase()
110-
.includes(destinationTextQuery)
111-
);
112-
});
113-
}
55+
const routes = await getRoutes({
56+
limit: DEFAULT_PAGE_SIZE,
57+
offset: DEFAULT_PAGE_SIZE * ((params.page || 1) - 1),
58+
originQuery: filters.originQuery,
59+
destinationQuery: filters.destinationQuery,
60+
});
11461

11562
return {
116-
routesToRender: routes,
117-
totalCount,
118-
filteredCount: routes.length,
63+
routesToRender: routes.data,
64+
totalCount: routes.meta.totalCount,
65+
filteredCount: routes.meta.filteredCount,
11966
};
12067
}
12168

@@ -128,10 +75,9 @@ export async function RoutesData(props: {
12875
props.searchParams,
12976
);
13077

131-
// pagination
132-
const totalPages = Math.ceil(routesToRender.length / DEFAULT_PAGE_SIZE);
78+
const totalPages = Math.ceil(filteredCount / DEFAULT_PAGE_SIZE);
13379

134-
const activePage = Number(props.searchParams.page || DEFAULT_PAGE);
80+
const activePage = Number(props.searchParams.page || 1);
13581
const pageSize = DEFAULT_PAGE_SIZE;
13682
const startIndex = (activePage - 1) * pageSize;
13783
const endIndex = startIndex + pageSize;

apps/dashboard/src/app/(app)/(dashboard)/(bridge)/utils.ts

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,69 @@ import "server-only";
22

33
import { NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST } from "@/constants/public-envs";
44
import { DASHBOARD_THIRDWEB_SECRET_KEY } from "@/constants/server-envs";
5-
import { getAuthToken } from "app/(app)/api/lib/getAuthToken";
5+
import type { Address } from "thirdweb";
66
import type { Route } from "./types/route";
77

88
export async function getRoutes({
99
limit,
10+
offset,
11+
originQuery,
12+
destinationQuery,
13+
originChainId,
14+
destinationChainId,
15+
originTokenAddress,
16+
destinationTokenAddress,
1017
}: {
1118
limit?: number;
19+
offset?: number;
20+
originQuery?: string;
21+
destinationQuery?: string;
22+
originChainId?: number;
23+
destinationChainId?: number;
24+
originTokenAddress?: Address;
25+
destinationTokenAddress?: Address;
1226
} = {}) {
1327
const url = new URL(`${NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST}/v1/routes`);
1428
if (limit) {
1529
url.searchParams.set("limit", limit.toString());
1630
}
31+
if (offset) {
32+
url.searchParams.set("offset", offset.toString());
33+
}
34+
if (originQuery) {
35+
url.searchParams.set("originQuery", originQuery);
36+
}
37+
if (destinationQuery) {
38+
url.searchParams.set("destinationQuery", destinationQuery);
39+
}
40+
if (originChainId) {
41+
url.searchParams.set("originChainId", originChainId.toString());
42+
}
43+
if (destinationChainId) {
44+
url.searchParams.set("destinationChainId", destinationChainId.toString());
45+
}
46+
if (originTokenAddress) {
47+
url.searchParams.set("originTokenAddress", originTokenAddress);
48+
}
49+
if (destinationTokenAddress) {
50+
url.searchParams.set("destinationTokenAddress", destinationTokenAddress);
51+
}
52+
url.searchParams.set("sortBy", "popularity");
1753
// It's faster to filter client side, doesn't seem to be a big performance boost to paginate/filter server side
18-
const token = await getAuthToken();
1954
const routesResponse = await fetch(url, {
20-
headers: token
21-
? {
22-
authorization: `Bearer ${token}`,
23-
}
24-
: {
25-
"x-secret-key": DASHBOARD_THIRDWEB_SECRET_KEY,
26-
},
55+
headers: {
56+
"x-secret-key": DASHBOARD_THIRDWEB_SECRET_KEY,
57+
},
2758
next: { revalidate: 60 * 60 },
2859
});
2960

3061
if (!routesResponse.ok) {
3162
throw new Error("Failed to fetch routes");
3263
}
33-
const routes: { data: Route[] } = await routesResponse.json();
64+
const routes: {
65+
data: Route[];
66+
meta: { totalCount: number; filteredCount: number };
67+
} = await routesResponse.json();
3468

35-
return routes.data;
69+
return routes;
3670
}

0 commit comments

Comments
 (0)