diff --git a/src/hooks/makeQuery.ts b/src/hooks/makeQuery.ts index 1d0e3013d..6aa28b7a5 100644 --- a/src/hooks/makeQuery.ts +++ b/src/hooks/makeQuery.ts @@ -31,7 +31,7 @@ type UseQueryHook = ( function makeQuery( query: DocumentNode ): UseQueryHook { - function useQuery({ + function useQuery({ displayLoader, require, skip, diff --git a/src/hooks/makeSearch.ts b/src/hooks/makeSearch.ts index c4b4dc42c..240274503 100644 --- a/src/hooks/makeSearch.ts +++ b/src/hooks/makeSearch.ts @@ -1,18 +1,57 @@ import { DocumentNode } from "graphql"; import { useState } from "react"; +import { QueryResult } from "react-apollo"; -import Debounce from "../components/Debounce"; -import { UseQueryResult } from "./makeQuery"; +import makeQuery, { UseQueryResult } from "./makeQuery"; +import useDebounce from "./useDebounce"; -export interface SearchQueryVariables { +export interface SearchVariables { after?: string; first: number; query: string; } -function makeSearch( +export interface UseSearchResult { + loadMore: () => void; + result: QueryResult; + search: (query: string) => void; +} +export type UseSearchOpts = Partial<{ + skip: boolean; + variables: TVariables; +}>; +export type UseSearchHook = ( + opts: UseSearchOpts +) => UseSearchResult; + +function makeSearch( query: DocumentNode, loadMoreFn: (result: UseQueryResult) => void ): UseSearchHook { - const [searchQuery, setSearchQuery] = useState(""); + const useSearchQuery = makeQuery(query); + + function useSearch( + opts: UseSearchOpts + ): UseSearchResult { + const [searchQuery, setSearchQuery] = useState(""); + const debouncedSearch = useDebounce(setSearchQuery); + const result = useSearchQuery({ + ...opts, + displayLoader: true, + variables: { + ...opts.variables, + query: searchQuery + } + }); + + return { + loadMore: () => loadMoreFn(result), + result, + search: debouncedSearch + }; + } + + return useSearch; } + +export default makeSearch; diff --git a/src/hooks/makeTopLevelSearch.ts b/src/hooks/makeTopLevelSearch.ts new file mode 100644 index 000000000..1a039546a --- /dev/null +++ b/src/hooks/makeTopLevelSearch.ts @@ -0,0 +1,45 @@ +import { DocumentNode } from "graphql"; + +import { PageInfoFragment } from "@saleor/types/PageInfoFragment"; +import makeSearch, { SearchVariables, UseSearchHook } from "./makeSearch"; + +export interface SearchData { + search: { + edges: Array<{ + node: any; + }>; + pageInfo: PageInfoFragment; + }; +} + +function makeTopLevelSearch< + TData extends SearchData, + TVariables extends SearchVariables +>(query: DocumentNode): UseSearchHook { + return makeSearch(query, result => { + if (result.data.search.pageInfo.hasNextPage) { + result.loadMore( + (prev, next) => { + if ( + prev.search.pageInfo.endCursor === next.search.pageInfo.endCursor + ) { + return prev; + } + + return { + ...prev, + search: { + ...prev.search, + edges: [...prev.search.edges, ...next.search.edges], + pageInfo: next.search.pageInfo + } + }; + }, + { + ...result.variables, + after: result.data.search.pageInfo.endCursor + } + ); + } + }); +}