import { useInfiniteQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' import type { ApiCollection } from '../types' import type { SearchResultResource } from '../types/resources/search_result' import { getSearchResultsQueryKey, getSearchResultsRequestArgs, } from '../utils/request/get_search_results' import { ONE_MINUTE } from '../utils/time' import { useApiClient } from './use_api_client' export type SearchResultsCollection = ApiCollection & { meta: { failedTypes?: SearchResultResource['type'][] } } type SearchResultsPageParam = { offset?: number } export const NO_FAILED_TYPES: SearchResultResource['type'][] = [] export function useSearchResults(term: string) { const apiClient = useApiClient() const trimmedTerm = term.trim() const { data, isPending, isError, isFetchNextPageError, fetchNextPage, hasNextPage, isFetchingNextPage, } = useInfiniteQuery({ queryKey: getSearchResultsQueryKey(trimmedTerm), queryFn: ({ pageParam }) => { const requestArgs = getSearchResultsRequestArgs(trimmedTerm) return apiClient.chat.get({ url: requestArgs.url, data: { ...requestArgs.data, ...pageParam }, }) }, initialPageParam: {} as SearchResultsPageParam, getNextPageParam: lastPage => nextPageParam(lastPage.meta.next?.offset), enabled: trimmedTerm.length >= 1, staleTime: ONE_MINUTE, refetchOnWindowFocus: false, refetchOnMount: false, retry: 1, }) const results = useMemo(() => uniqueResults(data?.pages.flatMap(page => page.data) ?? []), [data]) const failedTypes = data?.pages[0]?.meta.failedTypes ?? NO_FAILED_TYPES const loadMore = useCallback(() => fetchNextPage({ cancelRefetch: false }), [fetchNextPage]) return { results, failedTypes, isPending, isError: isError && !isFetchNextPageError, isFetchNextPageError, loadMore, hasNextPage, isFetchingNextPage, } } function nextPageParam(offset?: string): SearchResultsPageParam | undefined { return offset ? { offset: Number(offset) } : undefined } function uniqueResults(results: SearchResultResource[]) { const seen = new Set() return results.filter(result => { const key = `${result.type}:${result.id}` if (seen.has(key)) return false seen.add(key) return true }) }