95 lines
2.7 KiB
TypeScript

import useOpenable from "@Front/Hooks/useOpenable";
import { useCallback, useEffect, useState } from "react";
import DropdownMenu from "../Dropdown/DropdownMenu";
import { IOption } from "../Dropdown/DropdownMenu/DropdownOption";
import SearchBar from "../SearchBar";
import Typography, { ETypo, ETypoColor } from "../Typography";
import classes from "./classes.module.scss";
import { getLabel } from "../Dropdown";
type IProps = {
options: IOption[];
placeholder?: string;
disabled?: boolean;
label?: string;
onSelectionChange?: (option: IOption | null) => void;
selectedOption?: IOption | null;
};
export default function Autocomplete(props: IProps) {
const { onSelectionChange, options, placeholder, disabled, label, selectedOption: selectedOptionProps } = props;
const [selectedOption, setSelectedOption] = useState<IOption | null>(selectedOptionProps ?? 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()));
console.log(filteredOptions);
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(
(option: IOption | null) => {
setSelectedOption(option);
onSelectionChange?.(option);
},
[onSelectionChange],
);
useEffect(() => {
setSelectedOption(selectedOptionProps ?? null);
}, [selectedOptionProps]);
const handleSelectOption = useCallback(
(newOption: IOption, _options: IOption[]) => {
handleChange(newOption);
setSearchValue(getLabel(newOption) || "");
openable.close();
},
[handleChange, openable],
);
return (
<DropdownMenu
options={filteredOptions}
openable={openable}
onSelect={handleSelectOption}
selectedOptions={selectedOption ? [selectedOption] : []}>
<div className={classes["root"]}>
{label && (
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
{label}
</Typography>
)}
</div>
<SearchBar
placeholder={placeholder}
disabled={disabled}
onChange={handleSearchChange}
value={searchValue}
onClear={() => handleChange(null)}
onFocus={openable.open}
/>
</DropdownMenu>
);
}