76 lines
1.6 KiB
TypeScript
76 lines
1.6 KiB
TypeScript
import React, { useMemo, type ChangeEventHandler } from 'react';
|
|
|
|
export type DataItem = Record<string, any>;
|
|
|
|
interface Props {
|
|
onChange: (value: string | string[] | null) => void;
|
|
data: DataItem[];
|
|
keyData: string;
|
|
isMultiple?: boolean;
|
|
}
|
|
|
|
export default function Select({
|
|
data,
|
|
keyData,
|
|
isMultiple = false,
|
|
onChange,
|
|
}: Props): JSX.Element {
|
|
const options = useMemo(() => {
|
|
let options = [];
|
|
|
|
if (isMultiple) {
|
|
options = data.flatMap((item) => item[keyData]);
|
|
} else {
|
|
options = data.map((item) => item[keyData]);
|
|
}
|
|
|
|
options = [...new Set(options)];
|
|
|
|
options = options.map((item, idx) => (
|
|
<option key={idx} value={item}>
|
|
{item}
|
|
</option>
|
|
));
|
|
|
|
options.unshift(
|
|
<option key={-1} value="">
|
|
Select...
|
|
</option>,
|
|
);
|
|
|
|
return options;
|
|
}, [data, keyData]);
|
|
|
|
const onSelectChange: ChangeEventHandler<HTMLSelectElement> = ({
|
|
target,
|
|
}): void => {
|
|
if (!isMultiple) {
|
|
const value = target.value !== '' ? target.value : null;
|
|
onChange(value);
|
|
return;
|
|
}
|
|
|
|
const values = [];
|
|
|
|
// FIXME: This looks awfull, when updating the input use something better.
|
|
for (let index = 0; index < target.options.length; index++) {
|
|
const option = target.options[index];
|
|
if (!option.selected || option.value === '') continue;
|
|
|
|
values.push(option.value);
|
|
}
|
|
|
|
onChange(values);
|
|
};
|
|
|
|
return (
|
|
<select
|
|
name="fooe"
|
|
id="foo"
|
|
multiple={isMultiple}
|
|
onChange={onSelectChange}
|
|
>
|
|
{options}
|
|
</select>
|
|
);
|
|
}
|