From 8b403a4208710e9c247f61d86c348d3421fefd4d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 21 Oct 2025 15:01:48 +0700 Subject: [PATCH] feat(FE-113): create useSelect hook --- src/components/input/SelectInput.tsx | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/components/input/SelectInput.tsx b/src/components/input/SelectInput.tsx index f6cef527..e16bbea0 100644 --- a/src/components/input/SelectInput.tsx +++ b/src/components/input/SelectInput.tsx @@ -1,6 +1,8 @@ 'use client'; import { ComponentType, ReactNode, useEffect, useMemo, useState } from 'react'; +import useSWR from 'swr'; + import Select, { OptionProps, GroupBase, @@ -11,7 +13,10 @@ import Select, { import CreatableSelect from 'react-select/creatable'; import makeAnimated from 'react-select/animated'; import { useDebounce } from 'use-debounce'; -import { cn } from '@/lib/helper'; +import { cn, getByPath } from '@/lib/helper'; +import { httpClientFetcher } from '@/services/http/client'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { BaseApiResponse } from '@/types/api/api-general'; export interface OptionType { value: string | number; @@ -222,4 +227,45 @@ const SelectInput = (props: SelectInputProps) => { ); }; +const useSelect = ( + basePath: string, + valueKey: keyof T, + labelKey: keyof T, + searchKey: string = 'search', + params?: { [key: string]: string } +) => { + const [inputValue, setInputValue] = useState(''); + + const optionsUrlParams = useMemo(() => { + return new URLSearchParams({ + [searchKey]: inputValue ?? '', + ...params, + }).toString(); + }, [inputValue, searchKey]); + + const optionsUrl = `${basePath}?${optionsUrlParams}`; + + const { data, isLoading } = useSWR(optionsUrl, async (url) => { + return await httpClientFetcher>(url); + }); + + const options = isResponseSuccess(data) + ? data.data.map((item) => { + return { + value: getByPath(item, valueKey as string), + label: getByPath(item, labelKey as string), + }; + }) + : []; + + return { + inputValue, + setInputValue, + options, + isLoadingOptions: isLoading, + rawData: data, + }; +}; + +export { useSelect }; export default SelectInput;