created new component SelectMultiple items
This commit is contained in:
parent
8ece56da52
commit
cdec17735f
125
src/components/common/SelectMultiple.jsx
Normal file
125
src/components/common/SelectMultiple.jsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
import './MultiSelectDropdown.css';
|
||||||
|
|
||||||
|
const SelectMultiple = ({
|
||||||
|
name,
|
||||||
|
options = [],
|
||||||
|
label = 'Select options',
|
||||||
|
labelKey = 'name',
|
||||||
|
valueKey = 'id',
|
||||||
|
placeholder = 'Please select...',
|
||||||
|
IsLoading = false
|
||||||
|
}) => {
|
||||||
|
const { setValue, watch } = useFormContext();
|
||||||
|
const selectedValues = watch(name) || [];
|
||||||
|
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [searchText, setSearchText] = useState('');
|
||||||
|
const dropdownRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (e) => {
|
||||||
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleCheckboxChange = (value) => {
|
||||||
|
const updated = selectedValues.includes(value)
|
||||||
|
? selectedValues.filter((v) => v !== value)
|
||||||
|
: [...selectedValues, value];
|
||||||
|
|
||||||
|
setValue(name, updated, { shouldValidate: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredOptions = options.filter((item) =>
|
||||||
|
item[labelKey]?.toLowerCase().includes(searchText.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={dropdownRef} className="multi-select-dropdown-container">
|
||||||
|
<label className="form-label mb-1">{label}</label>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="multi-select-dropdown-header"
|
||||||
|
onClick={() => setIsOpen((prev) => !prev)}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
selectedValues.length > 0
|
||||||
|
? 'placeholder-style-selected'
|
||||||
|
: 'placeholder-style'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="selected-badges-container">
|
||||||
|
{selectedValues.length > 0 ? (
|
||||||
|
selectedValues.map((val) => {
|
||||||
|
const found = options.find((opt) => opt[valueKey] === val);
|
||||||
|
return (
|
||||||
|
<span key={val} className="badge badge-selected-item mx-1">
|
||||||
|
{found ? found[labelKey] : ''}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<span className="placeholder-text">{placeholder}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<i className="bx bx-chevron-down"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{isOpen && (
|
||||||
|
<div className="multi-select-dropdown-options">
|
||||||
|
<div className="multi-select-dropdown-search">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search..."
|
||||||
|
value={searchText}
|
||||||
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
|
className="multi-select-dropdown-search-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{filteredOptions.map((item) => {
|
||||||
|
const labelVal = item[labelKey];
|
||||||
|
const valueVal = item[valueKey];
|
||||||
|
const isChecked = selectedValues.includes(valueVal);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={valueVal}
|
||||||
|
className={`multi-select-dropdown-option ${isChecked ? 'selected' : ''}`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="custom-checkbox form-check-input"
|
||||||
|
checked={isChecked}
|
||||||
|
onChange={() => handleCheckboxChange(valueVal)}
|
||||||
|
/>
|
||||||
|
<label className="text-secondary">{labelVal}</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} )}
|
||||||
|
{!IsLoading && filteredOptions.length === 0 && (
|
||||||
|
<div className='multi-select-dropdown-Not-found'>
|
||||||
|
<label className="text-muted">Not Found {`'${searchText}'`}</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{IsLoading && filteredOptions.length === 0 && (
|
||||||
|
<div className='multi-select-dropdown-Not-found'>
|
||||||
|
<label className="text-muted">Loading...</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectMultiple;
|
Loading…
x
Reference in New Issue
Block a user