import useDebounce from "@/hooks/useDebounce"; import { useFriends } from "@/hooks/useFriends"; import { UserCircleIcon, UserPlusIcon } from "@heroicons/react/24/outline"; import { FC, PropsWithChildren, useEffect, useState } from "react"; import UserAvatar from "../user/UserAvatar"; import BasicField from "./BasicField"; type UserSearchProps = { limit?: number; friends: Map<string, any> | undefined; } const UserSearch:FC<PropsWithChildren<UserSearchProps>> = ({ limit = 6, friends }) => { const [searchQuery, setSearchQuery] = useState<string>(""); const debouncedSearchQuery = useDebounce<string>(searchQuery, 500) const [searchResults, setSearchResults] = useState<Map<[key: string], any>>(new Map([])); const [loading, setLoading] = useState<boolean>(false); useEffect(() => { setLoading(true) if(searchQuery.length === 0){ setSearchResults(new Map([])) } }, [searchQuery, setSearchResults]) useEffect(() => { if(debouncedSearchQuery.length > 0){ const endpoint = `${process.env.NEXT_PUBLIC_USER_SERVICE_URL}api/search?searchQuery=${debouncedSearchQuery}`; fetch(endpoint).then(async (result) => { const data = await result.json(); setLoading(false) setSearchResults(new Map(data.result)) }); } }, [debouncedSearchQuery]) return ( <div> <BasicField name="search" placeholder="Search users" onChange={setSearchQuery}/> <div className="border-t pt-2 flex item-center flex-col"> {!searchQuery && <div className='flex items-center justify-center mb-2'> <p className='text-xs text-gray-500'> Enter a search query to find friends </p> </div> } <div className="border-b"> {searchQuery && !loading && Array.from(searchResults.values()).map((result, index) => { if(index < limit && !friends?.has(result[0])){ console.log(result) return ( <div className="flex justify-between hover:bg-gray-100 rounded-md mb-2" key={index}> <UserAvatar key={result[0]} username={result.username} firstName={result.firstName} lastName={result.lastName} /> <button type="button" className="ml-auto mr-1 flex-shrink-1 rounded-full text-c-pink p-1 hover:text-gray-200 focus:outline-none " > <span className="sr-only">View notifications</span> <UserPlusIcon className="h-6 w-6" aria-hidden="true" /> </button> </div> ) } })} {searchQuery && loading && <div className="flex justify-center mb-2"> <div className="h-6 w-6 animate-spin text-gray-300 rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]" role="status"> </div> </div>} {searchQuery && !loading && searchResults.size === 0 && <div> <p className='text-xs text-gray-500 flex justify-center mb-2'> No results found </p> </div> } </div> <div className="w-full pt-2 text-xs text-gray-500"> Friends </div> {friends && searchQuery && !loading && Array.from(friends.values()).map((result, index) => { if(friends?.has(result[0])){ return ( <div className="flex justify-between hover:bg-gray-100 rounded-md" key={index}> <UserAvatar key={index} username={result[1].username} firstName={result[1].firstName} lastName={result[1].lastName} /> <button type="button" className="ml-auto mr-1 flex-shrink-1 rounded-full text-c-pink p-1 hover:text-gray-200 focus:outline-none " > <span className="sr-only">View notifications</span> <UserPlusIcon className="h-6 w-6" aria-hidden="true" /> </button> </div> ) } })} </div> </div> ) } export default UserSearch;