|
1 | | -import { useCallback } from 'react'; |
| 1 | +import { useMemo, useRef, useState } from 'react'; |
2 | 2 |
|
3 | | -import { licensesArrayLowercase, nonOpenSourceLicensesArray, openSourceLicensesArray } from '@databank/core'; |
4 | | -import type { LicenseWithLowercase } from '@databank/core'; |
5 | | -import { useDebounceCallback } from 'usehooks-ts'; |
| 3 | +import { |
| 4 | + licensesArrayLowercase, |
| 5 | + mostFrequentOpenSourceLicenses, |
| 6 | + nonOpenSourceLicensesArray, |
| 7 | + openSourceLicensesArray |
| 8 | +} from '@databank/core'; |
| 9 | +import type { $DatasetLicenses, LicenseWithLowercase } from '@databank/core'; |
| 10 | +import type FormTypes from '@douglasneuroinformatics/libui-form-types'; |
| 11 | + |
| 12 | +type BaseFormData = { |
| 13 | + isOpenSource?: boolean; |
| 14 | + license?: $DatasetLicenses; |
| 15 | + searchLicenseString?: string; |
| 16 | +}; |
| 17 | + |
| 18 | +function toObject(licenses: typeof licensesArrayLowercase): { [key: string]: string } { |
| 19 | + return Object.fromEntries( |
| 20 | + licenses.map(([key, value]) => { |
| 21 | + return [key, value.name]; |
| 22 | + }) |
| 23 | + ); |
| 24 | +} |
6 | 25 |
|
7 | 26 | export function useDebounceLicensesFilter() { |
8 | | - const _filterLicenses = useCallback( |
9 | | - (searchString: string | undefined, isOpenSource: boolean | undefined): { [key: string]: string } => { |
10 | | - let filterLicensesArray: [string, LicenseWithLowercase][]; |
11 | | - if (isOpenSource === undefined) { |
12 | | - filterLicensesArray = licensesArrayLowercase; |
13 | | - } else { |
14 | | - filterLicensesArray = isOpenSource ? openSourceLicensesArray : nonOpenSourceLicensesArray; |
15 | | - } |
| 27 | + const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined); |
| 28 | + const [licenseOptions, setLicenseOptions] = useState<{ [key: string]: string }>(mostFrequentOpenSourceLicenses); |
16 | 29 |
|
17 | | - if (searchString !== undefined) { |
18 | | - filterLicensesArray = filterLicensesArray.filter( |
19 | | - ([_, license]) => |
20 | | - license.lowercaseLicenseId.includes(searchString) || license.lowercaseName.includes(searchString) |
21 | | - ); |
22 | | - } |
| 30 | + const subscribe = useMemo( |
| 31 | + () => ({ |
| 32 | + onChange: (values: BaseFormData, setValues: React.Dispatch<React.SetStateAction<BaseFormData>>) => { |
| 33 | + clearTimeout(timeoutRef.current); |
| 34 | + const { isOpenSource, license, searchLicenseString } = values; |
| 35 | + |
| 36 | + if (searchLicenseString === undefined && isOpenSource === undefined) { |
| 37 | + setLicenseOptions(mostFrequentOpenSourceLicenses); |
| 38 | + return; |
| 39 | + } |
23 | 40 |
|
24 | | - return Object.fromEntries( |
25 | | - filterLicensesArray.map(([key, value]) => { |
26 | | - return [key, value.name]; |
27 | | - }) |
28 | | - ); |
29 | | - }, |
| 41 | + const searchString = searchLicenseString?.toLowerCase(); |
| 42 | + |
| 43 | + timeoutRef.current = setTimeout(() => { |
| 44 | + let filterLicensesArray: [string, LicenseWithLowercase][]; |
| 45 | + if (isOpenSource === undefined) { |
| 46 | + filterLicensesArray = licensesArrayLowercase; |
| 47 | + } else { |
| 48 | + filterLicensesArray = isOpenSource ? openSourceLicensesArray : nonOpenSourceLicensesArray; |
| 49 | + } |
| 50 | + |
| 51 | + if (!searchString) { |
| 52 | + setLicenseOptions(toObject(filterLicensesArray)); |
| 53 | + if (filterLicensesArray.find(([key]) => key === license)) { |
| 54 | + setValues((prevValues) => ({ ...prevValues, license: undefined })); |
| 55 | + } |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + filterLicensesArray = filterLicensesArray.filter( |
| 60 | + ([_, license]) => |
| 61 | + license.lowercaseLicenseId.includes(searchString) || license.lowercaseName.includes(searchString) |
| 62 | + ); |
| 63 | + |
| 64 | + setLicenseOptions(toObject(filterLicensesArray)); |
| 65 | + if (filterLicensesArray.find(([key]) => key === license)) { |
| 66 | + setValues((prevValues) => ({ ...prevValues, license: undefined })); |
| 67 | + } |
| 68 | + }, 500); |
| 69 | + }, |
| 70 | + selector: (values: FormTypes.PartialData<BaseFormData>) => { |
| 71 | + return `${values.isOpenSource}-${values.searchLicenseString}`; |
| 72 | + } |
| 73 | + }), |
30 | 74 | [] |
31 | 75 | ); |
32 | 76 |
|
33 | | - const debouncedLicensesFilter = useDebounceCallback(_filterLicenses, 200); |
34 | | - |
35 | | - return debouncedLicensesFilter; |
| 77 | + return { licenseOptions, subscribe }; |
36 | 78 | } |
0 commit comments