Skip to content

Commit 0d77eed

Browse files
committed
Feature: implement SearcherBar component with enhanced search functionality
1 parent b17fe4c commit 0d77eed

File tree

17 files changed

+213
-59
lines changed

17 files changed

+213
-59
lines changed

src/modules/SearcherBar.tsx

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/modules/search/SearcherBar.tsx

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { execute } from '@/graphql/execute';
2+
import { cn } from '@/lib/utils';
3+
import { useMutation } from '@tanstack/react-query';
4+
import { useNavigate } from '@tanstack/react-router';
5+
import { Search } from 'lucide-react';
6+
import { useState } from 'react';
7+
import { ChainLink } from '@/components/ChainLink';
8+
import { Button } from '@/components/ui/button';
9+
import { Input } from '@/components/ui/input';
10+
import useUserStore from '@/stores/useUser.store';
11+
import { getChainFromId } from '@/utils/chain.utils';
12+
import { fetchEnsAddress } from '@/utils/fetchEnsAddress';
13+
import { searchQuery } from './searchQuery';
14+
15+
export function SearcherBar({ className }: { className?: string }) {
16+
const { isConnected, address: userAddress, chainId } = useUserStore();
17+
const [inputValue, setInputValue] = useState('');
18+
const [ensResolvedAddress, setEnsResolvedAddress] = useState('');
19+
20+
const navigate = useNavigate();
21+
22+
const navigateToEntity = (
23+
data: Record<string, any>,
24+
slug: string,
25+
value: string
26+
) => {
27+
const routes = [
28+
'deal',
29+
'task',
30+
'dataset',
31+
'app',
32+
'workerpool',
33+
'account',
34+
'transaction',
35+
];
36+
for (const key of routes) {
37+
if (data[key]) {
38+
navigate({
39+
to: `/${slug}/${key === 'account' ? 'address' : key}/${value}`,
40+
});
41+
return;
42+
}
43+
}
44+
navigate({ to: '/search', search: { q: value } });
45+
// Show error message ender search bar instead
46+
};
47+
48+
const { mutate, isPending } = useMutation({
49+
mutationFn: async () =>
50+
execute(searchQuery, chainId, {
51+
search: inputValue.trim().toLowerCase(),
52+
}),
53+
onSuccess: (data) => {
54+
const value = inputValue.trim();
55+
if (!value) return;
56+
const chainSlug = getChainFromId(chainId)?.slug;
57+
if (!chainSlug) return;
58+
navigateToEntity(data, chainSlug, value);
59+
},
60+
onError: (err) => {
61+
console.error('Search error:', err);
62+
navigate({ to: '/search', search: { q: inputValue.trim() } });
63+
// Show error message ender search bar instead
64+
},
65+
});
66+
67+
const handleSearch = async () => {
68+
const rawValue = inputValue.trim().toLowerCase();
69+
if (!rawValue) return;
70+
71+
const isEnsName = rawValue.endsWith('.eth');
72+
73+
if (isEnsName) {
74+
try {
75+
const { data: address } = await fetchEnsAddress({
76+
name: rawValue,
77+
chainId,
78+
});
79+
if (address) {
80+
setEnsResolvedAddress(address);
81+
navigate({
82+
to: `/${getChainFromId(chainId)?.slug}/address/${address}`,
83+
});
84+
} else {
85+
// ENS non résolu : fallback vers page de recherche
86+
navigate({ to: `/search`, search: { q: rawValue } });
87+
}
88+
} catch (err) {
89+
console.error('ENS resolution failed:', err);
90+
navigate({ to: `/search`, search: { q: rawValue } });
91+
}
92+
} else {
93+
mutate();
94+
}
95+
};
96+
97+
const handleKeyDown = (e: React.KeyboardEvent) => {
98+
if (e.key === 'Enter') handleSearch();
99+
};
100+
101+
return (
102+
<div className={cn('m-auto w-full', className)}>
103+
<div className="relative w-full">
104+
<Input
105+
value={inputValue}
106+
onChange={(e) => setInputValue(e.target.value)}
107+
onKeyDown={handleKeyDown}
108+
disabled={isPending}
109+
className={cn(
110+
'bg-input border-secondary w-full rounded-2xl py-5.5 pl-12 sm:py-6.5',
111+
isConnected && 'sm:pr-32'
112+
)}
113+
placeholder="Search address, deal id, task id, transaction hash..."
114+
/>
115+
<Search
116+
size="18"
117+
className="pointer-events-none absolute top-1/2 left-4 -translate-y-1/2 sm:left-6"
118+
/>
119+
{isConnected && (
120+
<Button
121+
variant="outline"
122+
className="bg-input hover:bg-secondary absolute top-1/2 right-4 hidden -translate-y-1/2 sm:flex"
123+
asChild
124+
>
125+
<ChainLink to={`/address/${userAddress}`}>My activity</ChainLink>
126+
</Button>
127+
)}
128+
</div>
129+
130+
<div className="mt-3 flex justify-center sm:hidden">
131+
<Button variant="outline" onClick={handleSearch} disabled={isPending}>
132+
{isPending ? 'Searching...' : 'Search'}
133+
</Button>
134+
</div>
135+
136+
{isConnected && (
137+
<Button
138+
variant="outline"
139+
className="mx-auto mt-4 flex w-fit sm:hidden"
140+
asChild
141+
>
142+
<ChainLink to={`/address/${userAddress}`}>My activity</ChainLink>
143+
</Button>
144+
)}
145+
</div>
146+
);
147+
}

src/modules/search/searchQuery.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { graphql } from '@/graphql/gql';
2+
3+
export const searchQuery = graphql(`
4+
query Search($search: ID!) {
5+
app(id: $search) {
6+
address: id
7+
}
8+
dataset(id: $search) {
9+
address: id
10+
}
11+
workerpool(id: $search) {
12+
address: id
13+
}
14+
deal(id: $search) {
15+
dealid: id
16+
}
17+
task(id: $search) {
18+
taskid: id
19+
}
20+
account(id: $search) {
21+
address: id
22+
}
23+
transaction(id: $search) {
24+
txHash: id
25+
from {
26+
address: id
27+
}
28+
to {
29+
address: id
30+
}
31+
gasLimit
32+
gasUsed
33+
gasPrice
34+
}
35+
}
36+
`);

src/routes/$chainSlug/_layout/address/$addressAddress.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { Box, LoaderCircle } from 'lucide-react';
66
import { useState } from 'react';
77
import { DetailsTable } from '@/modules/DetailsTable';
88
import { ErrorAlert } from '@/modules/ErrorAlert';
9-
import { SearcherBar } from '@/modules/SearcherBar';
109
import { Tabs } from '@/modules/Tabs';
1110
import { AddressBreadcrumbs } from '@/modules/addresses/address/AddressBreadcrumbs';
1211
import { addressQuery } from '@/modules/addresses/address/addressQuery';
@@ -19,6 +18,7 @@ import { AddressRequestedDealsTable } from '@/modules/addresses/address/requests
1918
import { AddressRequestedTasksTable } from '@/modules/addresses/address/requests/requestedTasks/AddressRequestedTasksTable';
2019
import { AddressWorkerpoolsTable } from '@/modules/addresses/address/workerpools/AddressWorkerpoolsTable';
2120
import { AddressContributionTable } from '@/modules/addresses/address/workers/beneficiaryDeals/addressContributionTable';
21+
import { SearcherBar } from '@/modules/search/SearcherBar';
2222
import useUserStore from '@/stores/useUser.store';
2323
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
2424

src/routes/$chainSlug/_layout/app/$appAddress.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { createFileRoute } from '@tanstack/react-router';
55
import { Box, LoaderCircle } from 'lucide-react';
66
import { DetailsTable } from '@/modules/DetailsTable';
77
import { ErrorAlert } from '@/modules/ErrorAlert';
8-
import { SearcherBar } from '@/modules/SearcherBar';
98
import { AppBreadcrumbs } from '@/modules/apps/app/AppBreadcrumbs';
109
import { AppDealsTable } from '@/modules/apps/app/AppDealsTable';
1110
import { appQuery } from '@/modules/apps/app/appQuery';
1211
import { buildAppDetails } from '@/modules/apps/app/buildAppDetails';
12+
import { SearcherBar } from '@/modules/search/SearcherBar';
1313
import useUserStore from '@/stores/useUser.store';
1414
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1515

src/routes/$chainSlug/_layout/apps.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { useState } from 'react';
77
import { DataTable } from '@/components/DataTable';
88
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
99
import { ErrorAlert } from '@/modules/ErrorAlert';
10-
import { SearcherBar } from '@/modules/SearcherBar';
1110
import { appsQuery } from '@/modules/apps/appsQuery';
1211
import { columns } from '@/modules/apps/appsTable/columns';
1312
import { nextAppsQuery } from '@/modules/apps/nextAppsQuery';
13+
import { SearcherBar } from '@/modules/search/SearcherBar';
1414
import useUserStore from '@/stores/useUser.store';
1515
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1616

src/routes/$chainSlug/_layout/dataset/$datasetAddress.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { createFileRoute } from '@tanstack/react-router';
55
import { Box, LoaderCircle } from 'lucide-react';
66
import { DetailsTable } from '@/modules/DetailsTable';
77
import { ErrorAlert } from '@/modules/ErrorAlert';
8-
import { SearcherBar } from '@/modules/SearcherBar';
98
import { DatasetBreadcrumbs } from '@/modules/datasets/dataset/DatasetBreadcrumbs';
109
import { DatasetDealsTable } from '@/modules/datasets/dataset/DatasetDealsTable';
1110
import { buildDatasetDetails } from '@/modules/datasets/dataset/buildDatasetDetails';
1211
import { datasetQuery } from '@/modules/datasets/dataset/datasetQuery';
12+
import { SearcherBar } from '@/modules/search/SearcherBar';
1313
import useUserStore from '@/stores/useUser.store';
1414
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1515

src/routes/$chainSlug/_layout/datasets.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { useState } from 'react';
77
import { DataTable } from '@/components/DataTable';
88
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
99
import { ErrorAlert } from '@/modules/ErrorAlert';
10-
import { SearcherBar } from '@/modules/SearcherBar';
1110
import { datasetsQuery } from '@/modules/datasets/datasetsQuery';
1211
import { columns } from '@/modules/datasets/datasetsTable/columns';
1312
import { nextDatasetsQuery } from '@/modules/datasets/nextDatasetsQuery';
13+
import { SearcherBar } from '@/modules/search/SearcherBar';
1414
import useUserStore from '@/stores/useUser.store';
1515
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1616

src/routes/$chainSlug/_layout/deal/$dealAddress.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { Box, LoaderCircle } from 'lucide-react';
66
import { useState } from 'react';
77
import { DetailsTable } from '@/modules/DetailsTable';
88
import { ErrorAlert } from '@/modules/ErrorAlert';
9-
import { SearcherBar } from '@/modules/SearcherBar';
109
import { Tabs } from '@/modules/Tabs';
1110
import { DealBreadcrumbs } from '@/modules/deals/deal/DealBreadcrumbs';
1211
import { DealTasksTable } from '@/modules/deals/deal/DealTasksTable';
1312
import { buildDealDetails } from '@/modules/deals/deal/buildDealDetails';
1413
import { dealQuery } from '@/modules/deals/deal/dealQuery';
14+
import { SearcherBar } from '@/modules/search/SearcherBar';
1515
import useUserStore from '@/stores/useUser.store';
1616
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1717

src/routes/$chainSlug/_layout/deals.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { useState } from 'react';
77
import { DataTable } from '@/components/DataTable';
88
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
99
import { ErrorAlert } from '@/modules/ErrorAlert';
10-
import { SearcherBar } from '@/modules/SearcherBar';
1110
import { dealsQuery } from '@/modules/deals/dealsQuery';
1211
import { columns } from '@/modules/deals/dealsTable/columns';
1312
import { nextDealsQuery } from '@/modules/deals/nextDealsQuery';
13+
import { SearcherBar } from '@/modules/search/SearcherBar';
1414
import useUserStore from '@/stores/useUser.store';
1515
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
1616

0 commit comments

Comments
 (0)