diff --git a/src/features/ProfileAvatar/ProfileAvatar.scss b/src/features/ProfileAvatar/ProfileAvatar.scss index e8e8127..d91dcfb 100644 --- a/src/features/ProfileAvatar/ProfileAvatar.scss +++ b/src/features/ProfileAvatar/ProfileAvatar.scss @@ -11,11 +11,7 @@ object-fit: cover; } - input[type="file"] { - display: none; - } - - label { + &__change-btn { position: absolute; bottom: 0; right: 0; @@ -34,4 +30,126 @@ height: 22px; } } + + &__modal { + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + display: flex; + align-items: center; + justify-content: center; + + background-color: rgba(0, 0, 0, 0.5); + } + + &__wrapper { + position: relative; + max-width: 400px; + padding: 24px; + display: flex; + flex-direction: column; + align-items: center; + background-color: white; + border-radius: 15px; + box-shadow: 0px 16px 24px 0px rgba(0, 0, 0, 0.15); + } + + &__text { + div { + display: flex; + align-items: center; + justify-content: space-between; + + h4 { + font-size: 18px; + font-weight: 500; + line-height: 28px; + color: rgb(51, 65, 85); + } + + button { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid rgb(226, 232, 240); + border-radius: 50%; + } + } + + p { + width: 90%; + font-size: 14px; + font-weight: 400; + line-height: 20px; + color: rgb(100, 116, 139); + } + } + + &__user-img { + margin: 24px 0; + width: 130px; + height: 130px; + border-radius: 50%; + object-fit: cover; + } + + input[type="file"] { + display: none; + } + + &__btns { + display: flex; + align-items: center; + gap: 8px; + + button, + label { + min-width: 110px; + padding: 8px 16px; + margin-top: 24px; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: 500; + line-height: 20px; + border-radius: 8px; + cursor: pointer; + } + } + + &__blue-btn { + color: white; + background-color: rgb(72, 159, 225); + } + + &__gray-btn { + color: rgb(51, 65, 85); + border: 1px solid rgb(226, 232, 240); + background: rgb(255, 255, 255); + } + + &__message { + position: absolute; + bottom: 32px; + padding: 8px; + width: 302px; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 3px; + background-color: rgb(0, 0, 0); + font-size: 14px; + font-weight: 500; + line-height: 20px; + color: rgb(255, 255, 255); + + button { + font-size: 0; + } + } } diff --git a/src/features/ProfileAvatar/ProfileAvatar.tsx b/src/features/ProfileAvatar/ProfileAvatar.tsx index 74f093a..a9cf26c 100644 --- a/src/features/ProfileAvatar/ProfileAvatar.tsx +++ b/src/features/ProfileAvatar/ProfileAvatar.tsx @@ -3,9 +3,14 @@ import Image from "next/image"; import "./ProfileAvatar.scss"; import pen from "./icons/pen.svg"; +import close from "./icons/close.svg"; +import close_white from "./icons/close-white.svg"; import { authInstanse } from "@/shared/config/apiConfig"; import { useRouter } from "next/navigation"; import { useSession } from "next-auth/react"; +import { useState } from "react"; +import { AxiosError } from "axios"; +import Loader from "@/shared/ui/components/Loader/Loader"; interface IProfileAvatarProps { img: string; @@ -14,29 +19,109 @@ interface IProfileAvatarProps { const ProfileAvatar: React.FC = ({ img, }: IProfileAvatarProps) => { + const [modal, setModal] = useState(false); + const [display_image, setDisplayImage] = useState( + img + ); + const [isDeleting, setIsDeleting] = useState(false); + const [message, setMessage] = useState(false); + const def = + "https://api.kgroaduat.fishrungames.com/media/user_photo/default.webp"; + + const [success, setSuccess] = useState(""); + const [loader, setLoader] = useState(false); + const [error, setError] = useState(""); + const session = useSession(); const router = useRouter(); - const changeImage: React.ChangeEventHandler< - HTMLInputElement - > = async (e) => { - const formData = new FormData(); + + const handleChange: React.ChangeEventHandler = ( + e + ) => { if (e.target.files) { - const image = Array.from(e.target.files); - formData.append("image", image[0]); - } - - if (session.status === "unauthenticated") return; - - try { - const res = await authInstanse( - session.data?.access_token as string - ).patch("/users/update_image/", formData); - router.refresh(); - } catch (error) { - console.log(error); + setDisplayImage(e.target.files[0]); } }; + const changeImage = async () => { + const formData = new FormData(); + + if (session.status === "unauthenticated") return; + + if ( + typeof display_image === typeof "string" || + display_image === img + ) + return; + + formData.append("image", display_image); + + try { + setLoader(true); + const res = await authInstanse( + session.data?.access_token as string + ).patch("/users/update_image/", formData); + + setError(""); + setSuccess("Фото профиля обновлено"); + setMessage(true); + router.refresh(); + + setTimeout(() => { + setMessage(false); + }, 3000); + } catch (error: unknown) { + if (error instanceof AxiosError) { + setSuccess(""); + setError(error.message); + setMessage(true); + setTimeout(() => { + setMessage(false); + }, 3000); + } + } finally { + setLoader(false); + } + }; + + const returnDefaultImage = async () => { + if (session.status === "unauthenticated") return; + + try { + setLoader(true); + const res = await authInstanse( + session.data?.access_token as string + ).patch("/users/delete_image/", {}); + + setError(""); + setSuccess("Фото профиля удалено"); + setMessage(true); + setDisplayImage(def); + router.refresh(); + + setTimeout(() => { + setMessage(false); + }, 3000); + } catch (error: unknown) { + if (error instanceof AxiosError) { + setSuccess(""); + setError(error.message); + setMessage(true); + setTimeout(() => { + setMessage(false); + }, 3000); + } + } finally { + setLoader(false); + } + }; + + const imageIsString = + typeof display_image === "string" + ? display_image + : typeof display_image === "undefined" + ? "" + : URL.createObjectURL(display_image as File); return (
= ({ src={img} alt="User Image" /> -
); }; diff --git a/src/features/ProfileAvatar/icons/close-white.svg b/src/features/ProfileAvatar/icons/close-white.svg new file mode 100644 index 0000000..ab4a752 --- /dev/null +++ b/src/features/ProfileAvatar/icons/close-white.svg @@ -0,0 +1,14 @@ + + + Created with Pixso. + + + + + + + + + + + diff --git a/src/features/ProfileAvatar/icons/close.svg b/src/features/ProfileAvatar/icons/close.svg new file mode 100644 index 0000000..04f3f88 --- /dev/null +++ b/src/features/ProfileAvatar/icons/close.svg @@ -0,0 +1,14 @@ + + + Created with Pixso. + + + + + + + + + + + diff --git a/src/widgets/forms/SignUpForm/SignUpForm.tsx b/src/widgets/forms/SignUpForm/SignUpForm.tsx index ad2d514..a1f3098 100644 --- a/src/widgets/forms/SignUpForm/SignUpForm.tsx +++ b/src/widgets/forms/SignUpForm/SignUpForm.tsx @@ -24,6 +24,7 @@ const SignUpForm = () => { > = async (e) => { e.preventDefault(); const formData = new FormData(e.currentTarget); + const regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/; if (!formData.get("email")?.toString()) { setError(""); @@ -41,6 +42,26 @@ const SignUpForm = () => { return; } + if ((formData.get("password")?.toString().length as number) < 8) { + setError(""); + setEmailWarning(""); + setPasswordConfirmWarning(""); + setPasswordWarning( + "Пароль должен содержать минимум 8 символов" + ); + return; + } + + if (!regex.test(formData.get("password")?.toString() as string)) { + setError(""); + setEmailWarning(""); + setPasswordConfirmWarning(""); + setPasswordWarning( + "Пароль должен содержать по меньшей мере 1 прописную букву, одну заглавную букву и одну цифру" + ); + return; + } + if (!formData.get("password2")?.toString()) { setError(""); setEmailWarning(""); @@ -79,9 +100,15 @@ const SignUpForm = () => { } } catch (error: unknown) { if (error instanceof AxiosError) { - setError("Произошла непредвиденная ошибка"); + if (error.response?.status === 401) { + setError("Такой пользователь уже существует"); + } else if ( + error.response?.status.toString().slice(0, 1) === "5" + ) { + setError("Ошибка на стороне сервера"); + } } else { - setError("An error ocured"); + setError("Непредвиденная ошибка"); } } finally { setLoader(false);