Skip to content

Commit

Permalink
add search to market
Browse files Browse the repository at this point in the history
  • Loading branch information
vidvidvid committed Nov 28, 2024
1 parent 9e65f29 commit 9ee78ff
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 13 deletions.
1 change: 1 addition & 0 deletions packages/ui/app/_components/CommonTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ function CommonTable<T extends object>({
<ResultHandler
isLoading={isLoading}
center
height={80}
>
<Table className="w-full border-separate border-spacing-y-3">
<TableHeader>
Expand Down
81 changes: 81 additions & 0 deletions packages/ui/app/_components/markets/MarketSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useCallback, useEffect, useState } from 'react';

import { Search } from 'lucide-react';
import { isAddress } from 'viem';

import { Input } from '@ui/components/ui/input';
import type { MarketRowData } from '@ui/hooks/market/useMarketData';

const useDebounce = <T,>(value: T, delay: number = 300): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value);

useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);

return () => {
clearTimeout(handler);
};
}, [value, delay]);

return debouncedValue;
};

interface MarketSearchProps {
data: MarketRowData[];
onSearch: (filtered: MarketRowData[]) => void;
}

const MarketSearch = ({ data, onSearch }: MarketSearchProps) => {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm);

const filterMarkets = useCallback(
(term: string) => {
if (!term.trim()) {
onSearch(data);
return;
}

const lowercaseSearch = term.toLowerCase();
const isAddressSearch = isAddress(term);

const filtered = data.filter((market) => {
if (isAddressSearch) {
return (
market.cTokenAddress.toLowerCase() === lowercaseSearch ||
market.underlyingToken.toLowerCase() === lowercaseSearch
);
}

return (
market.asset.toLowerCase().includes(lowercaseSearch) ||
market.underlyingSymbol.toLowerCase().includes(lowercaseSearch)
);
});

onSearch(filtered);
},
[data, onSearch]
);

useEffect(() => {
filterMarkets(debouncedSearchTerm);
}, [debouncedSearchTerm, filterMarkets]);

return (
<div className="relative w-96">
<div className="absolute inset-y-0 left-3 flex items-center pointer-events-none">
<Search className="h-4 w-4 text-white/40" />
</div>
<Input
placeholder="Search by token or address..."
onChange={(e) => setSearchTerm(e.target.value)}
className="h-9 pl-10 pr-4 rounded-lg text-sm border-white/5 hover:border-white/10 focus-visible:ring-1 focus-visible:ring-accent/50 focus-visible:border-accent transition-colors placeholder:text-white/30"
/>
</div>
);
};

export default MarketSearch;
10 changes: 4 additions & 6 deletions packages/ui/app/_components/markets/PoolToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ import { pools } from '@ui/constants/index';
const PoolToggle = ({ chain, pool }: { chain: number; pool: string }) => {
const pathname = usePathname();
return (
<div
className={`flex items-center justify-start w-max gap-2 sm:mx-0 mx-auto p-2`}
>
<div className={`flex items-center justify-start w-max gap-2 sm:mx-0`}>
{pools[+chain].pools.map((poolx, idx) => {
return (
<Link
className={` cursor-pointer px-4 rounded-md ${
className={`cursor-pointer text-sm px-4 py-1 rounded-md transition-colors ${
pool === poolx.id
? ` ${pools[+chain].bg} ${pools[+chain].text}`
: 'bg-black '
? `${pools[+chain].bg} ${pools[+chain].text}`
: 'bg-darktwo border border-white/10 hover:border-white/20'
}`}
href={`${pathname}?chain=${chain}${
poolx.id ? `&pool=${poolx.id}` : ''
Expand Down
29 changes: 22 additions & 7 deletions packages/ui/app/market/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useState } from 'react';
import { useEffect, useState } from 'react';

import dynamic from 'next/dynamic';
import Image from 'next/image';
Expand All @@ -21,6 +21,7 @@ import ManageDialog from '../_components/dialogs/manage';
import Swap from '../_components/dialogs/manage/Swap';
import APRCell from '../_components/markets/APRCell';
import FeaturedMarketTile from '../_components/markets/FeaturedMarketTile';
import MarketSearch from '../_components/markets/MarketSearch';
import StakingTile from '../_components/markets/StakingTile';
import TotalTvlTile from '../_components/markets/TotalTvlTile';
import TvlTile from '../_components/markets/TvlTile';
Expand Down Expand Up @@ -59,9 +60,15 @@ export default function Market() {
const [isLoopDialogOpen, setIsLoopDialogOpen] = useState<boolean>(false);
const [selectedSymbol, setSelectedSymbol] = useState<string>();
const [isBorrowDisabled, setIsBorrowDisabled] = useState<boolean>(false);
const [filteredMarketData, setFilteredMarketData] = useState<MarketRowData[]>(
[]
);

const { marketData, isLoading, poolData, selectedMarketData, loopProps } =
useMarketData(selectedPool, chain, selectedSymbol);
useEffect(() => {
setFilteredMarketData(marketData);
}, [marketData]);

const columns: EnhancedColumnDef<MarketRowData>[] = [
{
Expand Down Expand Up @@ -265,15 +272,23 @@ export default function Market() {
</div>

<div className="bg-grayone w-full lg:px-[1%] xl:px-[3%] rounded-xl pt-3 pb-7">
<div className="w-full flex-wrap flex justify-between items-center">
<PoolToggle
chain={+chain}
pool={selectedPool}
/>
<div className="w-full grid grid-cols-1 sm:grid-cols-3 items-center gap-4 pt-2">
<div className="w-full flex justify-center sm:justify-start">
<PoolToggle
chain={+chain}
pool={selectedPool}
/>
</div>
<div className="flex justify-center">
<MarketSearch
data={marketData}
onSearch={setFilteredMarketData}
/>
</div>
</div>

<CommonTable
data={marketData}
data={filteredMarketData}
columns={columns}
isLoading={isLoading}
/>
Expand Down

0 comments on commit 9ee78ff

Please sign in to comment.