154 lines
4.3 KiB
TypeScript
154 lines
4.3 KiB
TypeScript
import { RefObject, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
|
import {
|
|
MdClose,
|
|
MdEdit,
|
|
MdKeyboardArrowDown,
|
|
MdKeyboardArrowUp,
|
|
} from 'react-icons/md';
|
|
|
|
import { SelectList, SelectListModel } from '@/components/select/SelectList';
|
|
import { isNullOrUndefined } from '@/utils/validator';
|
|
import { Button, Flex, Input } from '@/ui';
|
|
|
|
export type SelectSingleProps = {
|
|
options?: object[];
|
|
value?: number | string;
|
|
onChange?: (value: number | string | undefined) => void;
|
|
keyKey?: string;
|
|
keyValue?: string;
|
|
ref?: RefObject<any>;
|
|
// if set add capability to add the search item
|
|
onCreate?: (data: string) => void;
|
|
// if a suggestion exist at the auto compleat
|
|
suggestion?: string;
|
|
};
|
|
|
|
export const SelectSingle = ({
|
|
options,
|
|
onChange,
|
|
value,
|
|
ref,
|
|
keyKey = 'id',
|
|
keyValue = keyKey,
|
|
suggestion,
|
|
onCreate,
|
|
}: SelectSingleProps) => {
|
|
const [showList, setShowList] = useState(false);
|
|
const transformedOption = useMemo(() => {
|
|
return options?.map((element) => {
|
|
return {
|
|
id: element[keyKey],
|
|
name: element[keyValue],
|
|
} as SelectListModel;
|
|
});
|
|
}, [options, keyKey, keyValue]);
|
|
const [hasSuggestion, setHasSuggestion] = useState<boolean>(
|
|
onCreate && suggestion ? true : false
|
|
);
|
|
const [currentSearch, setCurrentSearch] = useState<string | undefined>(
|
|
onCreate ? suggestion : undefined
|
|
);
|
|
useEffect(() => {
|
|
console.log(`Update suggestion : ${onCreate} ${suggestion} ==> ${onCreate ? suggestion : undefined} .. ${onCreate && !isNullOrUndefined(suggestion) ? true : false}`);
|
|
setCurrentSearch(onCreate ? suggestion : undefined);
|
|
setHasSuggestion(onCreate && !isNullOrUndefined(suggestion) ? true : false);
|
|
}, [suggestion]);
|
|
const refFocus = 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?: SelectListModel) => {
|
|
const tmpData = data?.id == selectedOptions?.id ? undefined : data;
|
|
setShowList(false);
|
|
if (onChange) {
|
|
onChange(tmpData?.id);
|
|
}
|
|
};
|
|
if (!transformedOption) {
|
|
return <></>; // TODO: <Spinner />;
|
|
}
|
|
function onChangeInput(value: string): void {
|
|
setHasSuggestion(false);
|
|
if (value === '') {
|
|
setCurrentSearch(undefined);
|
|
} else {
|
|
setCurrentSearch(value);
|
|
}
|
|
}
|
|
const onRemoveItem = () => {
|
|
setHasSuggestion(false);
|
|
if (selectedOptions) {
|
|
if (onChange) {
|
|
onChange(undefined);
|
|
}
|
|
}
|
|
if (!showList || selectedOptions) {
|
|
refFocus?.current?.focus();
|
|
}
|
|
};
|
|
|
|
const createNewItem = !onCreate
|
|
? undefined
|
|
: (data: string) => {
|
|
onCreate(data);
|
|
setCurrentSearch(undefined);
|
|
setHasSuggestion(false);
|
|
};
|
|
|
|
return (
|
|
<Flex direction="column" width="full" gap="0px">
|
|
<Flex>
|
|
<Input
|
|
ref={refFocus}
|
|
style={{
|
|
width: "full",
|
|
backgroundColor: showList || !selectedOptions ? undefined : 'green.500',
|
|
borderRadius: "5px 0 0 5px",
|
|
}}
|
|
onChange={(e) => onChangeInput(e.target.value)}
|
|
//onFocus={() => setShowList(true)}
|
|
//onBlur={() => setTimeout(() => setShowList(false), 200)}
|
|
value={
|
|
showList ? (currentSearch ?? '') : (selectedOptions?.name ?? (hasSuggestion ? `suggest: ${currentSearch}` : ''))
|
|
}
|
|
/>
|
|
<Button
|
|
onClick={onRemoveItem}
|
|
// TODO: variant="outline"
|
|
style={{
|
|
borderRadius: "0 5px 5px 0",
|
|
borderWidth: "1px 1px 1px 0",
|
|
}}
|
|
>
|
|
{
|
|
selectedOptions ? (
|
|
<MdClose color="gray.300" />
|
|
) : showList ? (
|
|
<MdKeyboardArrowUp color="gray.300" />
|
|
) : hasSuggestion ? (
|
|
<MdEdit color="gray.300" />
|
|
) : (
|
|
<MdKeyboardArrowDown color="gray.300" />
|
|
)}
|
|
</Button>
|
|
</Flex>
|
|
{
|
|
showList && (
|
|
<SelectList
|
|
options={transformedOption}
|
|
selected={selectedOptions ? [selectedOptions] : []}
|
|
search={currentSearch}
|
|
onSelectValue={selectValue}
|
|
onCreate={createNewItem}
|
|
/>
|
|
)
|
|
}
|
|
</Flex >
|
|
);
|
|
};
|