"use client" import { useEffect, useState } from "react" import { toast } from "sonner" import { CustomerForm, type CustomerFormSavePayload } from "@/components/customer-form" import { ProjectDialog } from "@/components/project-dialog" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { linkConversationToCustomer } from "@/lib/api/agent" import { fetchCustomers, saveCustomerProfile, type AdminCustomer } from "@/lib/api/customer" import { linkTicketToCustomer } from "@/lib/api/ticket" import { useI18n } from "@/i18n/provider" export type CustomerLinkOrCreateDialogProps = { open: boolean onOpenChange: (open: boolean) => void /** When present, links an existing or newly created customer to this conversation. */ conversationId?: number | null /** When present, links an existing or newly created customer to this ticket. */ ticketId?: number | null /** Called after linking succeeds, or after creating without a linked context. */ onSuccess?: () => void | Promise } const createFormId = "customer-link-or-create-form" export function CustomerLinkOrCreateDialog({ open, onOpenChange, conversationId, ticketId, onSuccess, }: CustomerLinkOrCreateDialogProps) { const t = useI18n() const [searchText, setSearchText] = useState("") const [searching, setSearching] = useState(false) const [results, setResults] = useState([]) const [showCreate, setShowCreate] = useState(false) const [linkingId, setLinkingId] = useState(null) const [saving, setSaving] = useState(false) useEffect(() => { if (!open) { return } setSearchText("") setResults([]) setShowCreate(false) setLinkingId(null) }, [open]) const runSearch = async () => { const q = searchText.trim() if (!q) { toast.error(t("customerLink.keywordRequired")) return } setSearching(true) try { const data = await fetchCustomers({ keyword: q, page: 1, limit: 50, status: 0, }) setResults(data.results) if (data.results.length === 0) { toast.message(t("customerLink.noMatch")) } } catch (e) { toast.error(e instanceof Error ? e.message : t("customerLink.searchFailed")) } finally { setSearching(false) } } const handleLinkExisting = async (customer: AdminCustomer) => { const customerName = customer.name || t("customerLink.fallbackName", { id: customer.id }) if (!conversationId && !ticketId) { toast.success(t("customerLink.selected", { name: customerName })) onOpenChange(false) await onSuccess?.() return } setLinkingId(customer.id) try { if (conversationId) { await linkConversationToCustomer({ conversationId, customerId: customer.id, }) } if (ticketId) { await linkTicketToCustomer({ ticketId, customerId: customer.id, }) } toast.success(t("customerLink.linked")) onOpenChange(false) await onSuccess?.() } catch (e) { toast.error(e instanceof Error ? e.message : t("customerLink.linkFailed")) } finally { setLinkingId(null) } } const onCreateSave = async (payload: CustomerFormSavePayload) => { setSaving(true) try { const created = await saveCustomerProfile(payload) if (conversationId) { await linkConversationToCustomer({ conversationId, customerId: created.id, }) } if (ticketId) { await linkTicketToCustomer({ ticketId, customerId: created.id, }) } if (conversationId || ticketId) { toast.success( conversationId ? t("customerLink.createdAndLinkedConversation") : t("customerLink.createdAndLinkedTicket") ) } else { toast.success(t("customerLink.created")) } onOpenChange(false) await onSuccess?.() } catch (e) { toast.error(e instanceof Error ? e.message : t("customerLink.saveFailed")) } finally { setSaving(false) } } const description = ( <> {t("customerLink.descriptionPrefix")} {conversationId || ticketId ? conversationId ? t("customerLink.descriptionLinkConversation") : t("customerLink.descriptionLinkTicket") : t("customerLink.descriptionNoContext")} {t("customerLink.descriptionCreatePrefix")} {conversationId || ticketId ? conversationId ? t("customerLink.descriptionCreateConversation") : t("customerLink.descriptionCreateTicket") : t("customerLink.descriptionCreateNoContext")} ) return ( onOpenChange(nextOpen)} title={t("customerLink.title")} description={description} allowFullscreen size="xl" footer={
{showCreate ? ( ) : null}
} >
setSearchText(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); void runSearch(); } }} />
{results.length > 0 ? (
    {results.map((row) => (
  • {row.name || t("customerLink.fallbackName", { id: row.id })} {row.primaryMobile} {row.primaryEmail}
    {row.company?.name ? (
    {row.company.name}
    ) : null}
  • ))}
) : null}
{showCreate ? ( ) : null}
); }