import { Input } from '@/Components/ui/input'; import { Badge } from '@/Components/ui/badge'; import { Search, Loader2 } from 'lucide-react'; import { useCallback, useEffect, useRef, useState } from 'react'; interface MaterialItem { id: number; ulid: string; name: string; unit: string; unit_cost: string; } interface PurchaseOrderResult { id: number; ulid: string; document_number: string; supplier?: string; items: { id: number; material: MaterialItem; quantity: string; unit_cost: string }[]; } interface Props { projectUlid: string; onSelect: (po: PurchaseOrderResult) => void; selectedPo?: PurchaseOrderResult | null; className?: string; } export default function PurchaseOrderLookup({ projectUlid, onSelect, selectedPo, className }: Props) { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const wrapperRef = useRef(null); const debounceRef = useRef>(); const fetchResults = useCallback(async (q: string) => { if (!projectUlid) return; setLoading(true); try { const params = new URLSearchParams({ project_ulid: projectUlid }); if (q) params.set('q', q); const response = await fetch(`${route('purchase-orders.search')}?${params}`, { headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '', }, }); if (response.ok) { const data = await response.json(); setResults(data); } } catch { /* silently fail */ } finally { setLoading(false); } }, [projectUlid]); useEffect(() => { if (debounceRef.current) clearTimeout(debounceRef.current); if (!query && !open) return; debounceRef.current = setTimeout(() => fetchResults(query), 300); return () => { if (debounceRef.current) clearTimeout(debounceRef.current); }; }, [query, fetchResults]); // Close dropdown on outside click useEffect(() => { const handler = (e: MouseEvent) => { if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) { setOpen(false); } }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, []); const handleSelect = (po: PurchaseOrderResult) => { setQuery(po.document_number); setOpen(false); onSelect(po); }; const handleFocus = () => { setOpen(true); if (results.length === 0) fetchResults(query); }; return (
{ setQuery(e.target.value); setOpen(true); if (selectedPo) onSelect(null as unknown as PurchaseOrderResult); }} onFocus={handleFocus} placeholder="Search by PO number (e.g. PO-2026)..." className="pl-10 max-w-lg" /> {loading && }
{open && results.length > 0 && !selectedPo && (
{results.map(po => ( ))}
)} {open && results.length === 0 && !loading && query && (
No approved purchase orders found.
)}
); }