import { Combobox } from "@tailor-platform/app-shell"; import { useCallback } from "react"; import { useClient } from "urql"; import { graphql } from "@/graphql"; import { cn } from "@/lib/utils"; const CustomerAccountSearchQuery = graphql(` query CustomerAccountSearch($query: CustomerAccountQueryInput, $first: Int) { customerAccounts(query: $query, first: $first, order: [{ field: code, direction: Asc }]) { edges { node { id name companyId status } } } } `); /** id is a CustomerAccount ID. */ export interface CustomerAccountRef { id: string; name: string; } const DEBOUNCE_MS = 300; const PAGE_SIZE = 200; interface CustomerAccountComboboxProps { value: CustomerAccountRef | null; onValueChange: (customerAccount: CustomerAccountRef | null) => void; placeholder?: string; className?: string; disabled?: boolean; companyId?: string; } /** Selects active customer accounts by their required display names. */ export const CustomerAccountCombobox = ({ value, onValueChange, placeholder = "Search customers...", className, disabled, companyId, }: CustomerAccountComboboxProps) => { const client = useClient(); const fetcher = useCallback( async (input: string | null, { signal }: { signal: AbortSignal }) => { const searchText = input === value?.name ? null : input; const regex = searchText ? `(?i)${searchText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}` : undefined; const query = { status: { eq: "ACTIVE" as const }, ...(companyId ? { companyId: { eq: companyId } } : {}), ...(regex ? { or: [{ name: { regex } }, { code: { regex } }] } : {}), }; const result = await client .query( CustomerAccountSearchQuery, { query, first: PAGE_SIZE, }, { fetchOptions: { signal }, requestPolicy: "network-only" }, ) .toPromise(); if (result.error) throw result.error; return (result.data?.customerAccounts.edges ?? []) .map((edge) => edge.node) .map((account) => ({ id: account.id, name: account.name })); }, [client, value, companyId], ); return ( ({ label: c.name, key: c.id })} placeholder={placeholder} className={cn("[&_[data-slot=combobox-input]]:pr-14", className)} disabled={disabled} /> ); };