76 lines
2.6 KiB
TypeScript
76 lines
2.6 KiB
TypeScript
import React, {useEffect, useId, useState} from 'react';
|
|
import { AsyncPaginate } from 'react-select-async-paginate';
|
|
import axios from 'axios';
|
|
|
|
export const SelectFieldMany = ({ options, field, form, itemRef, showField, disabled }) => {
|
|
const [value, setValue] = useState([]);
|
|
const PAGE_SIZE = 100;
|
|
|
|
useEffect(() => {
|
|
// Check if field.value is an array of objects (Initial Load with Async data)
|
|
if (field.value && Array.isArray(field.value) && field.value.length > 0 && typeof field.value[0] === 'object') {
|
|
const initialValue = field.value.map((el) => ({
|
|
value: el.id,
|
|
label: el[showField] || el.label
|
|
}));
|
|
setValue(initialValue);
|
|
// Update form to IDs for submission consistency
|
|
form.setFieldValue(
|
|
field.name,
|
|
field.value.map((el) => el.id),
|
|
);
|
|
}
|
|
// Check if field.value is array of primitives (IDs) and options are provided (Static)
|
|
else if (field.value && Array.isArray(field.value) && field.value.length > 0 && options && options.length > 0) {
|
|
// Map IDs to labels from options
|
|
const initialValue = field.value.map(id => {
|
|
const option = options.find(o => (o.id === id || o.value === id));
|
|
return option ? { value: option.id || option.value, label: option[showField] || option.label } : null;
|
|
}).filter(Boolean);
|
|
setValue(initialValue);
|
|
}
|
|
// Handle empty field
|
|
else if (!field.value || field.value.length === 0) {
|
|
setValue([]);
|
|
}
|
|
}, [field.value, options, showField, field.name, form]);
|
|
|
|
const mapResponseToValuesAndLabels = (data) => ({
|
|
value: data.id,
|
|
label: data.label,
|
|
});
|
|
|
|
const handleChange = (data: any) => {
|
|
setValue(data)
|
|
form.setFieldValue(
|
|
field.name,
|
|
data.map(el => (el?.value || null)),
|
|
);
|
|
};
|
|
|
|
async function callApi(inputValue: string, loadedOptions: any[]) {
|
|
const path = `/${itemRef}/autocomplete?limit=${PAGE_SIZE}&offset=${loadedOptions.length}${inputValue ? `&query=${inputValue}` : ''}`;
|
|
const { data } = await axios(path);
|
|
return {
|
|
options: data.map(mapResponseToValuesAndLabels),
|
|
hasMore: data.length === PAGE_SIZE,
|
|
}
|
|
}
|
|
return (
|
|
<AsyncPaginate
|
|
classNames={{
|
|
control: () => 'px-1 py-2',
|
|
}}
|
|
classNamePrefix='react-select'
|
|
instanceId={useId()}
|
|
value={value}
|
|
isMulti
|
|
debounceTimeout={1000}
|
|
loadOptions={callApi}
|
|
onChange={handleChange}
|
|
defaultOptions
|
|
isDisabled={disabled}
|
|
isClearable
|
|
/>
|
|
);
|
|
}; |