"use client"; import { useQuery } from "@tanstack/react-query"; import { useAtomValue } from "jotai"; import { Globe, Loader2, Save } from "lucide-react"; import { useTranslations } from "next-intl"; import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { Switch } from "@/components/ui/switch"; import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service"; import { baseApiService } from "@/lib/apis/base-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; interface WebSearchSettingsManagerProps { searchSpaceId: number; } interface HealthStatus { status: string; response_time_ms?: number; error?: string; circuit_breaker?: string; } export function WebSearchSettingsManager({ searchSpaceId }: WebSearchSettingsManagerProps) { const t = useTranslations("searchSpaceSettings"); const { data: searchSpace, isLoading, refetch, } = useQuery({ queryKey: cacheKeys.searchSpaces.detail(searchSpaceId.toString()), queryFn: () => searchSpacesApiService.getSearchSpace({ id: searchSpaceId }), enabled: !!searchSpaceId, }); const { data: healthData } = useQuery({ queryKey: ["web-search-health"], queryFn: async () => { const response = await baseApiService.get("/api/v1/platform/web-search/health"); return response as HealthStatus; }, refetchInterval: 30000, staleTime: 10000, }); const { mutateAsync: updateSearchSpace } = useAtomValue(updateSearchSpaceMutationAtom); const [enabled, setEnabled] = useState(true); const [engines, setEngines] = useState(""); const [language, setLanguage] = useState(""); const [safesearch, setSafesearch] = useState(""); const [saving, setSaving] = useState(false); useEffect(() => { if (searchSpace) { setEnabled(searchSpace.web_search_enabled ?? true); const cfg = searchSpace.web_search_config as Record | null; setEngines((cfg?.engines as string) ?? ""); setLanguage((cfg?.language as string) ?? ""); const ss = cfg?.safesearch; setSafesearch(ss !== null && ss !== undefined ? String(ss) : ""); } }, [searchSpace]); const handleSave = useCallback(async () => { try { setSaving(true); const webSearchConfig: Record = {}; if (engines.trim()) webSearchConfig.engines = engines.trim(); if (language.trim()) webSearchConfig.language = language.trim(); if (safesearch !== "") webSearchConfig.safesearch = Number(safesearch); await updateSearchSpace({ id: searchSpaceId, data: { web_search_enabled: enabled, web_search_config: Object.keys(webSearchConfig).length > 0 ? webSearchConfig : null, }, }); toast.success(t("web_search_saved")); await refetch(); } catch (error: unknown) { console.error("Error saving web search settings:", error); const message = error instanceof Error ? error.message : "Failed to save web search settings"; toast.error(message); } finally { setSaving(false); } }, [searchSpaceId, enabled, engines, language, safesearch, updateSearchSpace, refetch, t]); if (isLoading) { return (
); } const isHealthy = healthData?.status === "healthy"; const isUnavailable = healthData?.status === "unavailable"; return (
{t("web_search_description")} {healthData && (
{isHealthy ? `${t("web_search_status_healthy")} (${healthData.response_time_ms}ms)` : isUnavailable ? t("web_search_status_not_configured") : t("web_search_status_unhealthy")}
)} {t("web_search_title")} {t("web_search_enabled_description")}

{t("web_search_enabled_description")}

{enabled && (
setEngines(e.target.value)} className="text-sm md:text-base h-9 md:h-10" />

{t("web_search_engines_description")}

setLanguage(e.target.value)} className="text-sm md:text-base h-9 md:h-10" />

{t("web_search_language_description")}

{t("web_search_safesearch_description")}

)}
); }