"use client"; import { useCallback, useEffect, useState } from "react"; import { useTranslations } from "next-intl"; import { Card, Button, Input, Badge } from "@/shared/components"; export default function NotionSourceCard() { const t = useTranslations("endpoint"); const [connected, setConnected] = useState(false); const [token, setToken] = useState(""); const [busy, setBusy] = useState(false); const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null); const [expanded, setExpanded] = useState(false); const fetchConfig = useCallback(async () => { try { const res = await fetch("/api/settings/notion"); if (res.ok) { const data = await res.json(); setConnected(data.connected); } } catch { // Non-critical } }, []); useEffect(() => { void fetchConfig(); }, [fetchConfig]); useEffect(() => { if (message) { const timer = setTimeout(() => setMessage(null), 5000); return () => clearTimeout(timer); } }, [message]); const handleSaveToken = async () => { if (!token.trim()) { setMessage({ type: "error", text: "Please enter a Notion integration token" }); return; } setBusy(true); setMessage(null); try { const res = await fetch("/api/settings/notion", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: token.trim() }), }); const data = await res.json(); if (res.ok) { setConnected(true); setMessage({ type: "success", text: data.message }); } else { setMessage({ type: "error", text: data.error ?? "Failed to connect" }); setConnected(false); } } catch (err) { setMessage({ type: "error", text: err instanceof Error ? err.message : "Connection failed" }); } finally { setBusy(false); } }; const handleDisconnect = async () => { setBusy(true); setMessage(null); try { const res = await fetch("/api/settings/notion", { method: "DELETE" }); const data = await res.json(); if (res.ok) { setConnected(false); setToken(""); setMessage({ type: "success", text: data.message }); } else { setMessage({ type: "error", text: data.error ?? "Failed to disconnect" }); } } catch (err) { setMessage({ type: "error", text: err instanceof Error ? err.message : "Disconnect failed" }); } finally { setBusy(false); } }; return (
{expanded && (
{message && (
{message.type === "success" ? "check_circle" : "error"} {message.text}
)} {!connected ? (
setToken(e.target.value)} placeholder="ntn_... or secret_..." disabled={busy} className="font-mono text-sm flex-1" />

Create an Internal Integration at{" "} https://www.notion.so/profile/integrations

) : (
Token configured. Notion tools are available via MCP.
)}
)}
); }