procurement-frontend2/src/widgets/forms/ConfirmEmailForm/ConfirmEmailForm.tsx

148 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useEffect, useState } from "react";
import { apiInstance } from "@/shared/config/apiConfig";
import { useRouter } from "@/shared/config/navigation";
import { AxiosError } from "axios";
import Loader from "@/shared/ui/Loader/Loader";
import s from "./ConfirmEmailForm.module.scss";
interface IConfirmEmailFormProps {
email: string;
}
const ConfirmEmailForm: React.FC<IConfirmEmailFormProps> = ({
email,
}: IConfirmEmailFormProps) => {
const router = useRouter();
const [otp, setOtp] = useState(new Array(6).fill(""));
const [seconds, setSeconds] = useState<number>(0);
const [minutes, setMinutes] = useState<number>(1);
const [error, setError] = useState<string>("");
const [loader, setLoader] = useState<boolean>(false);
const handleChange = (e: any, index: number) => {
if (isNaN(+e.target.value)) return false;
setOtp([...otp.map((data, i) => (i === index ? e.target.value : data))]);
if (e.target.value && e.target.nextSibling) {
e.target.nextSibling.focus();
} else if (!e.target.value && e.target.previousSibling) {
e.target.previousSibling.focus();
}
};
const handleSubmit: React.MouseEventHandler<HTMLFormElement> = async (e) => {
e.preventDefault();
const code = {
code: +otp.join(""),
};
try {
setLoader(true);
const response = await apiInstance.post("/users/confirm/", code);
if (response.status === 200 || response.status === 201) {
router.push("/sign-in");
}
} catch (error: unknown) {
if (error instanceof AxiosError) {
if ([400, 404].includes(error.response?.status as number)) {
setError("Неверный код подтверждения");
} else {
setError("Ошибка на стороне сервера");
}
} else {
setError("Произошла непредвиденная ошибка");
}
} finally {
setLoader(false);
}
};
const handleClick = async () => {
try {
const data = {
email,
};
const response = await apiInstance.post("/users/resend_code/", data);
if ([200, 201].includes(response.status)) {
setMinutes(1);
}
} catch (error) {
setError(
"Проблема на стороне сервера или вы достигли максимальное количество попыток"
);
}
};
useEffect(() => {
if (minutes === 0 && seconds === 0) return;
const timer = setInterval(() => {
if (seconds === 0) {
setMinutes((prev) => Math.max(0, prev - 1));
setSeconds(59);
} else {
setSeconds((prev) => prev - 1);
}
}, 1000);
return () => clearInterval(timer);
}, [minutes, seconds]);
return (
<form onSubmit={handleSubmit} className={s.confirmEmailForm}>
<div className={s.confirmEmailForm__inputs}>
<label>Код подтверждения</label>
<div className={s.confirmEmailForm__inputsWrapper}>
{otp.map((data, index) => (
<input
id={data ? s.confirmEmailForm__inputActive : ""}
key={index}
onChange={(e) => handleChange(e, index)}
value={data}
maxLength={1}
type="text"
/>
))}
</div>
{error ? <p className={s.confirmEmailForm__error}>{error}</p> : null}
</div>
<button
disabled={otp.join("").length === 6 ? false : true}
id={`${s.confirmEmailForm__sendCode}${
otp.join("").length === 6 ? "__active" : ""
}`}
type="submit"
>
{loader ? <Loader /> : "Подтвердить"}
</button>
<p className={s.confirmEmailForm__timer}>
Отправить код повторно через{" "}
<span>
0{minutes}:{seconds.toString().length === 1 ? `0${seconds}` : seconds}
</span>
</p>
<button
type="button"
onClick={handleClick}
disabled={minutes === 0 && seconds === 0 ? false : true}
id={`${s.confirmEmailForm__resendCode}${
minutes === 0 && seconds === 0 ? "__active" : ""
}`}
>
{loader ? <Loader /> : "Отправить код повторно"}
</button>
</form>
);
};
export default ConfirmEmailForm;