fix: resolve critical bugs and security issues across the project
Security: - Disable SSL verification only in development (lib/req.js) - Wrap all JSON.parse(cookie) calls in try-catch via safeJsonParse utility - Sanitize dangerouslySetInnerHTML in blog/clinic with sanitizeHtml utility - Fix open redirect in payment page — validate URL origin before redirect - Fix cookie cleanup on 401 — use js-cookie with correct domain scope Performance: - Wrap ItemDoctor with React.memo to prevent unnecessary re-renders - Replace <img> with Next.js <Image> in blog Caption component Functionality: - Fix memory leak in Recode.js — store intervals in refs, cleanup on unmount - Add null guard on retryIcon.current before classList manipulation - Fix getParsedUserInfo in helper to handle malformed cookie gracefully Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
1aa9f82d2a
commit
59e0a0fe4f
@@ -2,45 +2,66 @@ 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";
|
||||
|
||||
const time_resend_code = 120;
|
||||
|
||||
function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
|
||||
const timerIntervalRef = useRef(null);
|
||||
const animIntervalRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timerIntervalRef.current) clearInterval(timerIntervalRef.current);
|
||||
if (animIntervalRef.current) clearInterval(animIntervalRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleTimer = () => {
|
||||
setTimer("loading");
|
||||
if (timerIntervalRef.current) clearInterval(timerIntervalRef.current);
|
||||
setTimeout(() => {
|
||||
setTimer(time_resend_code);
|
||||
let timePresent = time_resend_code;
|
||||
const timerInterval = setInterval(() => {
|
||||
timerIntervalRef.current = setInterval(() => {
|
||||
timePresent--;
|
||||
setTimer(timePresent);
|
||||
|
||||
!timePresent && clearInterval(timerInterval);
|
||||
if (!timePresent) {
|
||||
clearInterval(timerIntervalRef.current);
|
||||
timerIntervalRef.current = null;
|
||||
}
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const rotateIcon = () => {
|
||||
if (!retryIcon.current) return;
|
||||
retryIcon.current.classList.add("retry-icon");
|
||||
setTimeout(() => {
|
||||
retryIcon.current && retryIcon.current.classList.remove("retry-icon");
|
||||
retryIcon.current?.classList.remove("retry-icon");
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const handleReq = () => {
|
||||
rotateIcon();
|
||||
const interval = setInterval(() => {
|
||||
if (animIntervalRef.current) clearInterval(animIntervalRef.current);
|
||||
animIntervalRef.current = setInterval(() => {
|
||||
rotateIcon();
|
||||
}, 1200);
|
||||
request
|
||||
.sendCode(changeNumToDefault(num), "")
|
||||
.then((response) => {
|
||||
clearInterval(interval);
|
||||
clearInterval(animIntervalRef.current);
|
||||
animIntervalRef.current = null;
|
||||
if (response.uuid) {
|
||||
setUuid(response.uuid);
|
||||
handleTimer();
|
||||
}
|
||||
})
|
||||
.catch(() => clearInterval(interval));
|
||||
.catch(() => {
|
||||
clearInterval(animIntervalRef.current);
|
||||
animIntervalRef.current = null;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -49,7 +70,6 @@ function Recode({ retryIcon, timer, setUuid, num, setTimer }) {
|
||||
disabled={typeof timer === "number" && timer !== 0}
|
||||
onClick={() => {
|
||||
if (!timer && timer !== "loading") {
|
||||
// handleTimer();
|
||||
handleReq();
|
||||
}
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user