import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { Autocomplete, Box, Checkbox, Popper, styled, TextField, Tooltip, Typography } from "@mui/material";
import { DataContext } from "../../context/Context";
import ComponentWrapper from "../../common/ComponentWrapper";
import { getFieldName } from "../../permissions/getFieldName";
import { inputProps } from "../../interface/inputfieldProps";
import { getComponentProps, getSchemaProps } from "../../common/getComponentProps";
import _ from "lodash";
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
import CheckBoxIcon from "@mui/icons-material/CheckBox";
import MultiSelectSearchPanel from "./MultiSelectSearchPanel";
import { useJsonForms } from "@jsonforms/react";
const StyledAutocompletePopper = styled("div")(({ theme, style }: { theme: any, style: any }) => ({
...theme.AutoCompleteStyle,
...style
}));
const CustomPopper = (props: any) => {
const { theme, style, anchorEl, ...other } = props;
return (
);
};
export const ImpaktAppsAutoComplete = memo(function CustomAutoComplete(
props: inputProps | any
) {
const {
errors,
uischema,
rootSchema,
data,
required,
handleChange,
path,
schema,
options,
} = props.props;
const uischemaData = uischema?.config?.main;
const { pageName, permissions, theme, setSchema, serviceProvider } =
useContext(DataContext);
const ctx = useJsonForms();
const dynamicStyle = useMemo(() => {
return serviceProvider(
ctx,
{
onClick: uischema.config?.main?.styleFunction || 'getStyle',
},
{
event: { _reactName: 'onClick' },
path,
},
);
}, [data, path]);
const componentStyle = useMemo(
() => ({ ...uischema.config?.style, ...dynamicStyle }),
[uischema.config?.style, dynamicStyle]
);
const fieldName = getFieldName(path);
const [changeState, setChangeState] = useState("");
const [selectOptions, setSelectOptions] = useState(
options || uischemaData.options || []
);
const [value, setValue] = useState(uischemaData.multiple ? [] : "");
const [open, setOpen] = useState(false);
const [dropdownSearch, setDropdownSearch] = useState("");
const isDisabled = getSchemaProps(schema, rootSchema).disabled;
const inputRef = useRef(null);
const handleRemoveChip = useCallback(
(val: any) => {
setValue((prev: any[]) => {
const next = prev.filter((option) => option.value !== val);
handleChange(path, next.length === 0 ? undefined : next.map((e) => e?.value));
return next;
});
setTimeout(() => inputRef.current?.focus(), 0);
},
[handleChange, path]
);
const PopperSlot = useMemo(
() => (props: any) => (
),
[componentStyle?.AutoCompleteStyle]
);
const triggerDisplayValue = useMemo(() => {
if (!uischemaData.multiple) return undefined;
if (!Array.isArray(value) || value.length === 0) return "";
if (value.length === 1) return value[0]?.label ?? "";
return `${value.length} selected`;
}, [uischemaData.multiple, value]);
const MultiSelectDropdownPanelProps = useMemo(
() => ({
selectedOptions: Array.isArray(value) ? value : [],
searchValue: dropdownSearch,
onSearchChange: setDropdownSearch,
searchPlaceholder: uischemaData?.searchPlaceholder,
onRemoveChip: handleRemoveChip,
styleConfig: componentStyle,
isDisabled,
appTheme: theme
}),
[value, dropdownSearch, uischemaData?.searchPlaceholder, handleRemoveChip, componentStyle, isDisabled, theme]
);
const filteredSelectOptions = useMemo(() => {
if (uischemaData.lazyLoading) return selectOptions;
if (!uischemaData.multiple || !dropdownSearch) return selectOptions;
return selectOptions.filter((opt: any) =>
opt.label?.toLowerCase().includes(dropdownSearch.toLowerCase())
);
}, [selectOptions, dropdownSearch, uischemaData.multiple]);
useEffect(() => {
setSelectOptions(options || []);
}, [options]);
useEffect(() => {
updateFreeSoloOptions();
}, []);
function updateFreeSoloOptions() {
if (uischemaData.freeSolo && !uischemaData.lazyLoading && data) {
// let Updatedresponse = [{const:data||"",title:data||""}];
if (options) {
const OptionsClone = _.cloneDeep(options);
const updatedOptions = OptionsClone?.map((e: any) => {
return { const: e.value, title: e.label };
});
const filterResult = updatedOptions.filter((e) => {
return e.const === data;
});
if (filterResult.length > 0) {
return;
}
updatedOptions.push({ const: data || "", title: data || "" });
updateSchema({
options,
response: updatedOptions,
setSchema,
path,
uischemaData,
});
} else {
updateSchema({
options,
response: [{ const: data || "", title: data || "" }],
setSchema,
path,
uischemaData,
});
}
}
}
const debouncedFunction = useMemo(
() =>
_.debounce((value: string, currentData: any) => {
serviceProvider(
props.ctx,
{
...uischemaData,
onInputChange: uischemaData.lazyLoadFunction || "getSelectOptions",
},
{
event: { _reactName: "onInputChange" },
path,
...uischemaData.additionalData,
paramValue: {
path,
serachValue: value,
currentValue: currentData,
},
}
).then((response: any) => {
if (response) {
if (uischemaData.freeSolo) {
response[response.length] = { const: changeState, title: changeState };
}
updateSchema({ options, response, setSchema, path, uischemaData });
const filteredOptions = [];
response.forEach((e) => {
if (!data?.includes(e?.const)) {
filteredOptions.push({ label: e.title, value: e.const });
}
});
setSelectOptions(filteredOptions);
}
});
}, 1000),
[changeState, uischemaData, serviceProvider, path, options, setSchema, props.ctx, data]
);
useEffect(() => {
if (!uischemaData.lazyLoading) return;
debouncedFunction(dropdownSearch, data);
}, [dropdownSearch]);
const findOptions = () => {
const value = data
? uischemaData.multiple
? options?.filter((o) => data.includes(o.value)) ?? []
: options?.find((o) => o.value === data) ?? data
: uischemaData.multiple
? []
: "";
setValue(value);
};
useEffect(() => {
if (options) {
findOptions();
}
}, [options, data]);
const computedProps = getComponentProps(
`${pageName}:${fieldName}`,
permissions,
schema,
rootSchema
);
return (
{
if (!uischemaData.multiple) return;
if (!e.currentTarget.contains(e.relatedTarget as Node)) {
setOpen(false);
setDropdownSearch("");
}
}}
>
setOpen(true) : undefined}
onClose={uischemaData.multiple ? () => {} : undefined}
openOnFocus={uischemaData.multiple ? false : undefined}
clearOnBlur={uischemaData.multiple ? false : undefined}
disabled={isDisabled && !uischemaData.multiple}
onChange={(event, newValue: any) => {
if (uischemaData.multiple) {
if(isDisabled) return;
if (newValue.length === 0) {
handleChange(path, undefined);
} else {
handleChange(
path,
newValue.map((e) => e?.value || e)
);
}
} else {
handleChange(path, newValue === null ? undefined : newValue.value);
}
}}
filterOptions={uischemaData.lazyLoading ? (option) => option : undefined}
onInputChange={(event, newInputValue) => {
if (uischemaData.multiple) return;
if (uischemaData.lazyLoading) setDropdownSearch(newInputValue);
}}
onMouseLeave={() => updateFreeSoloOptions()}
// placeholder={uischemaData.placeholder}
sx={{
...theme.InputFieldStyle,
...(computedProps.disabled && {
'& .MuiOutlinedInput-root.Mui-disabled': {
borderRadius: '12px'
},
'& .MuiOutlinedInput-input.Mui-disabled': {
WebkitTextFillColor:theme.myTheme.palette?.disabled?.text
},
}),
...(isDisabled && uischemaData.multiple && {
"& .MuiOutlinedInput-root": {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: theme.myTheme.palette.primary?.main,
},
"& input": {
WebkitTextFillColor: theme.myTheme.palette?.disabled?.text,
},
},
"& .MuiInputLabel-root": {
color: theme.myTheme.palette?.disabled?.text,
},
"& .MuiInputLabel-root.Mui-focused": {
color:
theme.myTheme.palette?.disabled?.text,
},
"& .MuiSvgIcon-root": {
color: theme.myTheme.palette?.disabled?.text,
},
}),
...componentStyle
}}
freeSolo={uischemaData.freeSolo ? true : false}
multiple={uischemaData.multiple ? true : false}
id={path}
options={filteredSelectOptions ?? []}
value={value}
slots={{
popper: PopperSlot,
...(uischemaData.multiple ? { paper: MultiSelectSearchPanel } : {}),
}}
slotProps={{
listbox: {
sx: {
overflowY: "auto",
"&::-webkit-scrollbar": { width: "4px" },
"&::-webkit-scrollbar-thumb": {
backgroundColor: theme.myTheme.palette?.secondary?.light,
borderRadius: "4px",
},
},
},
...(uischemaData.multiple ? { paper: MultiSelectDropdownPanelProps } : {}),
...(uischemaData.multiple
? {
popupIndicator: {
onClick: (e: any) => {
e.preventDefault();
e.stopPropagation();
setOpen((prev) => !prev);
},
},
}
: {}),
}}
renderTags={uischemaData.multiple ? () => null : undefined}
renderOption={
uischemaData.multiple
? (optionProps: any, option: any, { selected: isSelected }: any) => (
}
checkedIcon={}
sx={{ padding: 0 }}
disableRipple
onMouseDown={(e) => e.preventDefault()}
/>
{option.label}
)
: undefined
}
renderInput={(params) => (
{
setChangeState(newValue.target.value);
handleChange(path, newValue.target.value);
}
: () => {}
}
/>
)}
/>
);
});
export default ImpaktAppsAutoComplete;
function updateSchema(param) {
if (param.uischemaData.multiple) {
param.setSchema((pre: any) => {
return {
...pre,
properties: {
...pre.properties,
[param.path]: {
...pre.properties?.[param.path],
type: "array",
items: {
oneOf: param.response,
},
},
},
};
});
} else {
param.setSchema((pre: any) => {
return {
...pre,
properties: {
...pre.properties,
[param.path]: {
...pre.properties?.[param.path],
uniqueItems: true,
oneOf: param.response || [],
},
},
};
});
}
}