From e076edd588b4faca198155f242eeb50272624975 Mon Sep 17 00:00:00 2001 From: talksik Date: Sat, 2 Apr 2022 14:57:19 -0400 Subject: [PATCH] debouncing results and sort of getting results back --- packages/api/routes/search.ts | 8 +-- ...rch.response.ts => userSearch.response.ts} | 2 +- .../components/User/basicUserDetailsRow.tsx | 35 +++++++++++ packages/desktop/src/controller/index.tsx | 16 ++--- packages/desktop/src/controller/nirvanaApi.ts | 10 ++++ .../desktop/src/pages/Home/newConvo/index.tsx | 60 ++++++++++++++++++- .../desktop/src/pages/Home/search/index.tsx | 35 ----------- 7 files changed, 115 insertions(+), 51 deletions(-) rename packages/core/responses/{search.response.ts => userSearch.response.ts} (83%) create mode 100644 packages/desktop/src/components/User/basicUserDetailsRow.tsx diff --git a/packages/api/routes/search.ts b/packages/api/routes/search.ts index 9238296..133f410 100644 --- a/packages/api/routes/search.ts +++ b/packages/api/routes/search.ts @@ -1,7 +1,7 @@ import express, { Application, Request, Response } from "express"; -import SearchResponse from "@nirvana/core/responses/search.response"; import { User } from "@nirvana/core/models"; +import UserSearchResponse from "../../core/responses/userSearch.response"; import { UserService } from "../services/user.service"; import { authCheck } from "../middleware/auth"; @@ -11,12 +11,12 @@ export default function getSearchRoutes() { router.use(express.json()); // get user details based on id token - router.get("/", authCheck, handleSearch); + router.get("/users", authCheck, handleUserSearch); return router; } -async function handleSearch(req: Request, res: Response) { +async function handleUserSearch(req: Request, res: Response) { try { const { query } = req.query; @@ -30,7 +30,7 @@ async function handleSearch(req: Request, res: Response) { query as string ); - const resObj = new SearchResponse(users ?? []); + const resObj = new UserSearchResponse(users ?? []); res.send(resObj); } catch (error) { diff --git a/packages/core/responses/search.response.ts b/packages/core/responses/userSearch.response.ts similarity index 83% rename from packages/core/responses/search.response.ts rename to packages/core/responses/userSearch.response.ts index ab534d2..85b248a 100644 --- a/packages/core/responses/search.response.ts +++ b/packages/core/responses/userSearch.response.ts @@ -3,7 +3,7 @@ import { User } from "@nirvana/core/models"; /** * Full results from the global search */ -export default class SearchResponse { +export default class UserSearchResponse { // all friends/contacts matching search contacts?: User[]; diff --git a/packages/desktop/src/components/User/basicUserDetailsRow.tsx b/packages/desktop/src/components/User/basicUserDetailsRow.tsx new file mode 100644 index 0000000..095e63d --- /dev/null +++ b/packages/desktop/src/components/User/basicUserDetailsRow.tsx @@ -0,0 +1,35 @@ +import { FaAngleRight } from "react-icons/fa"; +import { Tooltip } from "antd"; +import { User } from "@nirvana/core/models/user.model"; + +export default function renderUserRow(user: User) { + return ( + + + + + + + + {user.name} + + {user.email} + + + {/* actions */} + + + + + ); +} diff --git a/packages/desktop/src/controller/index.tsx b/packages/desktop/src/controller/index.tsx index 5bc7e2a..f2e3aa6 100644 --- a/packages/desktop/src/controller/index.tsx +++ b/packages/desktop/src/controller/index.tsx @@ -23,15 +23,11 @@ export function useGetUserDetails() { }); } -// export function useSearch() { -// const authTokens = useRecoilValue($authTokens); -// const searchQuery = useRecoilValue($searchQuery); - -// return useQuery( -// Querytypes.GET_SEARCH_RESULTS, -// () => search(authTokens.idToken, searchQuery), -// { enabled: searchQuery ? true : false, refetchOnWindowFocus: false } -// ); -// } +export function useUserSearch(searchQuery: string) { + return useQuery("USER_SEARCH", () => ApiCalls.userSearch(searchQuery), { + enabled: searchQuery ? true : false, + refetchOnWindowFocus: false, + }); +} // =========== MUTATIONS diff --git a/packages/desktop/src/controller/nirvanaApi.ts b/packages/desktop/src/controller/nirvanaApi.ts index 5d51efd..2ac263e 100644 --- a/packages/desktop/src/controller/nirvanaApi.ts +++ b/packages/desktop/src/controller/nirvanaApi.ts @@ -3,6 +3,7 @@ import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios"; import LoginResponse from "../../../core/responses/login.response"; import { User } from "@nirvana/core/models"; import UserDetailsResponse from "../../../core/responses/userDetails.response"; +import UserSearchResponse from "../../../core/responses/userSearch.response"; // export const localHost = process.env.REACT_APP_API_DOMAIN; @@ -60,8 +61,17 @@ async function getUserDetails(): Promise { return await NirvanaApi.fetch(`/user`, "GET", true); } +async function userSearch(searchQuery: string): Promise { + return await NirvanaApi.fetch( + `/search/users?query=${searchQuery}`, + "GET", + true + ); +} + export const ApiCalls = { login, authCheck, getUserDetails, + userSearch, }; diff --git a/packages/desktop/src/pages/Home/newConvo/index.tsx b/packages/desktop/src/pages/Home/newConvo/index.tsx index 1cd49c9..000903a 100644 --- a/packages/desktop/src/pages/Home/newConvo/index.tsx +++ b/packages/desktop/src/pages/Home/newConvo/index.tsx @@ -6,23 +6,81 @@ import { InputLabel, TextField, } from "@mui/material"; +import { useEffect, useState } from "react"; +import { $newConvoPage } from "../../../controller/recoil"; import { Search } from "@mui/icons-material"; +import renderUserRow from "../../../components/User/basicUserDetailsRow"; +import { useSetRecoilState } from "recoil"; +import { useUserSearch } from "../../../controller/index"; export default function NewConvo() { + const setNewPageConvo = useSetRecoilState($newConvoPage); + const [userSearchQuery, setuserSearchQuery] = useState(""); + const [debUserSearchQ, setDebUserSearchQ] = useState(""); + + const { data, isLoading, isError, refetch } = useUserSearch(debUserSearchQ); + + const [debTimeout, setdebTimeout] = useState(); + + // trigger the react query to refetch once our deb/"final" search query is set + useEffect(() => { + if (debUserSearchQ) refetch(); + }, [debUserSearchQ]); + + const handleGoBack = () => { + setNewPageConvo(false); + }; + + const triggerSearch = (searchQ: string) => { + // update search query now and + + setDebUserSearchQ(searchQ); + }; + + const handleUpdateSearchInput = (event: any) => { + const newSearchQuery = event.target.value; + + // wait 2 seconds to hit api + const currInitInterval = setTimeout(() => { + console.log("triggering debounced search"); + + triggerSearch(newSearchQuery); + }, 1000); + + // clear previous interval now that there is a new search entry + // preventing the last interval from triggering a search + setdebTimeout((prevTimeout: any) => { + clearTimeout(prevTimeout); + return currInitInterval; + }); + + // update the view showing that the user's input is visibly changing input + setuserSearchQuery(newSearchQuery); + }; + return (
- +
+ + {/* search results list */} +
+ {data?.users?.map((user) => renderUserRow(user))} +
); } diff --git a/packages/desktop/src/pages/Home/search/index.tsx b/packages/desktop/src/pages/Home/search/index.tsx index 4743e59..2ab4942 100644 --- a/packages/desktop/src/pages/Home/search/index.tsx +++ b/packages/desktop/src/pages/Home/search/index.tsx @@ -53,41 +53,6 @@ export default function Search() { setSelectedConvo(googleUserId); }; - const renderUserRow = (user: User) => { - return ( - selectContact(user.googleId)} - className="border-t border-t-zinc-500 py-5 flex flex-row justify-start - items-center w-full hover:bg-zinc-600 cursor-pointer group" - > - - - - - - - - {user.name} - - - {user.email} - - - {/* actions */} - - - - - ); - }; - return (