96 lines
2.8 KiB
TypeScript

import useOpenable from "@Front/Hooks/useOpenable";
import { useCallback, useEffect, useState } from "react";
import { getLabel } from "../Dropdown";
import DropdownMenu from "../Dropdown/DropdownMenu";
import { IOption } from "../Dropdown/DropdownMenu/DropdownOption";
import Typography, { ETypo, ETypoColor } from "../Typography";
import ChipContainer from "./ChipContainer";
import classes from "./classes.module.scss";
type IProps = {
options: IOption[];
placeholder?: string;
disabled?: boolean;
label?: string;
onSelectionChange?: (options: IOption[] | null) => void;
selectedOptions?: IOption[] | null;
};
export default function AutocompleteMultiSelect(props: IProps) {
const { onSelectionChange, options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props;
const [selectedOptions, setSelectedOptions] = useState<IOption[] | null>(selectedOptionsProps ?? null);
const [searchValue, setSearchValue] = useState("");
const [filteredOptions, setFilteredOptions] = useState<IOption[]>(options);
const openable = useOpenable({ defaultOpen: false });
useEffect(() => {
if (searchValue) {
const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase()));
if (filteredOptions.length === 0)
return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]);
return setFilteredOptions(filteredOptions);
}
return setFilteredOptions(options);
}, [searchValue, options]);
const handleSearchChange = useCallback(
(value: string) => {
setSearchValue(value);
if (value) {
openable.open();
} else {
openable.close();
}
},
[openable],
);
const handleChange = useCallback(
(options: IOption[] | null) => {
setSelectedOptions(options);
onSelectionChange?.(options);
},
[onSelectionChange],
);
useEffect(() => {
setSelectedOptions(selectedOptionsProps ?? null);
}, [selectedOptionsProps]);
const handleSelectOption = useCallback(
(_newOption: IOption, options: IOption[]) => {
handleChange(options);
setSearchValue("");
openable.close();
},
[handleChange, openable],
);
return (
<DropdownMenu
options={filteredOptions}
openable={openable}
onSelect={handleSelectOption}
selectedOptions={selectedOptions ? selectedOptions : []}>
<div className={classes["root"]}>
{label && (
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
{label}
</Typography>
)}
</div>
<ChipContainer
placeholder={placeholder}
disabled={disabled}
onChange={handleSearchChange}
value={searchValue}
onClear={() => handleChange(null)}
onFocus={openable.open}
selectedOptions={selectedOptions ?? []}
onSelectedOptionsChange={handleChange}
/>
</DropdownMenu>
);
}