nej-react-utils/Form/Core/AutocompleteSelect.js
2024-12-24 00:31:54 +01:00

110 lines
3.5 KiB
JavaScript

import { Combobox } from "@headlessui/react";
import { DropDownItem } from "@shared/nej-react-components/Parts/DropDown";
import { useEffect, useState } from "react";
import tw, { styled } from "twin.macro";
import "styled-components/macro";
import { useField } from "@shared/nej-react-components/Parts/Input";
export function AutocompleteSelect({ title, titleProps = null, data, nullable = false, ...props }) {
const [field, meta, helpers] = useField(props);
const [query, setQuery] = useState(field.value ?? "");
const [internalData, setInternalData] = useState([]);
useEffect(() => {
(async () => {
if (typeof data === "function") {
//if data is async function await it
setInternalData(await data(query));
} else if (Array.isArray(data)) {
setInternalData(
query === ""
? data
: data.filter((item) => {
if (typeof item === "string")
return item.toLowerCase().includes(query.toLowerCase());
return item.label.toLowerCase().includes(query.toLowerCase());
})
);
} else if(typeof data === "object")
{
setInternalData(Object.values(data).map((value) => {
return {
value: value,
label: value
};
}));
}
else {
console.error("data is not an array or function :c");
setInternalData([]);
}
})();
}, [query, data]);
return (
<>
<Combobox
{...props}
{...field}
value={
field.value
? internalData?.filter((item) =>
typeof item === "string"
? item == field.value
: item.value === field.value
)[0]
: null
}
onChange={(value) => {
console.log(value);
field.onChange({ target: { value: value, name: field.name } });
}}
nullable={nullable}
>
<div css={[title && tw`my-1`, tw`relative`]} >
{title && (
<label
{...titleProps}
css={[
tw`block text-secondary text-sm font-bold mb-2`,
titleProps?.css,
]}
>
{title}
</label>
)}
<div tw="relative">
<Combobox.Input
tw="bg-primary cursor-pointer appearance-none border-2 border-secondary rounded w-full py-2 px-4 text-primary leading-tight focus:outline-none focus:bg-secondary focus:border-accent transition duration-150 "
onChange={(event) => setQuery(event.target.value)}
displayValue={(val) => (typeof val === "string" ? val : val?.label)}
/>
<Combobox.Button tw="absolute top-0 right-0 left-0 bottom-0 " />
</div>
<Combobox.Options tw="absolute z-10 max-h-60 w-full bg-trinary rounded-xl overflow-y-auto overflow-x-hidden">
{internalData?.map((val) => (
<Combobox.Option
tw=""
key={typeof val === "string" ? val : val.value}
value={typeof val === "string" ? val : val.value}
>
<DropDownItem>
{typeof val === "string" ? val : val.label}
</DropDownItem>
</Combobox.Option>
))}
</Combobox.Options>
</div>
</Combobox>
{meta?.touched && meta.error ? (
<div tw="text-[#c23c3c]">{meta.error}</div>
) : null}
</>
);
}