'use client'; import { SearchIcon } from '@/components/ui/animated-icons/search'; import { Form, FormControl, FormField, FormItem } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Separator } from '@/components/ui/separator'; import { useDebounce } from '@/hooks/use-debounce'; import { useQueryKeys } from '@/hooks/use-query-keys'; import { assetConfig } from '@/lib/config/assets'; import { sanitizeSearchTerm } from '@/lib/react-query'; import { hasuraClient } from '@/lib/settlemint/hasura'; import { theGraphClientStarterkits } from '@/lib/settlemint/the-graph'; import { cn } from '@/lib/utils'; import { useQuery } from '@tanstack/react-query'; import Link from 'next/link'; import { useForm, useWatch } from 'react-hook-form'; import { type Address, getAddress, isHex } from 'viem'; import { EvmAddress } from '../evm-address/evm-address'; import { SearchAssets, SearchUsers } from './search-query'; export const Search = () => { const { keys } = useQueryKeys(); const form = useForm({ defaultValues: { search: '', }, mode: 'all', }); const search = useWatch({ control: form.control, name: 'search', }); const debounced = useDebounce(search, 250); const { data } = useQuery({ queryKey: keys.search(debounced), queryFn: async () => { if (!debounced || debounced.length < 2) { return { assets: [], users: [] }; } const sanitizedSearch = sanitizeSearchTerm(debounced); // If the sanitized search term is too short after cleaning, return empty results if (sanitizedSearch.length < 2) { return { assets: [], users: [] }; } const users = await hasuraClient.request(SearchUsers, { search: `%${sanitizedSearch}%`, }); const assets = await theGraphClientStarterkits.request(SearchAssets, { searchAddress: isHex(sanitizedSearch) ? sanitizedSearch : '', search: sanitizedSearch, }); return { assets: assets.assets, users: users.user, }; }, enabled: debounced.length >= 2, }); return (
{ e.preventDefault(); }} className={cn( 'flex items-center border border-b px-3 shadow-md focus-within:outline-none focus-within:ring-0 md:min-w-[450px]', debounced ? 'rounded-t-lg' : 'rounded-lg' )} > ( { form.setValue('search', e.target.value, { shouldDirty: true, shouldTouch: true, shouldValidate: true, }); }} /> )} /> {debounced && (
{!data || (data.assets.length === 0 && data.users.length === 0 && (

No results found

))} {data && data.assets.length > 0 && ( <>
Assets
{data.assets.map((asset) => (
{ form.setValue('search', '', { shouldDirty: true, shouldTouch: true, shouldValidate: true, }); }} >
))} )} {data && data.assets.length > 0 && data.users.length > 0 && } {data && data.users.length > 0 && ( <>
Users
{data.users.map((user) => (
{ form.setValue('search', '', { shouldDirty: true, shouldTouch: true, shouldValidate: true, }); }} >
))} )}
)}
); };