"use client" import { ExternalLink, Plus, Trash2 } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import type { ApiSearchProvider, ApiSearchSettings } from "@/lib/contacts/discovery-types" import { FieldGroup } from "@/components/admin/settings/field-group" import { TechBrandSelectLabel } from "@/components/admin/settings/tech-brand-select-label" import { AutomationTabMasonry } from "@/components/gmail/settings/automation/automation-tab-masonry" import { catalogEntry, emptySearchProvider, ensureSearchSettingsDefaults, isSearchProviderConfigured, SEARCH_PROVIDER_CATALOG, } from "@/lib/web-search/search-provider-catalog" import { cn } from "@/lib/utils" type WebSearchProviderSecrets = Record type WebSearchProvidersEditorProps = { value: ApiSearchSettings onChange: (value: ApiSearchSettings) => void className?: string columns?: 1 | 2 providerSecrets?: WebSearchProviderSecrets } function providerOptions(value: ApiSearchSettings, providerSecrets?: WebSearchProviderSecrets) { return value.providers.map((provider) => ({ provider, configured: isSearchProviderConfigured(provider, { apiKeyConfigured: providerSecrets?.[provider.id]?.configured, }), })) } export function WebSearchProvidersEditor({ value, onChange, className, columns = 2, providerSecrets, }: WebSearchProvidersEditorProps) { const options = providerOptions(value, providerSecrets) function commit(next: ApiSearchSettings) { onChange(ensureSearchSettingsDefaults(next)) } function updateProvider(index: number, patch: Partial) { const providers = [...value.providers] providers[index] = { ...providers[index], ...patch } commit({ ...value, providers }) } function setProviderType(index: number, type: ApiSearchProvider["type"]) { const current = value.providers[index] const next = { ...emptySearchProvider(type), id: current?.id ?? emptySearchProvider(type).id, name: catalogEntry(type).label, api_key: current?.api_key ?? "", } const providers = [...value.providers] providers[index] = next commit({ ...value, providers }) } function addProvider() { const provider = emptySearchProvider("brave") commit({ default_provider_id: value.default_provider_id || provider.id, providers: [...value.providers, provider], }) } function removeProvider(index: number) { const removed = value.providers[index] const providers = value.providers.filter((_, i) => i !== index) const remainingOptions = providerOptions({ ...value, providers }, providerSecrets) let defaultId = value.default_provider_id if (defaultId === removed?.id) { defaultId = remainingOptions.find((entry) => entry.configured)?.provider.id ?? providers[0]?.id ?? "" } commit({ default_provider_id: defaultId, providers }) } return (
{value.providers.length > 0 ? ( {options.some((entry) => !entry.configured) ? (

Les fournisseurs incomplets restent visibles mais ne peuvent pas être sélectionnés par défaut.

) : null}
) : null} {value.providers.map((provider, index) => { const entry = catalogEntry(provider.type) const apiKeyConfigured = providerSecrets?.[provider.id]?.configured ?? false const configured = isSearchProviderConfigured(provider, { apiKeyConfigured }) return (

{provider.name || entry.label || `Fournisseur ${index + 1}`}

{!configured ? (

Configuration incomplète

) : apiKeyConfigured && !(provider.api_key ?? "").trim() ? (

Clé API enregistrée sur le serveur

) : null}

{entry.description}

{entry.docsUrl ? ( Documentation ) : null}
updateProvider(index, { name: e.target.value })} /> {entry.requiresApiKey || provider.api_key || apiKeyConfigured ? ( updateProvider(index, { api_key: e.target.value })} autoComplete="off" placeholder={ apiKeyConfigured && !(provider.api_key ?? "").trim() ? "•••••••• (laisser vide pour conserver)" : provider.type === "brave" ? "BSA…" : undefined } /> ) : null} {entry.requiresBaseURL || provider.base_url ? ( updateProvider(index, { base_url: e.target.value })} placeholder={ provider.type === "searxng" ? "https://searx.example.org" : "https://api.example.com/search" } /> ) : null} {provider.type === "bing" || provider.type === "searxng" || provider.type === "custom" ? ( updateProvider(index, { auth_header: e.target.value })} placeholder={ provider.type === "bing" ? "Ocp-Apim-Subscription-Key" : "Authorization" } /> ) : null} {provider.type === "custom" || provider.type === "searxng" || provider.query_param ? ( updateProvider(index, { query_param: e.target.value })} /> ) : null} {entry.supportsCustomMapping ? ( <> updateProvider(index, { results_path: e.target.value })} placeholder="results ou data.items" />
updateProvider(index, { title_field: e.target.value })} /> updateProvider(index, { url_field: e.target.value })} /> updateProvider(index, { description_field: e.target.value }) } />

L'URL peut contenir {"{query}"}{" "} et {"{count}"}. Sinon, le paramètre de requête est ajouté automatiquement.

) : null}
) })}
) }