components/DropDown/CustomDropDown.tsx
src/ui/components/widgets/SpeedLimitSection/components/DropDown/CustomDropDown.tsxunknown
typescript
6 days ago
6.2 kB
4
Indexable
Never
import React, { useCallback, useEffect, useRef, useState } from 'react' import { useSearchParams } from '@Hooks' import { useLocation } from 'react-router-dom' interface MultiselectDropdownProps { type: string options: { value: string; label: string }[] placeholder?: string txtSelected?: string txtAll?: string txtRemove?: string txtSearch?: string search?: boolean height?: string onChange?: (selected: string[]) => void disabled?: boolean // Thêm prop disabled } const CustomDropDown: React.FC<MultiselectDropdownProps> = ({ type, options, placeholder = 'select', txtSelected = 'selected', txtAll = 'All', txtRemove = 'Remove', txtSearch = 'search', search = true, height = '15rem', onChange, disabled = false // Mặc định không disabled }) => { const searchParams = useSearchParams() const location = useLocation() const [dropdownOpen, setDropdownOpen] = useState(false) const [searchText, setSearchText] = useState('') const dropdownRef = useRef<HTMLDivElement>(null) const [selectedOptions, setSelectedOptions] = useState<string[]>([]) const toggleOption = useCallback( (value: string) => { setSelectedOptions(prevSelected => { const newSelected = prevSelected.includes(value) ? prevSelected.filter(opt => opt !== value) : [...prevSelected, value] if (onChange) { onChange(newSelected) } return newSelected }) }, [onChange] ) const handleOutsideClick = useCallback((event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setDropdownOpen(false) } }, []) useEffect(() => { const selectedOptions = searchParams.getSearchParam('type')?.split(',') if (selectedOptions) { setTimeout(() => { setSelectedOptions(selectedOptions) }, 200) } }, [type]) useEffect(() => { document.addEventListener('click', handleOutsideClick) return () => { document.removeEventListener('click', handleOutsideClick) } }, [handleOutsideClick]) const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchText.toLowerCase()) ) return ( <div className={`inline-block relative w-full h-[35px] ${ disabled ? 'opacity-50 ' : '' }`} ref={dropdownRef} > <div className={`p-[6px] border border-gray-300 rounded cursor-pointer bg-white h-full ${ disabled ? 'pointer-events-none !bg-[#d8dbe0]' : '' }`} onClick={() => !disabled && setDropdownOpen(!dropdownOpen)} // Vô hiệu hóa click nếu bị disabled > {selectedOptions.length === 0 ? ( <span className="text-gray-400 block text-center">{placeholder}</span> ) : selectedOptions.length > 3 ? ( <span> {selectedOptions.length} {txtSelected} </span> ) : ( selectedOptions.map(value => ( <span key={value} className={`inline-block bg-gray-200 font-medium rounded text-[12px] px-1 py-[2px] mr-1 ${ disabled ? 'bg-gray-400' : '' }`} > {options.find(option => option.value === value)?.label} <span className="ml-1 cursor-pointer text-gray-600 hover:text-gray-800" onClick={e => { e.stopPropagation() toggleOption(value) }} > 🗙 </span> </span> )) )} </div> {dropdownOpen && !disabled && ( <div className="absolute border border-gray-300 rounded-xl bg-white z-10 shadow-lg w-full overflow-hidden"> {search && ( <div className="p-2"> <input type="text" className="w-full border border-gray-300 rounded p-1" placeholder={txtSearch} value={searchText} onChange={e => { setSearchText(e.target.value) }} disabled={disabled} /> </div> )} <div className="overflow-y-auto"> {options.length > 0 && ( <div className="p-2 cursor-pointer hover:bg-gray-200" onClick={() => { const allSelected = selectedOptions.length === options.length const newSelected = allSelected ? [] : options.map(opt => opt.value) setSelectedOptions(newSelected) if (onChange) { onChange(newSelected) } }} > <input type="checkbox" className="mr-2" checked={selectedOptions.length === options.length} onChange={e => {}} disabled={disabled} /> {txtAll} </div> )} {filteredOptions.map(option => ( <div key={option.value} className={`p-2 cursor-pointer hover:bg-gray-200 ${ selectedOptions.includes(option.value) ? 'bg-gray-100' : '' }`} onClick={() => !disabled && toggleOption(option.value)} > <input type="checkbox" className="mr-2" checked={selectedOptions.includes(option.value)} onChange={e => { toggleOption(option.value) }} onClick={e => e.stopPropagation()} disabled={disabled} /> {option.label} </div> ))} </div> </div> )} </div> ) } export default CustomDropDown
Leave a Comment