148 lines
4.3 KiB
TypeScript
148 lines
4.3 KiB
TypeScript
"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;
|