karusic/front2/src/components/form/SelectMultiple.tsx
2024-09-15 17:56:48 +02:00

127 lines
3.3 KiB
TypeScript

import { useMemo, useState } from 'react';
import {
Flex,
Input,
InputGroup,
InputRightElement,
Spinner,
Tag,
TagCloseButton,
TagLabel,
Wrap,
WrapItem,
} from '@chakra-ui/react';
import { MdSearch } from 'react-icons/md';
import {
FormSelectList,
SelectMultipleValueDisplayType,
} from '@/components/form/FormSelectList';
import { isNullOrUndefined } from '@/utils/validator';
export type SelectMultipleProps = {
options?: object[];
values?: (number | string)[];
onChange?: (value: (number | string)[] | undefined) => void;
keyKey?: string;
keyValue?: string;
};
export const SelectMultiple = ({
options,
onChange,
values,
keyKey = 'id',
keyValue = keyKey,
}: SelectMultipleProps) => {
const [showList, setShowList] = useState(false);
const transformedOption = useMemo(() => {
return options?.map((element) => {
return {
id: element[keyKey],
name: element[keyValue],
isSelected: false,
} as SelectMultipleValueDisplayType;
});
}, [options, keyKey, keyValue]);
const [currentSearch, setCurrentSearch] = useState<string | undefined>(
undefined
);
const selectedOptions = useMemo(() => {
if (isNullOrUndefined(values) || !transformedOption) {
return [];
}
return transformedOption.filter((element) => {
return values.includes(element[keyKey]);
});
}, [values, transformedOption]);
const selectValue = (data: SelectMultipleValueDisplayType) => {
const newValues = values?.includes(data.id)
? values.filter((elem) => data.id !== elem)
: [...(values ?? []), data.id];
setShowList(false);
if (onChange) {
if (newValues.length == 0) {
onChange(undefined);
} else {
onChange(newValues);
}
}
};
if (!options) {
return <Spinner />;
}
function onChangeInput(value: string): void {
if (value === '') {
setCurrentSearch(undefined);
} else {
setCurrentSearch(value);
}
}
return (
<Flex direction="column" width="full" gap="0px">
{selectedOptions && (
<Wrap spacing="5px" justify="left" width="full" marginBottom="2px">
{selectedOptions.map((data) => (
<WrapItem key={data[keyKey]}>
<Tag
size="md"
key="md"
borderRadius="5px"
variant="solid"
backgroundColor="green.500"
>
<TagLabel>{data[keyValue] ?? `id=${data[keyKey]}`}</TagLabel>
<TagCloseButton onClick={() => selectValue(data)} />
</Tag>
</WrapItem>
))}
</Wrap>
)}
<InputGroup minWidth="50%" marginLeft="auto">
<InputRightElement pointerEvents="none">
<MdSearch color="gray.300" />
</InputRightElement>
<Input
onChange={(e) => onChangeInput(e.target.value)}
//onSubmit={onSubmit}
onFocus={() => setShowList(true)}
onBlur={() => setTimeout(() => setShowList(false), 200)}
/>
</InputGroup>
{showList && (
<FormSelectList
options={transformedOption}
selected={selectedOptions}
search={currentSearch}
onSelectValue={selectValue}
/>
)}
</Flex>
);
};