Refactor code structure for improved readability and maintainability

This commit is contained in:
hamed
2026-07-10 11:27:17 +03:30
parent ab2ab0dea2
commit 778876b1f7
12 changed files with 318 additions and 139 deletions
+70
View File
@@ -0,0 +1,70 @@
"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);
// ثبت custom element فقط در مرورگر (وابسته به customElements/DOM).
useEffect(() => {
import("altcha");
}, []);
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(() => {
const el = ref.current;
if (!el) return;
const onStateChange = (e) => {
if (e.detail?.state === "verified" && e.detail.payload) {
onVerified(e.detail.payload);
}
};
el.addEventListener("statechange", onStateChange);
return () => el.removeEventListener("statechange", onStateChange);
}, [onVerified, enabled]);
if (enabled !== true) return null;
return (
<altcha-widget
ref={ref}
challengeurl={`${API}/api/v1/altcha/challenge`}
auto="onload"
strings={FA_STRINGS}
style={{ display: "block", marginTop: 12 }}
/>
);
}
+8 -1
View File
@@ -5,10 +5,13 @@ import { InputAdornment, Button, CircularProgress } from "@mui/material";
import Link from "next/link";
import { useState } from "react";
import { toast } from "react-toastify";
import Altcha from "@/components/Altcha";
function LogInPage({ setIsSendMsg, num, setNum, setUuid, matchedCity, setStep }) {
const [error, setError] = useState({ valid: true, text: "" });
const [loading, setLoading] = useState(false);
const [altcha, setAltcha] = useState("");
const [altchaKey, setAltchaKey] = useState(0); // remount widget برای challenge تازه بعد از خطا
const handleChange = (val) => {
const checkedNum = validatePhoneNumber(val);
@@ -24,7 +27,7 @@ function LogInPage({ setIsSendMsg, num, setNum, setUuid, matchedCity, setStep })
const handleReq = async () => {
setLoading(true);
request
.sendCode(num, "", typeof window !== "undefined" ? window.location.hostname : "")
.sendCode(num, altcha, typeof window !== "undefined" ? window.location.hostname : "")
.then((response) => {
setLoading(false);
if (response.uuid) {
@@ -36,6 +39,9 @@ function LogInPage({ setIsSendMsg, num, setNum, setUuid, matchedCity, setStep })
})
.catch(() => {
setLoading(false);
// challenge یک‌بارمصرف است؛ بعد از خطا widget را برای challenge تازه ری‌مانت کن
setAltcha("");
setAltchaKey((k) => k + 1);
});
};
@@ -64,6 +70,7 @@ function LogInPage({ setIsSendMsg, num, setNum, setUuid, matchedCity, setStep })
{error.text}
</p>
</div>
<Altcha key={altchaKey} onVerified={setAltcha} />
<Button
fullWidth
variant="contained"
+11 -2
View File
@@ -2,13 +2,16 @@ import RetryLogin from "@/components/icons/RetryLogin";
import { changeNumToDefault } from "@/helper";
import { request } from "@/services/response";
import { Button } from "@mui/material";
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import Altcha from "@/components/Altcha";
const time_resend_code = 120;
function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
const timerIntervalRef = useRef(null);
const animIntervalRef = useRef(null);
const [altcha, setAltcha] = useState("");
const [altchaKey, setAltchaKey] = useState(0);
useEffect(() => {
return () => {
@@ -49,7 +52,7 @@ function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
rotateIcon();
}, 1200);
request
.sendCode(changeNumToDefault(num), "", typeof window !== "undefined" ? window.location.hostname : "")
.sendCode(changeNumToDefault(num), altcha, typeof window !== "undefined" ? window.location.hostname : "")
.then((response) => {
clearInterval(animIntervalRef.current);
animIntervalRef.current = null;
@@ -61,10 +64,15 @@ function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
.catch(() => {
clearInterval(animIntervalRef.current);
animIntervalRef.current = null;
// challenge یک‌بارمصرف؛ برای تلاش بعدی تازه بگیر
setAltcha("");
setAltchaKey((k) => k + 1);
});
};
return (
<>
<Altcha key={altchaKey} onVerified={setAltcha} />
<Button
className="flex !p-1 items-center justify-start gap-1 hover-rotate-90 cursor-pointer"
disabled={typeof timer === "number" && timer !== 0}
@@ -89,6 +97,7 @@ function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
</>
)}
</Button>
</>
);
}