From eb32fdfe40eeb3796a5691735c2dede97ef1b90e Mon Sep 17 00:00:00 2001 From: Matt Kirby <MattJKirby@outlook.com> Date: Sun, 16 Apr 2023 21:40:28 +0100 Subject: [PATCH] Added standalone UserSearch --- .../src/components/form/UserSearch.tsx | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 daily-thought-frontend/src/components/form/UserSearch.tsx diff --git a/daily-thought-frontend/src/components/form/UserSearch.tsx b/daily-thought-frontend/src/components/form/UserSearch.tsx new file mode 100644 index 00000000..33d70ea0 --- /dev/null +++ b/daily-thought-frontend/src/components/form/UserSearch.tsx @@ -0,0 +1,82 @@ +import useDebounce from "@/hooks/useDebounce"; +import { UserCircleIcon } from "@heroicons/react/24/outline"; +import { FC, PropsWithChildren, useEffect, useState } from "react"; +import BasicField from "./BasicField"; + +type UserSearchProps = { + limit?: number +} + +const UserSearch:FC<PropsWithChildren<UserSearchProps>> = ({ + limit = 6 +}) => { + const [searchQuery, setSearchQuery] = useState<string>(""); + const debouncedSearchQuery = useDebounce<string>(searchQuery, 500) + const [searchResults, setSearchResults] = useState<any[]>([]); + const [loading, setLoading] = useState<boolean>(false) + + useEffect(() => { + setLoading(true) + if(searchQuery.length === 0){ + setSearchResults([]) + } + }, [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(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'> + <p className='text-xs text-gray-500'> + Enter a search query to add friends + </p> + </div> + } + {searchQuery && !loading && searchResults.map((result, index) => { + if(index < limit){ + return ( + <div className='flex items-center hover:bg-gray-100 rounded-md p-1'> + <div className=""> + <UserCircleIcon className='h-12 w-12 rounded-full text-gray-300 flex items-center justify-center' /> + </div> + <div className='text-sm ml-1 text-gray-900'> + {result.firstName && <div>{`${result.firstName} ${result.lastName || null}`}</div>} + <p className='text-sm text-gray-500 font-normal'>@{result.username}</p> + </div> + </div> + ) + } + })} + {searchQuery && loading && + <div className="flex justify-center"> + <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.length === 0 && + <div> + <p className='text-xs text-gray-500 flex justify-center'> + No results found + </p> + </div> + } + </div> + </div> + ) +} + +export default UserSearch; \ No newline at end of file -- GitLab