"use client"; import { useState } from "react"; import { useTranslations } from "next-intl"; import { Button } from "@/shared/components"; interface CloudflareRelayModalProps { isOpen: boolean; onClose: () => void; onDeployed: (poolProxyId: string, relayUrl: string) => void; } // Mirrors VercelRelayModal — shares the same x-relay-target/x-relay-auth // header scheme on the wire, only the deployment surface differs. export default function CloudflareRelayModal({ isOpen, onClose, onDeployed, }: CloudflareRelayModalProps) { const t = useTranslations("settings"); const [accountId, setAccountId] = useState(""); const [apiToken, setApiToken] = useState(""); const [projectName, setProjectName] = useState( process.env.NEXT_PUBLIC_CLOUDFLARE_RELAY_DEFAULT_PROJECT || "omniroute-relay" ); const [deploying, setDeploying] = useState(false); const [error, setError] = useState(null); const handleDeploy = async () => { if (!accountId.trim() || !apiToken.trim()) { setError(t("cloudflareRelayCredsRequired")); return; } setDeploying(true); setError(null); try { const res = await fetch("/api/settings/proxy/cloudflare-deploy", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ accountId: accountId.trim(), apiToken: apiToken.trim(), projectName: projectName.trim(), }), }); const data = await res.json(); if (!res.ok || !data.success) { setError(data.error?.message || t("cloudflareRelayDeployFailed")); } else { setApiToken(""); onDeployed(data.poolProxyId as string, data.relayUrl as string); onClose(); } } catch (err) { setError(err instanceof Error ? err.message : t("unknownError")); } finally { setDeploying(false); } }; if (!isOpen) return null; return (

{t("cloudflareRelayModalTitle")}

{t("cloudflareRelayWarning")}

{t("cloudflareRelayTokenHowto")}

setAccountId(e.target.value)} className="w-full text-sm bg-surface-alt border border-border rounded px-3 py-2 focus:outline-none focus:border-primary" placeholder="your-cloudflare-account-id" autoComplete="off" />

{t("cloudflareRelayAccountIdHint")}

setApiToken(e.target.value)} className="w-full text-sm bg-surface-alt border border-border rounded px-3 py-2 focus:outline-none focus:border-primary" placeholder="cloudflare-api-token" autoComplete="off" />

{t("cloudflareRelayApiTokenHint")}

setProjectName(e.target.value)} className="w-full text-sm bg-surface-alt border border-border rounded px-3 py-2 focus:outline-none focus:border-primary" placeholder="omniroute-relay" />
{error && (
{error}
)}

{t("cloudflareRelayFreeTierNote")}

); }