"use client" import { useEffect, useMemo, useState } from "react" import { ChevronsUpDownIcon, PlusIcon } from "lucide-react" import { toast } from "sonner" import { EditDialog as CompanyEditDialog } from "@/app/dashboard/companies/_components/edit" import { Button } from "@/components/ui/button" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@/components/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import { createCompany, fetchCompanies, fetchCompany, type AdminCompany, type CreateAdminCompanyPayload, } from "@/lib/api/company" import { cn } from "@/lib/utils" type CompanyPickerProps = { value: string onChange: (value: string) => void disabled?: boolean placeholder?: string } export function CompanyPicker({ value, onChange, disabled = false, placeholder = "请选择公司", }: CompanyPickerProps) { const [open, setOpen] = useState(false) const [keyword, setKeyword] = useState("") const [loading, setLoading] = useState(false) const [options, setOptions] = useState([]) const [selectedCompany, setSelectedCompany] = useState(null) const [createOpen, setCreateOpen] = useState(false) const [createSaving, setCreateSaving] = useState(false) const trimmedKeyword = keyword.trim() const normalizedKeyword = trimmedKeyword.toLowerCase() useEffect(() => { let cancelled = false if (!open) { return } setLoading(true) void (async () => { try { const data = await fetchCompanies({ status: 0, page: 1, limit: 20, name: trimmedKeyword || undefined, }) if (cancelled) { return } setOptions(data.results) } catch (error) { if (!cancelled) { setOptions([]) toast.error(error instanceof Error ? error.message : "加载公司列表失败") } } finally { if (!cancelled) { setLoading(false) } } })() return () => { cancelled = true } }, [open, trimmedKeyword]) useEffect(() => { let cancelled = false const companyId = Number(value) if (companyId <= 0) { setSelectedCompany(null) return } if (selectedCompany?.id === companyId) { return } void (async () => { try { const data = await fetchCompany(companyId) if (!cancelled) { setSelectedCompany(data) } } catch { if (!cancelled) { setSelectedCompany(null) } } })() return () => { cancelled = true } }, [selectedCompany?.id, value]) const canCreate = useMemo(() => { if (!trimmedKeyword) { return false } return !options.some((item) => item.name.trim().toLowerCase() === normalizedKeyword) }, [normalizedKeyword, options, trimmedKeyword]) const buttonLabel = Number(value) > 0 ? selectedCompany?.name || `公司 #${value}` : placeholder function handleSelectCompany(company: AdminCompany) { setSelectedCompany(company) onChange(String(company.id)) setOpen(false) setKeyword("") } function handleClear() { setSelectedCompany(null) onChange("0") setOpen(false) setKeyword("") } async function handleCreateCompany(payload: CreateAdminCompanyPayload) { setCreateSaving(true) try { const created = await createCompany(payload) setSelectedCompany(created) onChange(String(created.id)) setCreateOpen(false) setOpen(false) setKeyword("") toast.success(`已创建公司:${created.name}`) } catch (error) { toast.error(error instanceof Error ? error.message : "创建公司失败") throw error } finally { setCreateSaving(false) } } return ( <> } > 0 ? "text-foreground" : "text-muted-foreground")}> {buttonLabel} {loading ? 加载中... : null} {!loading && options.length === 0 ? 未找到匹配公司 : null} {!loading ? ( 不关联公司 {options.map((item) => ( handleSelectCompany(item)} >
{item.name} {item.code ? ( {item.code} ) : null}
))}
) : null} {canCreate ? ( <> setCreateOpen(true)} > 新建公司“{trimmedKeyword}” ) : null}
) }