74 lines
2.7 KiB
JavaScript
74 lines
2.7 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;
|
|
|
|
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 شود. locale رسمی fa با
|
|
// import ماژول i18n ثبت و با language="fa" فعال میشود (RTL هم خودکار است).
|
|
const el = ref.current;
|
|
if (el) {
|
|
el.setAttribute("challengeurl", `${API}/api/v1/altcha/challenge`);
|
|
el.setAttribute("language", "fa");
|
|
el.setAttribute("theme", "light");
|
|
el.setAttribute("auto", "onload");
|
|
el.addEventListener("statechange", onStateChange);
|
|
}
|
|
|
|
Promise.all([import("altcha/i18n/fa"), 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 }}
|
|
/>
|
|
);
|
|
}
|