|
|
|
|
@ -1,27 +1,18 @@ |
|
|
|
|
import type { FormEvent, ChangeEvent } from 'react' |
|
|
|
|
import { |
|
|
|
|
useState, |
|
|
|
|
useRef, |
|
|
|
|
useCallback, |
|
|
|
|
} from 'react' |
|
|
|
|
import type { FormEvent } from 'react' |
|
|
|
|
import { useCallback, useEffect } from 'react' |
|
|
|
|
|
|
|
|
|
import trim from 'lodash/trim' |
|
|
|
|
import debounce from 'lodash/debounce' |
|
|
|
|
import size from 'lodash/size' |
|
|
|
|
import { useToggle } from 'hooks' |
|
|
|
|
|
|
|
|
|
import type { SearchItems } from 'requests' |
|
|
|
|
import { getSearchItems } from 'requests' |
|
|
|
|
import { |
|
|
|
|
useRequest, |
|
|
|
|
useToggle, |
|
|
|
|
} from 'hooks' |
|
|
|
|
|
|
|
|
|
import { SEARCH_DELAY, MIN_CHARACTERS_LENGTH } from '../config' |
|
|
|
|
import { normalizeItems } from '../helpers' |
|
|
|
|
import { useExtendedSearchStore } from 'features/ExtendedSearchPage/store' |
|
|
|
|
|
|
|
|
|
export const useSearch = () => { |
|
|
|
|
const [searchItems, setSearchItems] = useState<SearchItems>({}) |
|
|
|
|
const abortControllerRef = useRef<AbortController | null>(null) |
|
|
|
|
const { |
|
|
|
|
isFetching, |
|
|
|
|
onQueryChange, |
|
|
|
|
query, |
|
|
|
|
reset, |
|
|
|
|
searchItems, |
|
|
|
|
} = useExtendedSearchStore() |
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
close, |
|
|
|
|
@ -29,58 +20,22 @@ export const useSearch = () => { |
|
|
|
|
open, |
|
|
|
|
} = useToggle() |
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
isFetching, |
|
|
|
|
request: searchItemsRequest, |
|
|
|
|
} = useRequest(getSearchItems) |
|
|
|
|
|
|
|
|
|
const fetchSearchItems = useCallback(debounce((searchString: string) => { |
|
|
|
|
const abortController = new window.AbortController() |
|
|
|
|
abortControllerRef.current = abortController |
|
|
|
|
searchItemsRequest(searchString, abortController.signal).then((data) => { |
|
|
|
|
setSearchItems(data) |
|
|
|
|
abortControllerRef.current = null |
|
|
|
|
}) |
|
|
|
|
}, SEARCH_DELAY), []) |
|
|
|
|
|
|
|
|
|
const cancelRequest = useCallback(() => { |
|
|
|
|
const abortController = abortControllerRef.current |
|
|
|
|
|
|
|
|
|
if (abortController) { |
|
|
|
|
abortController.abort() |
|
|
|
|
abortControllerRef.current = null |
|
|
|
|
} |
|
|
|
|
}, []) |
|
|
|
|
|
|
|
|
|
const onChange = useCallback(({ target: { value } }: ChangeEvent<HTMLInputElement>) => { |
|
|
|
|
const trimmedValue = trim(value) |
|
|
|
|
|
|
|
|
|
if (size(trimmedValue) >= MIN_CHARACTERS_LENGTH) { |
|
|
|
|
cancelRequest() |
|
|
|
|
setSearchItems({}) |
|
|
|
|
fetchSearchItems(trimmedValue) |
|
|
|
|
open() |
|
|
|
|
} else { |
|
|
|
|
close() |
|
|
|
|
} |
|
|
|
|
}, [ |
|
|
|
|
cancelRequest, |
|
|
|
|
close, |
|
|
|
|
fetchSearchItems, |
|
|
|
|
open, |
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
const onSubmit = useCallback((e: FormEvent<HTMLFormElement>) => { |
|
|
|
|
e.preventDefault() |
|
|
|
|
}, []) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
reset() |
|
|
|
|
}, [reset]) |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
close, |
|
|
|
|
isFetching, |
|
|
|
|
normalizedItems: normalizeItems(searchItems), |
|
|
|
|
onChange, |
|
|
|
|
onChange: onQueryChange, |
|
|
|
|
onFocus: open, |
|
|
|
|
onSubmit, |
|
|
|
|
query, |
|
|
|
|
searchItems, |
|
|
|
|
showResults: isOpen, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|