ENCOA-314 :
- Implemented Async Select - Changed Stats Page User fetching to use Async Select and only fetch the User data when it needs - Changed Record Filter to use Async Select - Changed useTicketListener to only fetch needed data - Added Sort/Projection to remove unnecessary data processing. - Removed some unnecessary data processing.
This commit is contained in:
117
src/components/Low/AsyncSelect.tsx
Normal file
117
src/components/Low/AsyncSelect.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import clsx from "clsx";
|
||||
import { useEffect, useState } from "react";
|
||||
import { GroupBase, StylesConfig } from "react-select";
|
||||
import ReactSelect from "react-select";
|
||||
import Option from "@/interfaces/option";
|
||||
|
||||
interface Props {
|
||||
defaultValue?: Option | Option[];
|
||||
options: Option[];
|
||||
value?: Option | Option[] | null;
|
||||
isLoading?: boolean;
|
||||
loadOptions: (inputValue: string) => void;
|
||||
onMenuScrollToBottom: (event: WheelEvent | TouchEvent) => void;
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
isClearable?: boolean;
|
||||
styles?: StylesConfig<Option, boolean, GroupBase<Option>>;
|
||||
className?: string;
|
||||
label?: string;
|
||||
flat?: boolean;
|
||||
}
|
||||
|
||||
interface MultiProps {
|
||||
isMulti: true;
|
||||
onChange: (value: Option[] | null) => void;
|
||||
}
|
||||
|
||||
interface SingleProps {
|
||||
isMulti?: false;
|
||||
onChange: (value: Option | null) => void;
|
||||
}
|
||||
|
||||
export default function AsyncSelect({
|
||||
value,
|
||||
isMulti,
|
||||
defaultValue,
|
||||
options,
|
||||
loadOptions,
|
||||
onMenuScrollToBottom,
|
||||
placeholder,
|
||||
disabled,
|
||||
onChange,
|
||||
styles,
|
||||
isClearable,
|
||||
isLoading,
|
||||
label,
|
||||
className,
|
||||
flat,
|
||||
}: Props & (MultiProps | SingleProps)) {
|
||||
const [target, setTarget] = useState<HTMLElement>();
|
||||
|
||||
useEffect(() => {
|
||||
if (document) setTarget(document.body);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="w-full flex flex-col gap-3">
|
||||
{label && (
|
||||
<label className="font-normal text-base text-mti-gray-dim">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<ReactSelect
|
||||
isMulti={isMulti}
|
||||
className={
|
||||
styles
|
||||
? undefined
|
||||
: clsx(
|
||||
"placeholder:text-mti-gray-cool border-mti-gray-platinum w-full border bg-white text-sm font-normal focus:outline-none",
|
||||
disabled &&
|
||||
"!bg-mti-gray-platinum/40 !text-mti-gray-dim cursor-not-allowed",
|
||||
flat ? "rounded-md" : "px-4 py-4 rounded-full",
|
||||
className
|
||||
)
|
||||
}
|
||||
isLoading={isLoading}
|
||||
filterOption={null}
|
||||
loadingMessage={() => "Loading..."}
|
||||
onInputChange={(inputValue) => {
|
||||
loadOptions(inputValue);
|
||||
}}
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={onChange as any}
|
||||
placeholder={placeholder}
|
||||
menuPortalTarget={target}
|
||||
defaultValue={defaultValue}
|
||||
onMenuScrollToBottom={onMenuScrollToBottom}
|
||||
styles={
|
||||
styles || {
|
||||
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
|
||||
control: (styles) => ({
|
||||
...styles,
|
||||
paddingLeft: "4px",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
":focus": {
|
||||
outline: "none",
|
||||
},
|
||||
}),
|
||||
option: (styles, state) => ({
|
||||
...styles,
|
||||
backgroundColor: state.isFocused
|
||||
? "#D5D9F0"
|
||||
: state.isSelected
|
||||
? "#7872BF"
|
||||
: "white",
|
||||
color: state.isFocused ? "black" : styles.color,
|
||||
}),
|
||||
}
|
||||
}
|
||||
isDisabled={disabled}
|
||||
isClearable={isClearable}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user