karusic/front2/src/components/form/SelectSingle.tsx
2024-09-01 16:08:06 +02:00

138 lines
3.4 KiB
TypeScript

import { useMemo, useRef, useState } from 'react';
import {
Badge,
Box,
Button,
Flex,
Input,
InputGroup,
InputRightElement,
Spinner,
Tag,
TagCloseButton,
TagLabel,
} from '@chakra-ui/react';
import {
MdClose,
MdKeyboardArrowDown,
MdKeyboardArrowUp,
MdSearch,
} from 'react-icons/md';
import {
FormSelectList,
SelectMultipleValueDisplayType,
} from '@/components/form/FormSelectList';
import { isNullOrUndefined } from '@/utils/validator';
export type SelectSingleProps = {
options?: object[];
value?: number | string;
onChange?: (value: number | string | undefined) => void;
keyKey?: string;
keyValue?: string;
};
export const SelectSingle = ({
options,
onChange,
value,
keyKey = 'id',
keyValue = keyKey,
}: SelectSingleProps) => {
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 ref = useRef<HTMLInputElement | null>(null);
const selectedOptions = useMemo(() => {
if (isNullOrUndefined(value)) {
return undefined;
}
return transformedOption?.find((data) => data.id === value);
}, [value, transformedOption]);
const selectValue = (data?: SelectMultipleValueDisplayType) => {
const tmpData = data?.id == selectedOptions?.id ? undefined : data;
setShowList(false);
if (onChange) {
onChange(tmpData?.id);
}
};
if (!transformedOption) {
return <Spinner />;
}
function onChangeInput(value: string): void {
if (value === '') {
setCurrentSearch(undefined);
} else {
setCurrentSearch(value);
}
}
const onRemoveItem = () => {
if (showList || !selectedOptions) {
ref?.current?.focus();
return;
}
console.log('Remove item ...');
if (onChange) {
onChange(undefined);
}
};
return (
<Flex direction="column" width="full" gap="0px">
<Flex>
<Input
ref={ref}
width="full"
onChange={(e) => onChangeInput(e.target.value)}
//onSubmit={onSubmit}
onFocus={() => setShowList(true)}
onBlur={() => setTimeout(() => setShowList(false), 200)}
value={
showList ? (currentSearch ?? '') : (selectedOptions?.name ?? '')
}
backgroundColor={
showList || !selectedOptions ? undefined : 'green.500'
}
borderRadius="5px 0 0 5px"
/>
<Button
onClick={onRemoveItem}
variant="outline"
borderRadius="0 5px 5px 0"
borderWidth="1px 1px 1px 0"
isDisabled={showList}
>
{selectedOptions ? (
<MdClose color="gray.300" />
) : showList ? (
<MdKeyboardArrowUp color="gray.300" />
) : (
<MdKeyboardArrowDown color="gray.300" />
)}
</Button>
</Flex>
{showList && (
<FormSelectList
options={transformedOption}
selected={selectedOptions ? [selectedOptions] : []}
search={currentSearch}
onSelectValue={selectValue}
/>
)}
</Flex>
);
};