import { IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconMessageCircle, IconChevronDown, IconChevronRight, IconCopy, IconCheck, IconInfoCircle, } from "@tabler/icons-react"; import React, { useState, useCallback } from "react"; import { agentNativePath } from "../api-path.js"; import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js"; import { useT } from "../i18n.js"; import type { IntegrationStatus } from "./useIntegrationStatus.js"; import { isNonPublicWebhookUrl } from "./webhook-url.js"; // eslint-disable-next-line @typescript-eslint/no-explicit-any const platformIcons: Record> = { slack: IconBrandSlack as React.ComponentType, telegram: IconBrandTelegram as React.ComponentType, whatsapp: IconBrandWhatsapp as React.ComponentType, }; function StatusDot({ enabled, configured, }: { enabled: boolean; configured: boolean; }) { const color = enabled && configured ? "bg-green-500" : configured ? "bg-yellow-500" : "bg-muted-foreground/55"; return ; } export function IntegrationCard({ status, onRefresh, }: { status: IntegrationStatus; onRefresh: () => void; }) { const t = useT(); const [expanded, setExpanded] = useState(false); const [toggling, setToggling] = useState(false); const [copied, setCopied] = useState(false); const [toggleError, setToggleError] = useState(null); const Icon = platformIcons[status.platform] || IconMessageCircle; const handleToggle = useCallback(async () => { setToggling(true); setToggleError(null); try { const action = status.enabled ? "disable" : "enable"; const res = await fetch( agentNativePath( `/_agent-native/integrations/${status.platform}/${action}`, ), { method: "POST" }, ); if (res.ok) { onRefresh(); return; } const data = (await res.json().catch(() => null)) as { error?: string; } | null; setToggleError( data?.error || res.statusText || `Couldn't ${action} ${status.label} (HTTP ${res.status})`, ); } catch (err) { setToggleError( err instanceof Error ? err.message : t("integrations.networkError"), ); } finally { setToggling(false); } }, [status.platform, status.enabled, status.label, onRefresh]); const webhookUrlIsLocalOnly = !!status.webhookUrl && isNonPublicWebhookUrl(status.webhookUrl); const handleCopy = useCallback(async () => { if (!status.webhookUrl || webhookUrlIsLocalOnly) return; await navigator.clipboard.writeText(status.webhookUrl); setCopied(true); setTimeout(() => setCopied(false), 2000); }, [status.webhookUrl, webhookUrlIsLocalOnly]); return (
{expanded && (
{status.webhookUrl && (
{t("integrations.webhookUrl")}
{webhookUrlIsLocalOnly ? (
{t("integrations.webhookUrlLocalOnly", { platform: status.label, url: status.webhookUrl, })}
) : (
{status.webhookUrl} {t("integrations.copyWebhookUrl")}
)}
)} {status.error && (

{status.error}

)} {toggleError && (

{toggleError}

)} {!status.configured && !status.error && (

{t("integrations.notConfigured")}

)} {status.configured && ( )}
)}
); }