You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
FreeBug/frontend/edu-connect/src/components/(dashboard)/Forms/AsyncSelectField.tsx

169 lines
4.7 KiB

import AsyncSelect from 'react-select/async';
import React, { useEffect, useRef } from 'react';
import { ChoiceType } from '@/helpers/commonSchema/common.schema';
import { Label } from '../ui/label';
import { StylesConfig } from 'node_modules/react-select/dist/declarations/src';
interface SelectFieldProps {
className?: string;
id?: string;
label?: string;
labelStyle: string;
labelWidth?: string;
name: string;
defaultValue?: ChoiceType | null;
value?: string | number | boolean;
required?: boolean;
wrapperClassName?: string;
options?: { value: string | number; label: string }[];
fieldErrors?: Array<string>;
clearSelectValue?: boolean;
setClearSelectValue?: React.Dispatch<React.SetStateAction<boolean>>;
isDisabled?: boolean;
onChange?: (choice: ChoiceType) => void | any;
loadOptions? : (inputValue: string, callback: (options: any[]) => void) => Promise<void> | any
placeHolder? : string
labelClassName? : string
defaultOptions? : { value: string | number; label: string }[]
isMulti? : boolean
}
const AsyncSelectField: React.FC<SelectFieldProps> = ({
className = '',
id,
label,
labelStyle,
labelWidth,
name,
defaultValue,
value,
required,
wrapperClassName = '',
fieldErrors = [],
clearSelectValue = false,
setClearSelectValue,
isDisabled,
onChange,
loadOptions,
placeHolder,
labelClassName ,
defaultOptions ,
isMulti = false ,
}) => {
if (labelStyle === 'label-left') {
wrapperClassName = wrapperClassName.concat(
' ',
' flex justify-between items-center gap-4 '
);
}
const selectRef = useRef<any>(null);
useEffect(() => {
if (clearSelectValue) {
selectRef?.current?.clearValue?.();
setClearSelectValue && setClearSelectValue(false);
}
}, [clearSelectValue, setClearSelectValue]);
// useEffect(() => {
// // Auto-select the first option if available
// if (!selectedValue && defaultOptions && defaultOptions.length > 0) {
// const firstOption = defaultOptions[0];
// setSelectedValue(firstOption);
// onChange && onChange(firstOption);
// }
// }, [defaultOptions, selectedValue, onChange]);
const styles = {
menuList: (base: any , state :any) => ({
...base,
borderColor : state?.isFocused && 'bg-[var(--primary)]',
colourStyles : '#fff',
'::-webkit-scrollbar': {
width: '5px',
},
'::-webkit-scrollbar-track': {
background: '#f1f1f1',
},
'::-webkit-scrollbar-thumb': {
background: '#d1d1d1',
},
'::-webkit-scrollbar-thumb:hover': {
background: '#555',
},
}),
input: (base:any, state : any) => ({
...base,
'[type="text"]': {
fontSize: 13,
fontWeight: 900,
color: 'green'
}
})
};
const colourStyles: StylesConfig<any> = {
control: (styles) => ({ ...styles, backgroundColor: 'white' }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return {
...styles,
backgroundColor:'hsl(var(--background))',
color:'#fff'
};
},
// input: (styles) => ({ ...styles, ...dot() }),
// placeholder: (styles) => ({ ...styles, ...dot('#ccc') }),
// singleValue: (styles, { data }) => ({ ...styles, ...dot(data.color) }),
};
return (
<div className={`${wrapperClassName}`}>
{label && (
<Label className={`${labelClassName} ${fieldErrors?.length > 0 && 'text-destructive'}`}>
{label}
{required ? <span className="text-red-400"> *</span> : ''}
</Label>
)}
<div className="w-full mt-2">
<AsyncSelect
cacheOptions
isMulti={isMulti}
loadOptions={loadOptions}
defaultOptions={defaultOptions}
ref={selectRef}
styles={styles}
isDisabled={isDisabled}
onChange={onChange as any}
className={className + 'bg-[var(--primary)]' + ' !text-sm '+ (fieldErrors?.length > 0 && 'border border-destructive')}
theme={(theme) => ({
...theme,
borderRadius: 0,
colors: {
...theme.colors,
backgroundColor: 'hsl(var(--background))' ,
primary25: 'hsl(var(--secondary))',
primary: 'hsl(var(--secondary))',
color : '#fff'
},
})}
id={id}
name={name}
defaultValue={defaultValue}
placeholder={placeHolder}
/>
<span className="block text-destructive text-xs my-1">
{fieldErrors.map((item: string, index: any) => (
<span key={index}>{item}</span>
))}
</span>
</div>
</div>
);
};
export default AsyncSelectField;