Files
nobat724_front/components/Altcha.js
T

82 lines
3.0 KiB
JavaScript

"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;
const FA_STRINGS = JSON.stringify({
label: "من ربات نیستم",
verifying: "در حال بررسی...",
verified: "تأیید شد",
waitAlert: "در حال بررسی... لطفاً منتظر بمانید.",
error: "احراز هویت ناموفق بود. کمی بعد دوباره تلاش کنید.",
expired: "احراز هویت منقضی شد. دوباره تلاش کنید.",
});
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]);
// ثبت custom element + ست‌کردن config به‌صورت attribute واقعی. در React 18
// پراپ‌های JSX روی custom element ممکن است به‌جای attribute به‌شکل property ست
// شوند و widget آن‌ها را نخواند (strings/theme اعمال نمی‌شد)؛ با setAttribute
// مطمئن می‌شویم درست خوانده می‌شوند. auto را آخر ست می‌کنیم تا بعد از config حل شود.
useEffect(() => {
if (enabled !== true) return;
const onStateChange = (e) => {
if (e.detail?.state === "verified" && e.detail.payload) {
onVerified(e.detail.payload);
}
};
// attributeها را قبل از import (قبل از upgrade شدن element) ست می‌کنیم تا
// widget از همان ابتدا با تم روشن و متن فارسی init شود.
const el = ref.current;
if (el) {
el.setAttribute("challengeurl", `${API}/api/v1/altcha/challenge`);
el.setAttribute("strings", FA_STRINGS);
el.setAttribute("theme", "light");
el.setAttribute("auto", "onload");
el.addEventListener("statechange", onStateChange);
}
import("altcha");
return () => {
el?.removeEventListener("statechange", onStateChange);
};
}, [enabled, onVerified]);
if (enabled !== true) return null;
return (
<altcha-widget
ref={ref}
style={{ display: "block", marginTop: 16, marginBottom: 20 }}
/>
);
}