76 lines
1.6 KiB
TypeScript
76 lines
1.6 KiB
TypeScript
import React, { useCallback, useMemo } from "react";
|
|
import Option from "./option";
|
|
import Autocomplete from "./AutoComplete";
|
|
import Pill from "./Pill";
|
|
|
|
interface MultiSelectProps {
|
|
includeLabel?: boolean;
|
|
name: string;
|
|
label: string;
|
|
error?: string;
|
|
|
|
options?: Option[];
|
|
selectedOptions: Option[];
|
|
|
|
onAdd: (item: Option) => void;
|
|
onDelete: (item: Option) => void;
|
|
}
|
|
|
|
const MultiSelect: React.FC<MultiSelectProps> = ({
|
|
includeLabel = true,
|
|
name,
|
|
label,
|
|
error,
|
|
options,
|
|
selectedOptions,
|
|
onAdd,
|
|
onDelete,
|
|
}) => {
|
|
const handleDelete = useCallback(
|
|
(id: string) => {
|
|
const found = options?.find((x) => x._id === id);
|
|
if (found) {
|
|
onDelete(found);
|
|
}
|
|
},
|
|
[options, onDelete],
|
|
);
|
|
|
|
const selectedBlock = useMemo(() => {
|
|
if (selectedOptions.length === 0) return <></>;
|
|
|
|
return (
|
|
<>
|
|
{selectedOptions.map((x) => (
|
|
<Pill
|
|
key={x._id}
|
|
pillKey={x._id}
|
|
displayText={x.name}
|
|
readOnly={false}
|
|
onClick={handleDelete}
|
|
/>
|
|
))}
|
|
</>
|
|
);
|
|
}, [selectedOptions, handleDelete]);
|
|
|
|
return (
|
|
<div className="form-group multiSelect multiSelectContainer">
|
|
{includeLabel && <label htmlFor={name}>{label}</label>}
|
|
|
|
<div className="form-control">
|
|
<Autocomplete
|
|
options={options}
|
|
selectedOptions={selectedOptions}
|
|
onSelect={onAdd}
|
|
/>
|
|
{selectedBlock}
|
|
</div>
|
|
|
|
{error && <div className="alert alert-danger">{error}</div>}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default MultiSelect;
|