"use client"; import React, { useState, useRef, useEffect } from "react"; import { Search, ChevronDown, Check, Loader2 } from "lucide-react"; interface Option { id: string; name: string; } interface AsyncComboboxProps { value: string; onChange: (value: string) => void; onSearch: (query: string) => Promise; placeholder?: string; id?: string; leftIcon?: React.ReactNode; defaultOptions?: Option[]; } export default function AsyncCombobox({ value, onChange, onSearch, placeholder = "Search...", id, leftIcon, defaultOptions = [] }: AsyncComboboxProps) { const [isOpen, setIsOpen] = useState(false); const [search, setSearch] = useState(""); const [options, setOptions] = useState(defaultOptions); const [loading, setLoading] = useState(false); const containerRef = useRef(null); const selectedOption = options.find(o => o.id === value) || defaultOptions.find(o => o.id === value); useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { setIsOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); useEffect(() => { if (!isOpen) return; const delayDebounceFn = setTimeout(async () => { if (!search) { setOptions(defaultOptions); return; } setLoading(true); try { const results = await onSearch(search); setOptions(results); } catch (error) { console.error("Search failed", error); } finally { setLoading(false); } }, 300); return () => clearTimeout(delayDebounceFn); }, [search, onSearch, isOpen, defaultOptions]); return (
{isOpen && (
{!loading && options.length === 0 ? (
No se encontraron resultados
) : ( options.map(option => (
{ onChange(option.id); setIsOpen(false); setSearch(""); }} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { onChange(option.id); setIsOpen(false); setSearch(""); } }} className={`flex items-center justify-between px-3 py-2.5 rounded-lg cursor-pointer transition-colors outline-none focus:bg-indigo-600 focus:text-white ${value === option.id ? "bg-indigo-600 text-white" : "hover:bg-white/5 text-gray-300" }`} > {option.name} {value === option.id &&
)) )}
)}
); }