diff --git a/src/components/pages/master-data/customer/form/CustomerForm.tsx b/src/components/pages/master-data/customer/form/CustomerForm.tsx index 0a629b36..fed5b14e 100644 --- a/src/components/pages/master-data/customer/form/CustomerForm.tsx +++ b/src/components/pages/master-data/customer/form/CustomerForm.tsx @@ -23,13 +23,17 @@ import TextInput from '@/components/input/TextInput'; import { cn } from '@/lib/helper'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import TextArea from '@/components/input/TextArea'; -import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import useSWR from 'swr'; import { UserApi } from '@/services/api/user'; import { TYPE_OPTIONS } from '@/config/constant'; import RequirePermission from '@/components/helper/RequirePermission'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; +import { User } from '@/types/api/api-general'; interface CustomerFormProps { formType?: 'add' | 'edit' | 'detail'; @@ -47,25 +51,15 @@ const CustomerForm = ({ // Setup State const [customerFormErrorMessage, setCustomerFormErrorMessage] = useState(''); const [isDeleteLoading, setIsDeleteLoading] = useState(false); - const [picSelectInputValue, setPicSelectInputValue] = useState(''); - // Fetch Data - const picUrl = `${UserApi.basePath}?${new URLSearchParams({ - search: picSelectInputValue ?? '', - })}`; - - const { data: pic, isLoading: isLoadingPic } = useSWR( - picUrl, - UserApi.getAllFetcher - ); + const { + setInputValue: setPicSelectInputValue, + options: picOptions, + isLoadingOptions: isLoadingPicOptions, + loadMore: loadMorePic, + } = useSelect(UserApi.basePath, 'id', 'name'); // -- Options data mapping - const picOptions = isResponseSuccess(pic) - ? pic?.data.map((area) => ({ - value: area.id, - label: area.name, - })) - : []; const typeOptions = TYPE_OPTIONS; // Handler Event @@ -240,11 +234,12 @@ const CustomerForm = ({ required placeholder='Pilih PIC' label='PIC' - value={formik.values.pic ?? undefined} + value={formik.values.pic?.value ? formik.values.pic : undefined} onChange={picChangeHandler} options={picOptions} onInputChange={setPicSelectInputValue} - isLoading={isLoadingPic} + onMenuScrollToBottom={loadMorePic} + isLoading={isLoadingPicOptions} isError={formik.touched.picId && Boolean(formik.errors.picId)} errorMessage={formik.errors.picId as string} isDisabled={formType === 'detail'} diff --git a/src/components/pages/master-data/kandang/form/KandangForm.tsx b/src/components/pages/master-data/kandang/form/KandangForm.tsx index ffea5718..acced3c5 100644 --- a/src/components/pages/master-data/kandang/form/KandangForm.tsx +++ b/src/components/pages/master-data/kandang/form/KandangForm.tsx @@ -9,7 +9,10 @@ import useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; -import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; @@ -31,6 +34,7 @@ import { UserApi } from '@/services/api/user'; import NumberInput from '@/components/input/NumberInput'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; +import { User } from '@/types/api/api-general'; interface KandangFormProps { type?: 'add' | 'edit' | 'detail'; @@ -128,23 +132,12 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => { const { setValues: formikSetValues } = formik; // location - const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); - - const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({ - search: locationSelectInputValue ?? '', - }).toString()}`; - - const { data: locations, isLoading: isLoadingLocations } = useSWR( - locationsUrl, - LocationApi.getAllFetcher - ); - - const locationOptions = isResponseSuccess(locations) - ? locations?.data.map((location) => ({ - value: location.id, - label: location.name, - })) - : []; + const { + setInputValue: setLocationSelectInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + loadMore: loadMoreLocations, + } = useSelect(LocationApi.basePath, 'id', 'name'); const locationChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('location', true); @@ -155,23 +148,12 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => { }; // PIC - const [picSelectInputValue, setPicSelectInputValue] = useState(''); - - const picsUrl = `${UserApi.basePath}?${new URLSearchParams({ - search: picSelectInputValue ?? '', - }).toString()}`; - - const { data: pics, isLoading: isLoadingPics } = useSWR( - picsUrl, - LocationApi.getAllFetcher - ); - - const picOptions = isResponseSuccess(pics) - ? pics?.data.map((pic) => ({ - value: pic.id, - label: pic.name, - })) - : []; + const { + setInputValue: setPicSelectInputValue, + options: picOptions, + isLoadingOptions: isLoadingPicOptions, + loadMore: loadMorePics, + } = useSelect(UserApi.basePath, 'id', 'name'); const picChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('pic', true); @@ -249,7 +231,8 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => { onChange={locationChangeHandler} options={locationOptions} onInputChange={setLocationSelectInputValue} - isLoading={isLoadingLocations} + onMenuScrollToBottom={loadMoreLocations} + isLoading={isLoadingLocationOptions} isError={ formik.touched.locationId && Boolean(formik.errors.locationId) } @@ -280,7 +263,8 @@ const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => { onChange={picChangeHandler} options={picOptions} onInputChange={setPicSelectInputValue} - isLoading={isLoadingPics} + onMenuScrollToBottom={loadMorePics} + isLoading={isLoadingPicOptions} isError={formik.touched.picId && Boolean(formik.errors.picId)} errorMessage={formik.errors.picId as string} isDisabled={type === 'detail'} diff --git a/src/components/pages/master-data/location/form/LocationForm.tsx b/src/components/pages/master-data/location/form/LocationForm.tsx index 9f77cf86..224c0f35 100644 --- a/src/components/pages/master-data/location/form/LocationForm.tsx +++ b/src/components/pages/master-data/location/form/LocationForm.tsx @@ -9,7 +9,10 @@ import useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; -import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; @@ -29,6 +32,7 @@ import { AreaApi, LocationApi } from '@/services/api/master-data'; import { cn } from '@/lib/helper'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; +import { Area } from '@/types/api/master-data/area'; interface LocationFormProps { type?: 'add' | 'edit' | 'detail'; @@ -117,23 +121,12 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => { const { setValues: formikSetValues } = formik; - const [areaSelectInputValue, setAreaSelectInputValue] = useState(''); - - const areasUrl = `${AreaApi.basePath}?${new URLSearchParams({ - search: areaSelectInputValue ?? '', - }).toString()}`; - - const { data: areas, isLoading: isLoadingAreas } = useSWR( - areasUrl, - AreaApi.getAllFetcher - ); - - const areaOptions = isResponseSuccess(areas) - ? areas?.data.map((area) => ({ - value: area.id, - label: area.name, - })) - : []; + const { + setInputValue: setAreaSelectInputValue, + options: areaOptions, + isLoadingOptions: isLoadingAreaOptions, + loadMore: loadMoreAreas, + } = useSelect(AreaApi.basePath, 'id', 'name'); const areaChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('area', true); @@ -224,7 +217,8 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => { onChange={areaChangeHandler} options={areaOptions} onInputChange={setAreaSelectInputValue} - isLoading={isLoadingAreas} + onMenuScrollToBottom={loadMoreAreas} + isLoading={isLoadingAreaOptions} isError={formik.touched.areaId && Boolean(formik.errors.areaId)} errorMessage={formik.errors.areaId as string} isDisabled={type === 'detail'} diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx index 7d8b8784..cd2c361b 100644 --- a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx @@ -9,7 +9,10 @@ import useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; -import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; @@ -31,6 +34,8 @@ import { flags } from '@/types/api/api-general'; import { SUPPLIER_FLAG_OPTIONS } from '@/config/constant'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; +import { Supplier } from '@/types/api/master-data/supplier'; +import { Uom } from '@/types/api/master-data/uom'; interface NonstockFormProps { type?: 'add' | 'edit' | 'detail'; @@ -129,23 +134,12 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const { setValues: formikSetValues } = formik; // UOM - const [uomSelectInputValue, setUomSelectInputValue] = useState(''); - - const uomsUrl = `${UomApi.basePath}?${new URLSearchParams({ - search: uomSelectInputValue ?? '', - }).toString()}`; - - const { data: uoms, isLoading: isLoadingUoms } = useSWR( - uomsUrl, - UomApi.getAllFetcher - ); - - const uomOptions = isResponseSuccess(uoms) - ? uoms?.data.map((uom) => ({ - value: uom.id, - label: uom.name, - })) - : []; + const { + setInputValue: setUomSelectInputValue, + options: uomOptions, + isLoadingOptions: isLoadingUomOptions, + loadMore: loadMoreUoms, + } = useSelect(UomApi.basePath, 'id', 'name'); const uomChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('uom', true); @@ -156,25 +150,12 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { }; // supplier - const [supplierSelectInputValue, setSupplierSelectInputValue] = useState(''); - - const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ - search: supplierSelectInputValue ?? '', - }).toString()}`; - - const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR( - suppliersUrl, - SupplierApi.getAllFetcher - ); - - const supplierOptions = isResponseSuccess(suppliers) - ? suppliers?.data - .filter((sup) => sup.category === 'BOP') - .map((supplier) => ({ - value: supplier.id, - label: supplier.name, - })) - : []; + const { + setInputValue: setSupplierSelectInputValue, + options: supplierOptions, + isLoadingOptions: isLoadingSupplierOptions, + loadMore: loadMoreSuppliers, + } = useSelect(SupplierApi.basePath, 'id', 'name'); const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('suppliers', true); @@ -264,7 +245,8 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { onChange={uomChangeHandler} options={uomOptions} onInputChange={setUomSelectInputValue} - isLoading={isLoadingUoms} + isLoading={isLoadingUomOptions} + onMenuScrollToBottom={loadMoreUoms} isError={formik.touched.uomId && Boolean(formik.errors.uomId)} errorMessage={formik.errors.uomId as string} isDisabled={type === 'detail'} @@ -278,7 +260,8 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { onChange={supplierChangeHandler} options={supplierOptions ?? []} onInputChange={setSupplierSelectInputValue} - isLoading={isLoadingSuppliers} + onMenuScrollToBottom={loadMoreSuppliers} + isLoading={isLoadingSupplierOptions} isError={ formik.touched.suppliers && Boolean(formik.errors.suppliers) } diff --git a/src/components/pages/master-data/product/form/ProductForm.tsx b/src/components/pages/master-data/product/form/ProductForm.tsx index 204422dd..2fc3b267 100644 --- a/src/components/pages/master-data/product/form/ProductForm.tsx +++ b/src/components/pages/master-data/product/form/ProductForm.tsx @@ -40,6 +40,7 @@ import { import { cn } from '@/lib/helper'; import { PRODUCT_FLAG_OPTIONS } from '@/config/constant'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; +import { Supplier } from '@/types/api/master-data/supplier'; interface ProductFormProps { type?: 'add' | 'edit' | 'detail'; @@ -145,6 +146,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { setInputValue: setUomSelectInputValue, options: uomOptions, isLoadingOptions: isLoadingUoms, + loadMore: loadMoreUoms, } = useSelect(UomApi.basePath, 'id', 'name'); const uomChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('uom', true); @@ -158,6 +160,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { setInputValue: setCategorySelectInputValue, options: categoryOptions, isLoadingOptions: isLoadingCategories, + loadMore: loadMoreCategories, } = useSelect(ProductCategoryApi.basePath, 'id', 'name'); const categoryChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('product_category', true); @@ -167,17 +170,15 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { }; // Supplier (multi select) - using SWR to filter by category - const [supplierSelectInputValue, setSupplierSelectInputValue] = useState(''); - const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ search: supplierSelectInputValue ?? '' }).toString()}`; - const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR( - suppliersUrl, - SupplierApi.getAllFetcher - ); - const supplierOptions = isResponseSuccess(suppliers) - ? suppliers?.data - .filter((sup) => sup.category === 'SAPRONAK') - .map((sup) => ({ value: sup.id, label: sup.name })) - : []; + const { + setInputValue: setSupplierSelectInputValue, + options: supplierOptions, + isLoadingOptions: isLoadingSuppliers, + loadMore: loadMoreSuppliers, + } = useSelect(SupplierApi.basePath, 'id', 'name', 'search', { + category: 'SAPRONAK', + }); + const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { const arr = Array.isArray(val) ? val : val ? [val] : []; formik.setFieldTouched('supplier_ids', true); @@ -291,6 +292,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { onChange={uomChangeHandler} options={uomOptions} onInputChange={setUomSelectInputValue} + onMenuScrollToBottom={loadMoreUoms} isLoading={isLoadingUoms} isError={ (formik.touched.uom || formik.touched.uom_id) && @@ -308,6 +310,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { onChange={categoryChangeHandler} options={categoryOptions} onInputChange={setCategorySelectInputValue} + onMenuScrollToBottom={loadMoreCategories} isLoading={isLoadingCategories} isError={ (formik.touched.product_category || @@ -412,6 +415,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { onChange={supplierChangeHandler} options={supplierOptions} onInputChange={setSupplierSelectInputValue} + onMenuScrollToBottom={loadMoreSuppliers} isLoading={isLoadingSuppliers} isError={ formik.touched.supplier_ids && diff --git a/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx index 0fb55a2a..cab9f750 100644 --- a/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx +++ b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx @@ -9,7 +9,10 @@ import useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; -import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; @@ -35,6 +38,8 @@ import { cn } from '@/lib/helper'; import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import AlertErrorList from '@/components/helper/form/FormErrors'; +import { Area } from '@/types/api/master-data/area'; +import { Kandang } from '@/types/api/master-data/kandang'; interface WarehouseFormProps { type?: 'add' | 'edit' | 'detail'; @@ -221,61 +226,28 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { const { setValues: formikSetValues } = formik; // Area - const [areaSelectInputValue, setAreaSelectInputValue] = useState(''); - - const areasUrl = `${AreaApi.basePath}?${new URLSearchParams({ - search: areaSelectInputValue ?? '', - }).toString()}`; - - const { data: areas, isLoading: isLoadingAreas } = useSWR( - areasUrl, - AreaApi.getAllFetcher - ); - - const areaOptions = isResponseSuccess(areas) - ? areas?.data.map((area) => ({ - value: area.id, - label: area.name, - })) - : []; + const { + setInputValue: setAreaSelectInputValue, + options: areaOptions, + isLoadingOptions: isLoadingAreaOptions, + loadMore: loadMoreAreas, + } = useSelect(AreaApi.basePath, 'id', 'name'); // Location - const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); - - const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({ - search: locationSelectInputValue ?? '', - }).toString()}`; - - const { data: locations, isLoading: isLoadingLocations } = useSWR( - locationsUrl, - LocationApi.getAllFetcher - ); - - const locationOptions = isResponseSuccess(locations) - ? locations?.data.map((location) => ({ - value: location.id, - label: location.name, - })) - : []; + const { + setInputValue: setLocationSelectInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + loadMore: loadMoreLocations, + } = useSelect(LocationApi.basePath, 'id', 'name'); // Kandang - const [kandangSelectInputValue, setKandangSelectInputValue] = useState(''); - - const kandangsUrl = `${KandangApi.basePath}?${new URLSearchParams({ - search: kandangSelectInputValue ?? '', - }).toString()}`; - - const { data: kandangs, isLoading: isLoadingKandangs } = useSWR( - kandangsUrl, - KandangApi.getAllFetcher - ); - - const kandangOptions = isResponseSuccess(kandangs) - ? kandangs?.data.map((kandang) => ({ - value: kandang.id, - label: kandang.name, - })) - : []; + const { + setInputValue: setKandangSelectInputValue, + options: kandangOptions, + isLoadingOptions: isLoadingKandangOptions, + loadMore: loadMoreKandangs, + } = useSelect(KandangApi.basePath, 'id', 'name'); const typeChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('type', true); @@ -393,7 +365,8 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { onChange={areaChangeHandler} options={areaOptions} onInputChange={setAreaSelectInputValue} - isLoading={isLoadingAreas} + onMenuScrollToBottom={loadMoreAreas} + isLoading={isLoadingAreaOptions} isError={formik.touched.areaId && Boolean(formik.errors.areaId)} errorMessage={formik.errors.areaId as string} isDisabled={type === 'detail'} @@ -409,7 +382,8 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { onChange={locationChangeHandler} options={locationOptions} onInputChange={setLocationSelectInputValue} - isLoading={isLoadingLocations} + onMenuScrollToBottom={loadMoreLocations} + isLoading={isLoadingLocationOptions} isError={ formik.touched.locationId && Boolean(formik.errors.locationId) } @@ -427,7 +401,8 @@ const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { onChange={kandangChangeHandler} options={kandangOptions} onInputChange={setKandangSelectInputValue} - isLoading={isLoadingKandangs} + onMenuScrollToBottom={loadMoreKandangs} + isLoading={isLoadingKandangOptions} isError={ formik.touched.kandangId && Boolean(formik.errors.kandangId) }