"use client"; import { useEffect, useRef, useState } from "react"; // ALTCHA کپچای خودمیزبان روی بک‌اند clinicpro. widget فقط وقتی رندر می‌شود که // سرور کپچا را فعال کرده باشد (/api/v1/altcha/config). چون nobat724 روی دامنه‌ی // جدا از API است، آدرس challenge باید absolute باشد. const API = process.env.NEXT_PUBLIC_API_URL; export default function Altcha({ onVerified }) { const ref = useRef(null); // null=در حال بررسی، true/false=فعال/غیرفعال بودن کپچا در سرور const [enabled, setEnabled] = useState(null); useEffect(() => { let alive = true; fetch(`${API}/api/v1/altcha/config`) .then((r) => r.json()) .then((c) => { if (!alive) return; setEnabled(!!c.enabled); if (!c.enabled) onVerified(""); // کپچا خاموش → فرم بدون مانع ارسال شود }) .catch(() => { if (alive) setEnabled(false); }); return () => { alive = false; }; }, [onVerified]); useEffect(() => { if (enabled !== true) return; const el = ref.current; if (!el) return; let cancelled = false; const onStateChange = (e) => { if (e.detail?.state === "verified" && e.detail.payload) { onVerified(e.detail.payload); } }; el.addEventListener("statechange", onStateChange); // در React 18 پراپ‌های JSX روی custom element ممکن است property ست شوند و // widget نخواند؛ پس با setAttribute ست می‌کنیم. نام attribute در widget v3 // «challenge» است (نه «challengeurl» قدیمی که باعث fetch صفحه‌ی HTML می‌شد). el.setAttribute("challenge", `${API}/api/v1/altcha/challenge`); el.setAttribute("language", "fa"); el.setAttribute("theme", "light"); // اول locale فارسی ثبت شود، سپس ماژول widget (تا هنگام upgrade، fa موجود باشد)، // و در نهایت auto فعال شود تا حل PoW بعد از آماده‌بودن challenge/زبان انجام شود. import("altcha/i18n/fa") .then(() => import("altcha")) .then(() => { if (!cancelled) el.setAttribute("auto", "onload"); }); return () => { cancelled = true; el.removeEventListener("statechange", onStateChange); }; }, [enabled, onVerified]); if (enabled !== true) return null; return ( ); }