diff --git a/src/app/[locale]/sign-in/reset-code/icons/key.svg b/src/app/[locale]/sign-in/reset-code/icons/key.svg new file mode 100644 index 0000000..88beab1 --- /dev/null +++ b/src/app/[locale]/sign-in/reset-code/icons/key.svg @@ -0,0 +1,14 @@ + + + Created with Pixso. + + + + + + + + + + + diff --git a/src/app/[locale]/sign-in/reset-code/page.tsx b/src/app/[locale]/sign-in/reset-code/page.tsx new file mode 100644 index 0000000..4e48aab --- /dev/null +++ b/src/app/[locale]/sign-in/reset-code/page.tsx @@ -0,0 +1,29 @@ +import Image from "next/image"; +import key from "./icons/key.svg"; +import ResetCodeForm from "@/widgets/forms/ResetCodeForm"; + +const ResetCode = () => { + return ( +
+
+
+ Key Icon +
+ +
+

+ Введите новый пароль +

+

+ Пароль должен содерждать минимум 8 символов, 1 заглавная буква и + цифра +

+
+ + +
+
+ ); +}; + +export default ResetCode; diff --git a/src/widgets/forms/ResetCodeForm.tsx b/src/widgets/forms/ResetCodeForm.tsx new file mode 100644 index 0000000..df2b86d --- /dev/null +++ b/src/widgets/forms/ResetCodeForm.tsx @@ -0,0 +1,174 @@ +"use client"; + +import AuthInput from "@/features/AuthInput/AuthInput"; +import { useState } from "react"; +import { apiInstance } from "@/shared/config/apiConfig"; +import { ITokens } from "@/shared/types/token-type"; +import { useRouter } from "@/shared/config/navigation"; +import { AxiosError } from "axios"; +import Loader from "@/shared/ui/Loader/Loader"; +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import Image from "next/image"; +import eye_off from "./icons/eye-off.svg"; +import eye_on from "./icons/eye-on.svg"; +import alert from "./icons/alert-circle.svg"; + +const ResetCodeForm = () => { + const [passwordWarning, setPasswordWarning] = useState(""); + const [passwordConfirmWarning, setPasswordConfirmWarning] = + useState(""); + const [error, setError] = useState(""); + const [loader, setLoader] = useState(false); + const [showPasswordOne, setShowPasswordOne] = useState(false); + const [showPasswordTwo, setShowPasswordTwo] = useState(false); + + const router = useRouter(); + + const resetCodeFormScheme = z + .object({ + new_password1: z + .string() + .min(8, "Пароль должен содержать минимум 8 символов"), + new_password2: z + .string() + .min(8, "Пароль должен содержать минимум 8 символов"), + }) + .refine((data) => data.new_password1 === data.new_password2, { + message: "Пароли не совпадают", + path: ["new_password2"], + }); + type FormFields = z.infer; + + const { + register, + handleSubmit, + formState: { errors, isSubmitting }, + } = useForm({ + resolver: zodResolver(resetCodeFormScheme), + }); + + const onSubmit = async (data: FormFields) => { + try { + setError(""); + setLoader(true); + + const storage = localStorage.getItem("transitional"); + if (storage === null) return; + const transitional: ITokens = JSON.parse(storage); + + const Authorization = `Bearer ${transitional.access_token}`; + + const config = { + headers: { + Authorization, + }, + }; + + const response = await apiInstance.patch( + "/auth/password_reset/", + data, + config + ); + + if ([200, 201].includes(response.status)) { + localStorage.removeItem("transitional"); + router.push("/sign-in"); + } + } catch (error) { + if (error instanceof AxiosError) { + if ( + [500, 501, 502, 503, 504].includes(error.response?.status as number) + ) { + setError("Ошибка на стороне сервера"); + } else if ([400, 404].includes(error.response?.status as number)) { + setError("Слабый пароль, прошу избегайте очевидных паролей"); + } + } else { + setError("Произошла непредвиденная ошибка"); + } + } finally { + setLoader(false); + } + }; + + return ( +
+
+
+ +
+ + +
+ {errors?.new_password1?.message && ( +

+ {errors.new_password1.message}{" "} + Alert Icon +

+ )} +
+
+ +
+ + +
+ {errors?.new_password2?.message && ( +

+ {errors.new_password2.message}{" "} + Alert Icon +

+ )} +
+
+ {errors.root && ( +

{errors.root.message}

+ )} + {error ?

{error}

: null} + +
+ ); +}; + +export default ResetCodeForm;