import { FC, useState, useRef, useEffect } from 'react'; import INDONESIAN_CITIES from '../constants/cities'; interface CitySelectProps { value: string; onChange: (value: string) => void; error?: string; placeholder?: string; } export const CitySelect: FC = ({ value, onChange, error, placeholder = 'Search your city...', }) => { const [isOpen, setIsOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const dropdownRef = useRef(null); const inputRef = useRef(null); // Filter cities based on search query const filteredCities = INDONESIAN_CITIES.filter((city) => city.toLowerCase().includes(searchQuery.toLowerCase()) ); // Close dropdown when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const handleSelectCity = (city: string) => { onChange(city); setSearchQuery(''); setIsOpen(false); }; const handleInputClick = () => { setIsOpen(true); setSearchQuery(''); }; const handleClearSelection = () => { onChange(''); setSearchQuery(''); setIsOpen(true); inputRef.current?.focus(); }; return (
{ setSearchQuery(e.target.value); setIsOpen(true); }} onClick={handleInputClick} placeholder={placeholder} className={`w-full h-[42px] px-3 text-[15px] border rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 ${ error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600' }`} /> {value && !isOpen && ( )}
{error &&

{error}

} {isOpen && (
{filteredCities.length > 0 ? (
    {filteredCities.map((city) => (
  • handleSelectCity(city)} className={`px-3 py-2 cursor-pointer hover:bg-blue-50 dark:hover:bg-blue-900/30 ${ value === city ? 'bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-400' : 'text-gray-900 dark:text-gray-200' }`} > {city}
  • ))}
) : (
No cities found
)}
)}
); };