"use client"; import { useEffect, useState } from "react"; import { MessageCircle } from "lucide-react"; import { api } from "@/lib/client-api"; import { useI18n } from "./I18nProvider"; import type { DiscordStatus } from "@/shared/discord"; export function DiscordIntegration() { const { t } = useI18n(); const [status, setStatus] = useState(null), [error, setError] = useState(""), [message, setMessage] = useState(""), [busy, setBusy] = useState(false); async function load() { try { setStatus(await api("moderation/discord")); setError(""); } catch (e) { setError((e as Error).message); } } useEffect(() => { void load(); }, []); const configured = !!( status?.botConfigured && status.publicUrlConfigured && (status.mapsConfigured || status.partiesConfigured) ); async function run(action: "check" | "retry") { setBusy(true); setError(""); setMessage(""); try { await api("moderation/discord", { action }); setMessage( action === "check" ? "Discord bot and channel access checked. Send Messages and Embed Links are also required." : "Saved Discord announcements will retry.", ); await load(); } catch (e) { setError((e as Error).message); } finally { setBusy(false); } } return (

{t( "New approved maps are announced automatically. Hosts can publish an open party to the shared Discord channel.", )}

{status && ( <>

{configured ? t("Discord bot configured") : t("Discord setup required in Vercel environment variables")}

{t("Map announcements: {state}", { state: status.mapsConfigured ? t("Configured") : t("Not configured"), })}{" "} ·{" "} {t("Party announcements: {state}", { state: status.partiesConfigured ? t("Configured") : t("Not configured"), })}

{t("{pending} pending · {failed} need attention · {sent} sent", { pending: status.pending, failed: status.failed, sent: status.sent, })}

)} {error && (

{t(error)}

)} {message &&

{t(message)}

}
); }