diff --git a/src/components/companies/company-picker.tsx b/src/components/companies/company-picker.tsx new file mode 100644 index 0000000..34cd522 --- /dev/null +++ b/src/components/companies/company-picker.tsx @@ -0,0 +1,103 @@ +'use client'; + +import { useState } from 'react'; +import { Check, ChevronsUpDown } from 'lucide-react'; +import { useQuery } from '@tanstack/react-query'; + +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { useDebounce } from '@/hooks/use-debounce'; +import { apiFetch } from '@/lib/api/client'; +import { cn } from '@/lib/utils'; + +interface CompanyOption { + id: string; + name: string; + legalName?: string | null; +} + +interface CompanyPickerProps { + value: string | null; + onChange: (companyId: string | null) => void; + placeholder?: string; + disabled?: boolean; +} + +export function CompanyPicker({ + value, + onChange, + placeholder = 'Select company...', + disabled, +}: CompanyPickerProps) { + const [open, setOpen] = useState(false); + const [search, setSearch] = useState(''); + const debounced = useDebounce(search, 300); + + const { data } = useQuery<{ data: CompanyOption[] }>({ + queryKey: ['company-picker', debounced], + queryFn: () => apiFetch(`/api/v1/companies/autocomplete?q=${encodeURIComponent(debounced)}`), + enabled: open, + }); + + const options = data?.data ?? []; + + const selectedLabel = (() => { + if (!value) return placeholder; + const match = options.find((o) => o.id === value); + return match?.name ?? `Company ${value.slice(0, 8)}`; + })(); + + return ( + + + + + + + + + No companies found. + + {options.map((c) => ( + { + onChange(c.id); + setOpen(false); + }} + > + + + {c.name} + {c.legalName ? ( + {c.legalName} + ) : null} + + + ))} + + + + + + ); +}