Compare commits
2 Commits
c6a223d444
...
57a30a1cc3
Author | SHA1 | Date | |
---|---|---|---|
57a30a1cc3 | |||
188925380b |
@ -1,12 +1,7 @@
|
||||
import { ReactElement, ReactNode } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { Button, Flex, IconButton, Text, Tooltip } from '@chakra-ui/react';
|
||||
import {
|
||||
MdErrorOutline,
|
||||
MdHelpOutline,
|
||||
MdLabelImportant,
|
||||
MdRefresh,
|
||||
} from 'react-icons/md';
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { MdErrorOutline, MdHelpOutline, MdRefresh } from 'react-icons/md';
|
||||
|
||||
export type FormGroupProps = {
|
||||
error?: ReactNode;
|
||||
|
37
front2/src/components/form/FormInput.tsx
Normal file
37
front2/src/components/form/FormInput.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import { Input } from '@chakra-ui/react';
|
||||
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { UseFormidableReturn } from '@/components/form/Formidable';
|
||||
|
||||
export type FormInputProps = {
|
||||
form: UseFormidableReturn;
|
||||
variableName: string;
|
||||
ref?: RefObject<any>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
isRequired?: boolean;
|
||||
};
|
||||
|
||||
export const FormInput = ({
|
||||
form,
|
||||
variableName,
|
||||
ref,
|
||||
placeholder,
|
||||
...rest
|
||||
}: FormInputProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
isModify={form.isModify[variableName]}
|
||||
onRestore={() => form.restoreValue({ [variableName]: true })}
|
||||
{...rest}
|
||||
>
|
||||
<Input
|
||||
ref={ref}
|
||||
value={form.values[variableName]}
|
||||
onChange={(e) => form.setValues({ [variableName]: e.target.value })}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
62
front2/src/components/form/FormNumber.tsx
Normal file
62
front2/src/components/form/FormNumber.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import {
|
||||
Input,
|
||||
NumberDecrementStepper,
|
||||
NumberIncrementStepper,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputProps,
|
||||
NumberInputStepper,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { UseFormidableReturn } from '@/components/form/Formidable';
|
||||
|
||||
export type FormNumberProps = Pick<
|
||||
NumberInputProps,
|
||||
'step' | 'defaultValue' | 'min' | 'max'
|
||||
> & {
|
||||
form: UseFormidableReturn;
|
||||
variableName: string;
|
||||
ref?: RefObject<any>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
isRequired?: boolean;
|
||||
};
|
||||
|
||||
export const FormNumber = ({
|
||||
form,
|
||||
variableName,
|
||||
ref,
|
||||
placeholder,
|
||||
step,
|
||||
min,
|
||||
max,
|
||||
defaultValue,
|
||||
...rest
|
||||
}: FormNumberProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
isModify={form.isModify[variableName]}
|
||||
onRestore={() => form.restoreValue({ [variableName]: true })}
|
||||
{...rest}
|
||||
>
|
||||
<NumberInput
|
||||
ref={ref}
|
||||
value={form.values[variableName]}
|
||||
onChange={(_, value) => form.setValues({ [variableName]: value })}
|
||||
step={step}
|
||||
defaultValue={defaultValue}
|
||||
min={min}
|
||||
max={max}
|
||||
>
|
||||
<NumberInputField />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
42
front2/src/components/form/FormSelect.tsx
Normal file
42
front2/src/components/form/FormSelect.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { UseFormidableReturn } from '@/components/form/Formidable';
|
||||
import { SelectSingle } from '@/components/select/SelectSingle';
|
||||
|
||||
export type FormSelectProps = {
|
||||
form: UseFormidableReturn;
|
||||
variableName: string;
|
||||
ref?: RefObject<any>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
isRequired?: boolean;
|
||||
options?: object[];
|
||||
keyInputValue?: string;
|
||||
};
|
||||
|
||||
export const FormSelect = ({
|
||||
form,
|
||||
variableName,
|
||||
ref,
|
||||
placeholder,
|
||||
options,
|
||||
keyInputValue = 'name',
|
||||
...rest
|
||||
}: FormSelectProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
isModify={form.isModify[variableName]}
|
||||
onRestore={() => form.restoreValue({ [variableName]: true })}
|
||||
{...rest}
|
||||
>
|
||||
<SelectSingle
|
||||
ref={ref}
|
||||
value={form.values[variableName]}
|
||||
options={options}
|
||||
onChange={(value) => form.setValues({ [variableName]: value })}
|
||||
keyValue={keyInputValue}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
42
front2/src/components/form/FormSelectMultiple.tsx
Normal file
42
front2/src/components/form/FormSelectMultiple.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { UseFormidableReturn } from '@/components/form/Formidable';
|
||||
import { SelectMultiple } from '@/components/select/SelectMultiple';
|
||||
|
||||
export type FormSelectMultipleProps = {
|
||||
form: UseFormidableReturn;
|
||||
variableName: string;
|
||||
ref?: RefObject<any>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
isRequired?: boolean;
|
||||
options?: object[];
|
||||
keyInputValue?: string;
|
||||
};
|
||||
|
||||
export const FormSelectMultiple = ({
|
||||
form,
|
||||
variableName,
|
||||
ref,
|
||||
placeholder,
|
||||
options,
|
||||
keyInputValue = 'name',
|
||||
...rest
|
||||
}: FormSelectMultipleProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
isModify={form.isModify[variableName]}
|
||||
onRestore={() => form.restoreValue({ [variableName]: true })}
|
||||
{...rest}
|
||||
>
|
||||
<SelectMultiple
|
||||
//ref={ref}
|
||||
values={form.values[variableName]}
|
||||
options={options}
|
||||
onChange={(value) => form.setValues({ [variableName]: value })}
|
||||
keyValue={keyInputValue}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
37
front2/src/components/form/FormTextarea.tsx
Normal file
37
front2/src/components/form/FormTextarea.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { RefObject } from 'react';
|
||||
|
||||
import { Textarea } from '@chakra-ui/react';
|
||||
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { UseFormidableReturn } from '@/components/form/Formidable';
|
||||
|
||||
export type FormTextareaProps = {
|
||||
form: UseFormidableReturn;
|
||||
variableName: string;
|
||||
ref?: RefObject<any>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
isRequired?: boolean;
|
||||
};
|
||||
|
||||
export const FormTextarea = ({
|
||||
form,
|
||||
variableName,
|
||||
ref,
|
||||
placeholder,
|
||||
...rest
|
||||
}: FormTextareaProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
isModify={form.isModify[variableName]}
|
||||
onRestore={() => form.restoreValue({ [variableName]: true })}
|
||||
{...rest}
|
||||
>
|
||||
<Textarea
|
||||
ref={ref}
|
||||
value={form.values[variableName]}
|
||||
onChange={(e) => form.setValues({ [variableName]: e.target.value })}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
@ -62,9 +62,7 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
}) => {
|
||||
const [values, setValues] = useState<TYPE>({ ...initialValues } as TYPE);
|
||||
const [initialData, setInitialData] = useState<TYPE>(initialValues);
|
||||
const [valueChange, setValueChange] = useState<{ [key: string]: boolean }>(
|
||||
{}
|
||||
);
|
||||
const [isModify, setIsModify] = useState<{ [key: string]: boolean }>({});
|
||||
const [isFormModified, setIsFormModified] = useState<boolean>(false);
|
||||
useEffect(() => {
|
||||
setInitialData((previous) => {
|
||||
@ -77,7 +75,7 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
//console.log(`FORMIDABLE: ==> update new values`);
|
||||
setValues({ ...initialValues });
|
||||
const ret = getDifferences(initialValues, initialValues);
|
||||
setValueChange(ret);
|
||||
setIsModify(ret);
|
||||
setIsFormModified(hasAnyTrue(ret));
|
||||
return initialValues;
|
||||
});
|
||||
@ -85,7 +83,7 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
initialValues,
|
||||
setInitialData,
|
||||
setValues,
|
||||
setValueChange,
|
||||
setIsModify,
|
||||
setIsFormModified,
|
||||
]);
|
||||
const setValuesExternal = useCallback(
|
||||
@ -94,7 +92,7 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
setValues((previous) => {
|
||||
const newValues = { ...previous, ...data };
|
||||
const ret = getDifferences(initialData, newValues);
|
||||
setValueChange(ret);
|
||||
setIsModify(ret);
|
||||
setIsFormModified(hasAnyTrue(ret));
|
||||
return newValues;
|
||||
});
|
||||
@ -124,21 +122,21 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
//console.log(`initialData data ${JSON.stringify(initialData, null, 2)}`);
|
||||
//console.log(`New data ${JSON.stringify(newValue, null, 2)}`);
|
||||
const ret = getDifferences(initialData, newValue);
|
||||
setValueChange(ret);
|
||||
setIsModify(ret);
|
||||
setIsFormModified(hasAnyTrue(ret));
|
||||
return newValue;
|
||||
});
|
||||
},
|
||||
[setValues, initialData, setIsFormModified, setValueChange]
|
||||
[setValues, initialData, setIsFormModified, setIsModify]
|
||||
);
|
||||
const getDeltaData = useCallback(
|
||||
({ omit = [], only }: { omit?: string[]; only?: string[] }) => {
|
||||
const out = {};
|
||||
Object.keys(valueChange).forEach((key) => {
|
||||
Object.keys(isModify).forEach((key) => {
|
||||
if (omit.includes(key) || (only && !only.includes(key))) {
|
||||
return;
|
||||
}
|
||||
if (!valueChange[key]) {
|
||||
if (!isModify[key]) {
|
||||
return;
|
||||
}
|
||||
const tmpValue = values[key];
|
||||
@ -150,14 +148,16 @@ export const useFormidable = <TYPE extends object = object>({
|
||||
});
|
||||
return out;
|
||||
},
|
||||
[valueChange, values]
|
||||
[isModify, values]
|
||||
);
|
||||
return {
|
||||
values,
|
||||
valueChange,
|
||||
isModify,
|
||||
isFormModified,
|
||||
setValues: setValuesExternal,
|
||||
getDeltaData,
|
||||
restoreValue,
|
||||
};
|
||||
};
|
||||
|
||||
export type UseFormidableReturn = ReturnType<typeof useFormidable>;
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
AlertDialogOverlay,
|
||||
Button,
|
||||
UseDisclosureReturn,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
export type ConfirmPopUpProps = {
|
||||
|
@ -30,10 +30,15 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import { Track, TrackResource } from '@/back-api';
|
||||
import { FormGroup } from '@/components/form/FormGroup';
|
||||
import { FormInput } from '@/components/form/FormInput';
|
||||
import { FormNumber } from '@/components/form/FormNumber';
|
||||
import { FormSelect } from '@/components/form/FormSelect';
|
||||
import { FormSelectMultiple } from '@/components/form/FormSelectMultiple';
|
||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
||||
import { useFormidable } from '@/components/form/Formidable';
|
||||
import { SelectMultiple } from '@/components/form/SelectMultiple';
|
||||
import { SelectSingle } from '@/components/form/SelectSingle';
|
||||
import { ConfirmPopUp } from '@/components/popup/ConfirmPopUp';
|
||||
import { SelectMultiple } from '@/components/select/SelectMultiple';
|
||||
import { SelectSingle } from '@/components/select/SelectSingle';
|
||||
import { useOrderedAlbums } from '@/service/Album';
|
||||
import { useOrderedArtists } from '@/service/Artist';
|
||||
import { useOrderedGenders } from '@/service/Gender';
|
||||
@ -142,87 +147,45 @@ export const TrackEditPopUp = ({}: TrackEditPopUpProps) => {
|
||||
)}
|
||||
{!admin && (
|
||||
<>
|
||||
<FormGroup
|
||||
<FormInput
|
||||
form={form}
|
||||
variableName="name"
|
||||
isRequired
|
||||
isModify={form.valueChange.name}
|
||||
onRestore={() => form.restoreValue({ name: true })}
|
||||
label="Title"
|
||||
>
|
||||
<Input
|
||||
ref={initialRef}
|
||||
value={form.values.name}
|
||||
onChange={(e) => form.setValues({ name: e.target.value })}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
isModify={form.valueChange.description}
|
||||
onRestore={() => form.restoreValue({ description: true })}
|
||||
ref={initialRef}
|
||||
/>
|
||||
<FormTextarea
|
||||
form={form}
|
||||
variableName="description"
|
||||
label="Description"
|
||||
>
|
||||
<Textarea
|
||||
value={form.values.description}
|
||||
onChange={(e) =>
|
||||
form.setValues({ description: e.target.value })
|
||||
}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
isModify={form.valueChange.genderId}
|
||||
onRestore={() => form.restoreValue({ genderId: true })}
|
||||
/>
|
||||
<FormSelect
|
||||
form={form}
|
||||
variableName="genderId"
|
||||
options={dataGenders}
|
||||
label="Gender"
|
||||
>
|
||||
<SelectSingle
|
||||
value={form.values.genderId}
|
||||
options={dataGenders}
|
||||
onChange={(value) => form.setValues({ genderId: value })}
|
||||
keyValue="name"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
isModify={form.valueChange.artists}
|
||||
onRestore={() => form.restoreValue({ artists: true })}
|
||||
/>
|
||||
<FormSelectMultiple
|
||||
form={form}
|
||||
variableName="artists"
|
||||
options={dataArtist}
|
||||
label="Artist(s)"
|
||||
>
|
||||
<SelectMultiple
|
||||
values={form.values.artists}
|
||||
options={dataArtist}
|
||||
onChange={(value) => form.setValues({ artists: value })}
|
||||
keyValue="name"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
isModify={form.valueChange.albumId}
|
||||
onRestore={() => form.restoreValue({ albumId: true })}
|
||||
/>
|
||||
<FormSelect
|
||||
form={form}
|
||||
variableName="albumId"
|
||||
options={dataAlbums}
|
||||
label="Album"
|
||||
>
|
||||
<SelectSingle
|
||||
value={form.values.albumId}
|
||||
options={dataAlbums}
|
||||
onChange={(value) => form.setValues({ albumId: value })}
|
||||
keyValue="name"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
isModify={form.valueChange.track}
|
||||
onRestore={() => form.restoreValue({ track: true })}
|
||||
/>
|
||||
<FormNumber
|
||||
form={form}
|
||||
variableName="track"
|
||||
label="Track n°"
|
||||
>
|
||||
<NumberInput
|
||||
value={form.values.track}
|
||||
onChange={(_, value) => form.setValues({ track: value })}
|
||||
step={1}
|
||||
defaultValue={0}
|
||||
min={0}
|
||||
max={1000}
|
||||
>
|
||||
<NumberInputField />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
</FormGroup>
|
||||
step={1}
|
||||
defaultValue={0}
|
||||
min={0}
|
||||
max={1000}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</ModalBody>
|
||||
|
@ -4,21 +4,21 @@ import { Box, Button, Flex, Text } from '@chakra-ui/react';
|
||||
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
|
||||
export type SelectMultipleValueDisplayType = {
|
||||
export type SelectListModel = {
|
||||
id: any;
|
||||
name: any;
|
||||
isSelected: boolean;
|
||||
isSelected?: boolean;
|
||||
};
|
||||
|
||||
const optionToOptionDisplay = (
|
||||
data: SelectMultipleValueDisplayType[] | undefined,
|
||||
selectedOptions: SelectMultipleValueDisplayType[],
|
||||
data: SelectListModel[] | undefined,
|
||||
selectedOptions: SelectListModel[],
|
||||
search?: string
|
||||
): SelectMultipleValueDisplayType[] => {
|
||||
): SelectListModel[] => {
|
||||
if (isNullOrUndefined(data)) {
|
||||
return [];
|
||||
}
|
||||
const out: SelectMultipleValueDisplayType[] = [];
|
||||
const out: SelectListModel[] = [];
|
||||
data.forEach((element) => {
|
||||
if (search) {
|
||||
if (!element.name.toLowerCase().includes(search.toLowerCase())) {
|
||||
@ -34,18 +34,18 @@ const optionToOptionDisplay = (
|
||||
return out;
|
||||
};
|
||||
|
||||
export type FormSelectListProps = {
|
||||
options?: SelectMultipleValueDisplayType[];
|
||||
selected: SelectMultipleValueDisplayType[];
|
||||
onSelectValue: (data: SelectMultipleValueDisplayType) => void;
|
||||
export type SelectListProps = {
|
||||
options?: SelectListModel[];
|
||||
selected: SelectListModel[];
|
||||
onSelectValue: (data: SelectListModel) => void;
|
||||
search?: string;
|
||||
};
|
||||
export const FormSelectList = ({
|
||||
export const SelectList = ({
|
||||
options,
|
||||
selected,
|
||||
onSelectValue,
|
||||
search,
|
||||
}: FormSelectListProps) => {
|
||||
}: SelectListProps) => {
|
||||
const displayedValue = optionToOptionDisplay(options, selected, search);
|
||||
const scrollToRef = useRef<HTMLButtonElement | null>(null);
|
||||
useEffect(() => {
|
@ -1,10 +1,9 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { RefObject, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputRightElement,
|
||||
Spinner,
|
||||
Tag,
|
||||
TagCloseButton,
|
||||
@ -12,12 +11,9 @@ import {
|
||||
Wrap,
|
||||
WrapItem,
|
||||
} from '@chakra-ui/react';
|
||||
import { MdSearch } from 'react-icons/md';
|
||||
import { MdKeyboardArrowDown, MdKeyboardArrowUp } from 'react-icons/md';
|
||||
|
||||
import {
|
||||
FormSelectList,
|
||||
SelectMultipleValueDisplayType,
|
||||
} from '@/components/form/FormSelectList';
|
||||
import { SelectList, SelectListModel } from '@/components/select/SelectList';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
|
||||
export type SelectMultipleProps = {
|
||||
@ -26,12 +22,14 @@ export type SelectMultipleProps = {
|
||||
onChange?: (value: (number | string)[] | undefined) => void;
|
||||
keyKey?: string;
|
||||
keyValue?: string;
|
||||
ref?: RefObject<any>;
|
||||
};
|
||||
|
||||
export const SelectMultiple = ({
|
||||
options,
|
||||
onChange,
|
||||
values,
|
||||
ref,
|
||||
keyKey = 'id',
|
||||
keyValue = keyKey,
|
||||
}: SelectMultipleProps) => {
|
||||
@ -41,14 +39,14 @@ export const SelectMultiple = ({
|
||||
return {
|
||||
id: element[keyKey],
|
||||
name: element[keyValue],
|
||||
isSelected: false,
|
||||
} as SelectMultipleValueDisplayType;
|
||||
} as SelectListModel;
|
||||
});
|
||||
}, [options, keyKey, keyValue]);
|
||||
const [currentSearch, setCurrentSearch] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const refFocus = ref ?? useRef<HTMLInputElement | null>(null);
|
||||
const selectedOptions = useMemo(() => {
|
||||
if (isNullOrUndefined(values) || !transformedOption) {
|
||||
return [];
|
||||
@ -58,7 +56,7 @@ export const SelectMultiple = ({
|
||||
});
|
||||
}, [values, transformedOption]);
|
||||
|
||||
const selectValue = (data: SelectMultipleValueDisplayType) => {
|
||||
const selectValue = (data: SelectListModel) => {
|
||||
const newValues = values?.includes(data.id)
|
||||
? values.filter((elem) => data.id !== elem)
|
||||
: [...(values ?? []), data.id];
|
||||
@ -74,13 +72,19 @@ export const SelectMultiple = ({
|
||||
if (!options) {
|
||||
return <Spinner />;
|
||||
}
|
||||
function onChangeInput(value: string): void {
|
||||
const onChangeInput = (value: string): void => {
|
||||
if (value === '') {
|
||||
setCurrentSearch(undefined);
|
||||
} else {
|
||||
setCurrentSearch(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
const onOpenClose = () => {
|
||||
if (!showList) {
|
||||
refFocus?.current?.focus();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column" width="full" gap="0px">
|
||||
@ -102,19 +106,33 @@ export const SelectMultiple = ({
|
||||
))}
|
||||
</Wrap>
|
||||
)}
|
||||
<InputGroup minWidth="50%" marginLeft="auto">
|
||||
<InputRightElement pointerEvents="none">
|
||||
<MdSearch color="gray.300" />
|
||||
</InputRightElement>
|
||||
|
||||
<Flex>
|
||||
<Input
|
||||
ref={refFocus}
|
||||
width="full"
|
||||
onChange={(e) => onChangeInput(e.target.value)}
|
||||
//onSubmit={onSubmit}
|
||||
onFocus={() => setShowList(true)}
|
||||
onBlur={() => setTimeout(() => setShowList(false), 200)}
|
||||
value={showList ? (currentSearch ?? '') : ''}
|
||||
borderRadius="5px 0 0 5px"
|
||||
/>
|
||||
</InputGroup>
|
||||
<Button
|
||||
onClick={onOpenClose}
|
||||
variant="outline"
|
||||
borderRadius="0 5px 5px 0"
|
||||
borderWidth="1px 1px 1px 0"
|
||||
>
|
||||
{showList ? (
|
||||
<MdKeyboardArrowUp color="gray.300" />
|
||||
) : (
|
||||
<MdKeyboardArrowDown color="gray.300" />
|
||||
)}
|
||||
</Button>
|
||||
</Flex>
|
||||
{showList && (
|
||||
<FormSelectList
|
||||
<SelectList
|
||||
options={transformedOption}
|
||||
selected={selectedOptions}
|
||||
search={currentSearch}
|
@ -1,29 +1,13 @@
|
||||
import { useMemo, useRef, useState } from 'react';
|
||||
import { RefObject, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputRightElement,
|
||||
Spinner,
|
||||
Tag,
|
||||
TagCloseButton,
|
||||
TagLabel,
|
||||
} from '@chakra-ui/react';
|
||||
import { Button, Flex, Input, Spinner } from '@chakra-ui/react';
|
||||
import {
|
||||
MdClose,
|
||||
MdKeyboardArrowDown,
|
||||
MdKeyboardArrowUp,
|
||||
MdSearch,
|
||||
} from 'react-icons/md';
|
||||
|
||||
import {
|
||||
FormSelectList,
|
||||
SelectMultipleValueDisplayType,
|
||||
} from '@/components/form/FormSelectList';
|
||||
import { SelectList, SelectListModel } from '@/components/select/SelectList';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
|
||||
export type SelectSingleProps = {
|
||||
@ -32,12 +16,14 @@ export type SelectSingleProps = {
|
||||
onChange?: (value: number | string | undefined) => void;
|
||||
keyKey?: string;
|
||||
keyValue?: string;
|
||||
ref?: RefObject<any>;
|
||||
};
|
||||
|
||||
export const SelectSingle = ({
|
||||
options,
|
||||
onChange,
|
||||
value,
|
||||
ref,
|
||||
keyKey = 'id',
|
||||
keyValue = keyKey,
|
||||
}: SelectSingleProps) => {
|
||||
@ -47,14 +33,13 @@ export const SelectSingle = ({
|
||||
return {
|
||||
id: element[keyKey],
|
||||
name: element[keyValue],
|
||||
isSelected: false,
|
||||
} as SelectMultipleValueDisplayType;
|
||||
} as SelectListModel;
|
||||
});
|
||||
}, [options, keyKey, keyValue]);
|
||||
const [currentSearch, setCurrentSearch] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
const ref = useRef<HTMLInputElement | null>(null);
|
||||
const refFocus = ref ?? useRef<HTMLInputElement | null>(null);
|
||||
const selectedOptions = useMemo(() => {
|
||||
if (isNullOrUndefined(value)) {
|
||||
return undefined;
|
||||
@ -62,7 +47,7 @@ export const SelectSingle = ({
|
||||
return transformedOption?.find((data) => data.id === value);
|
||||
}, [value, transformedOption]);
|
||||
|
||||
const selectValue = (data?: SelectMultipleValueDisplayType) => {
|
||||
const selectValue = (data?: SelectListModel) => {
|
||||
const tmpData = data?.id == selectedOptions?.id ? undefined : data;
|
||||
setShowList(false);
|
||||
if (onChange) {
|
||||
@ -80,13 +65,13 @@ export const SelectSingle = ({
|
||||
}
|
||||
}
|
||||
const onRemoveItem = () => {
|
||||
if (showList || !selectedOptions) {
|
||||
ref?.current?.focus();
|
||||
return;
|
||||
if (selectedOptions) {
|
||||
if (onChange) {
|
||||
onChange(undefined);
|
||||
}
|
||||
}
|
||||
console.log('Remove item ...');
|
||||
if (onChange) {
|
||||
onChange(undefined);
|
||||
if (!showList || selectedOptions) {
|
||||
refFocus?.current?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
@ -94,7 +79,7 @@ export const SelectSingle = ({
|
||||
<Flex direction="column" width="full" gap="0px">
|
||||
<Flex>
|
||||
<Input
|
||||
ref={ref}
|
||||
ref={refFocus}
|
||||
width="full"
|
||||
onChange={(e) => onChangeInput(e.target.value)}
|
||||
//onSubmit={onSubmit}
|
||||
@ -113,7 +98,6 @@ export const SelectSingle = ({
|
||||
variant="outline"
|
||||
borderRadius="0 5px 5px 0"
|
||||
borderWidth="1px 1px 1px 0"
|
||||
isDisabled={showList}
|
||||
>
|
||||
{selectedOptions ? (
|
||||
<MdClose color="gray.300" />
|
||||
@ -125,7 +109,7 @@ export const SelectSingle = ({
|
||||
</Button>
|
||||
</Flex>
|
||||
{showList && (
|
||||
<FormSelectList
|
||||
<SelectList
|
||||
options={transformedOption}
|
||||
selected={selectedOptions ? [selectedOptions] : []}
|
||||
search={currentSearch}
|
Loading…
x
Reference in New Issue
Block a user