diff --git a/apps/hyperdrive-trading/src/ui/landing/Landing.tsx b/apps/hyperdrive-trading/src/ui/landing/Landing.tsx index efe377da8..4e4ed6c8a 100644 --- a/apps/hyperdrive-trading/src/ui/landing/Landing.tsx +++ b/apps/hyperdrive-trading/src/ui/landing/Landing.tsx @@ -7,22 +7,7 @@ export function Landing(): ReactElement | null {
-
- {/* TODO: Implement filter buttons -
- - - -
*/} +
diff --git a/apps/hyperdrive-trading/src/ui/markets/PoolsList.tsx b/apps/hyperdrive-trading/src/ui/markets/PoolsList.tsx index 28c010272..2e1e53abc 100644 --- a/apps/hyperdrive-trading/src/ui/markets/PoolsList.tsx +++ b/apps/hyperdrive-trading/src/ui/markets/PoolsList.tsx @@ -11,8 +11,9 @@ import { BarsArrowDownIcon, } from "@heroicons/react/20/solid"; import { QueryStatus, useQuery } from "@tanstack/react-query"; +import { useNavigate, useSearch } from "@tanstack/react-router"; import { getPublicClient } from "@wagmi/core"; -import { ReactElement, ReactNode, useMemo, useRef, useState } from "react"; +import { ReactElement, ReactNode, useMemo, useState } from "react"; import { ZERO_ADDRESS } from "src/base/constants"; import { isTestnetChain } from "src/chains/isTestnetChain"; import { calculateMarketYieldMultiplier } from "src/hyperdrive/calculateMarketYieldMultiplier"; @@ -25,6 +26,7 @@ import LoadingState from "src/ui/base/components/LoadingState"; import { MultiSelect } from "src/ui/base/components/MultiSelect"; import { NonIdealState } from "src/ui/base/components/NonIdealState"; import { Well } from "src/ui/base/components/Well/Well"; +import { LANDING_ROUTE } from "src/ui/landing/routes"; import { PoolRow, PoolRowProps } from "src/ui/markets/PoolRow"; import { PublicClient } from "viem"; import { useChainId } from "wagmi"; @@ -41,6 +43,10 @@ type SortOption = (typeof sortOptions)[number]; export function PoolsList(): ReactElement { const { pools: allPools, status } = usePoolsList(); + const { chains: selectedChains, assets: selectedAssets } = useSearch({ + from: LANDING_ROUTE, + }); + const navigate = useNavigate({ from: LANDING_ROUTE }); const [sort, setSort] = useState("TVL"); // Sync filters with pools @@ -88,21 +94,18 @@ export function PoolsList(): ReactElement { }; }, [allPools]); - const [selectedChains, setSelectedChains] = useState([]); - const [selectedAssets, setSelectedAssets] = useState([]); - // Filter and sort pools const selectedPools = allPools ?.filter((pool) => { if ( - selectedChains.length && + selectedChains?.length && !selectedChains.includes(pool.hyperdrive.chainId) ) { return false; } if ( - selectedAssets.length && + selectedAssets?.length && !pool.depositAssets.some(({ symbol }) => selectedAssets.includes(symbol), ) @@ -136,14 +139,8 @@ export function PoolsList(): ReactElement { } }); - // To prevent jarring layout shifts when no pools match the selected filters, - // the NonIdealState is wrapped in a div with a width set to match the outer - // container's width, which will be the width it rendered at before the - // filter's were changed. - const containerRef = useRef(null); - return ( -
+
{status === "loading" && !selectedPools ? ( ) : selectedPools ? ( @@ -157,13 +154,22 @@ export function PoolsList(): ReactElement { {filters && filters.chains.length > 1 && ( + navigate({ + search: (current) => { + return { + ...current, + chains, + }; + }, + }) + } displayValue={ - selectedChains.length === 1 + selectedChains?.length === 1 ? appConfig.chains[selectedChains[0]].name : `${ - selectedChains.length || filters?.chains.length + selectedChains?.length || filters?.chains.length } chains` } searchEnabled @@ -185,13 +191,22 @@ export function PoolsList(): ReactElement { {filters && filters.assets.length > 1 && ( + navigate({ + search: (current) => { + return { + ...current, + assets, + }; + }, + }) + } displayValue={ - selectedAssets.length === 1 + selectedAssets?.length === 1 ? selectedAssets[0] : `${ - selectedAssets.length || filters.assets.length + selectedAssets?.length || filters.assets.length } assets` } searchEnabled @@ -248,12 +263,7 @@ export function PoolsList(): ReactElement {
{!selectedPools.length ? ( - + {allPools?.length ? ( ( @@ -9,4 +10,8 @@ export const Route = createFileRoute(LANDING_ROUTE)({ ), + validateSearch: z.object({ + chains: z.array(z.number()).optional(), + assets: z.array(z.string()).optional(), + }), });