diff --git a/enshi/src/Pages/LoginRegisterPage/LoginElement/LoginElement.tsx b/enshi/src/Pages/LoginRegisterPage/LoginElement/LoginElement.tsx index 650fe85..3b00098 100644 --- a/enshi/src/Pages/LoginRegisterPage/LoginElement/LoginElement.tsx +++ b/enshi/src/Pages/LoginRegisterPage/LoginElement/LoginElement.tsx @@ -1,28 +1,43 @@ import * as Form from "@radix-ui/react-form"; import { CrossCircledIcon } from "@radix-ui/react-icons"; import { Button, Card, Heading, Text, TextField } from "@radix-ui/themes"; -import { useEffect, useState } from "react"; +import { useMutation } from "@tanstack/react-query"; +import { t } from "i18next"; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { axiosLocalhost } from "../../../api/axios/axios"; +import UseCapsLock from "../../../hooks/useCapsLock"; import ShowPasswordButton from "../ShowPasswordButton/ShowPasswordButton"; +type TLoginData = { + username: string; + password: string; +}; + export default function LoginElement() { const [showPassword, setShowPassword] = useState(false); - const [isCapsLockOn, setIsCapsLockOn] = useState(false); + const { isCapsLockOn } = UseCapsLock(); + const [isError, setIsError] = useState(false); - useEffect(() => { - const f = (e: KeyboardEvent) => { - if (e.getModifierState("CapsLock")) { - setIsCapsLockOn(true); - } else { - setIsCapsLockOn(false); - } - }; + const navigate = useNavigate() - document.addEventListener("keydown", f); + const logInMutation = useMutation({ + mutationFn: async (data: TLoginData) => { + await axiosLocalhost.post( + "/login", + JSON.stringify(data) + ); + }, - return () => { - document.removeEventListener("keydown", f); - }; - }, []); + onError: (error, _variables, _context) => { + console.log(error); + setIsError(true); + }, + + onSuccess: () => { + navigate("/") + }, + }); return ( - Log in form + {t("loginForm")} - + { + e.preventDefault(); + let formData = new FormData( + document.querySelector("form") as HTMLFormElement + ); + + let loginData: TLoginData = { + password: (formData.get("password") as string) || "", + username: (formData.get("username") as string) || "", + }; + + logInMutation.mutate(loginData); + }} + >
- Username + {t("username")} - Please enter your username + {t("errors.enterUsername")}
@@ -70,10 +99,10 @@ export default function LoginElement() {
- Password + {t("password")} - Please enter your password + {t("errors.enterPassword")}
@@ -103,60 +132,17 @@ export default function LoginElement() {
- {/* -
- - Confirm password - - - Please enter your password - - - value !== formData.get("password") - } - > - Passwords must be the same - -
- - - - {(validity) => ( - - - - )} - - - -
*/} + - -
diff --git a/enshi/src/Pages/LoginRegisterPage/LoginRegisterPage.tsx b/enshi/src/Pages/LoginRegisterPage/LoginRegisterPage.tsx index ebe5a7a..ade733c 100644 --- a/enshi/src/Pages/LoginRegisterPage/LoginRegisterPage.tsx +++ b/enshi/src/Pages/LoginRegisterPage/LoginRegisterPage.tsx @@ -1,10 +1,16 @@ -import { useState } from "react"; import LoginElement from "./LoginElement/LoginElement"; +import RegisterElement from "./RegisterElement/RegisterElement"; -export default function LoginRegisterPage() { - const [isRegister, setIsRegister] = useState(false) +export function LoginPage() { return ( ) +} + +export function RegisterPage() { + + return ( + + ) } \ No newline at end of file diff --git a/enshi/src/Pages/LoginRegisterPage/RegisterElement/RegisterElement.tsx b/enshi/src/Pages/LoginRegisterPage/RegisterElement/RegisterElement.tsx new file mode 100644 index 0000000..21c3f62 --- /dev/null +++ b/enshi/src/Pages/LoginRegisterPage/RegisterElement/RegisterElement.tsx @@ -0,0 +1,241 @@ +import * as Form from "@radix-ui/react-form"; +import { CrossCircledIcon } from "@radix-ui/react-icons"; +import { Button, Card, Heading, Text, TextField } from "@radix-ui/themes"; +import { useMutation } from "@tanstack/react-query"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { axiosLocalhost } from "../../../api/axios/axios"; +import UseCapsLock from "../../../hooks/useCapsLock"; +import ShowPasswordButton from "../ShowPasswordButton/ShowPasswordButton"; + +type TRegisterData = { + username: string; + password: string; + email: string; +}; + +export default function RegisterElement() { + const [showPassword, setShowPassword] = useState(false); + const [showConfPassword, setShowConfPassword] = useState(false); + const { isCapsLockOn } = UseCapsLock(); + + const { t } = useTranslation(); + + const [isError, setIsError] = useState(false); + + const navigate = useNavigate(); + + const registerMutation = useMutation({ + mutationFn: async (data: TRegisterData) => { + await axiosLocalhost.post("/users", JSON.stringify(data)); + }, + + onError: (error, _variables, _context) => { + console.log(error); + setIsError(true); + }, + + onSuccess: () => { + navigate("/"); + }, + }); + + return ( + + + {t("registerForm")} + + { + e.preventDefault(); + let formData = new FormData( + document.querySelector("form") as HTMLFormElement + ); + + let registerData: TRegisterData = { + password: (formData.get("password") as string) || "", + username: (formData.get("username") as string) || "", + email: (formData.get("email") as string) || "", + }; + + registerMutation.mutate(registerData); + }} + > + +
+ + {t("username")} + + + {t("errors.enterUsername")} + +
+ + + + {(validity) => ( + + + + )} + + + +
+ + +
+ + {t("email")} + + + {t("errors.enterEmail")} + + + {t("errors.invalidEmail")} + +
+ + + + {(validity) => ( + + + + )} + + + +
+ + +
+ + {t("password")} + + + {t("errors.enterPassword")} + +
+ + + + {(validity) => ( + + + + )} + + + + +
+ + +
+ + {t("confirmPassword")} + + + {t("errors.enterPassword")} + + + value !== formData.get("password") + } + > + + {t("errors.passwordsMismatch")} + + +
+ + + + {(validity) => ( + + + + )} + + + + +
+ + + + + + +
+
+ ); +} diff --git a/enshi/src/api/axios/axios.ts b/enshi/src/api/axios/axios.ts index 1a352da..858e9a0 100644 --- a/enshi/src/api/axios/axios.ts +++ b/enshi/src/api/axios/axios.ts @@ -2,7 +2,7 @@ import axios from "axios"; export const axiosLocalhost = axios.create( { - baseURL: `http://localhost:9876/`, + baseURL: `http://127.0.0.1:9876/`, withCredentials: true, headers: { diff --git a/enshi/src/hooks/useCapsLock.tsx b/enshi/src/hooks/useCapsLock.tsx new file mode 100644 index 0000000..04abe26 --- /dev/null +++ b/enshi/src/hooks/useCapsLock.tsx @@ -0,0 +1,27 @@ +import { useEffect, useState } from "react"; + +export default function UseCapsLock() { + + const [isCapsLockOn, setIsCapsLockOn] = useState(false); + + useEffect(() => { + const f = (e: KeyboardEvent) => { + if (e.getModifierState("CapsLock")) { + setIsCapsLockOn(true); + } else { + setIsCapsLockOn(false); + } + }; + + document.addEventListener("keydown", f); + + return () => { + document.removeEventListener("keydown", f); + }; + }, []); + + + return { + isCapsLockOn + } +} \ No newline at end of file diff --git a/enshi/src/locale/en.ts b/enshi/src/locale/en.ts index bd15612..c955807 100644 --- a/enshi/src/locale/en.ts +++ b/enshi/src/locale/en.ts @@ -1,6 +1,26 @@ const en = { hello: "hello!", search: "Search...", -} + username: "Username", + email: "Email", + password: "Password", + confirmPassword: "Confirm password", + submit: "Submit", -export default en; \ No newline at end of file + capsLogWarning: "CapsLock is on", + + registerForm: "Register", + loginForm: "Log in", + + errors: { + enterUsername: "Please enter your username", + enterEmail: "Please enter your email", + invalidEmail: "Please enter correct email", + enterPassword: "Please enter your password", + passwordsMismatch: "Passwords must be the same", + invalidLoginData: "Invalid username or password", + invalidRegisterData: "Invalid register data", + }, +}; + +export default en; diff --git a/enshi/src/locale/ru.ts b/enshi/src/locale/ru.ts index abba300..7d2cddc 100644 --- a/enshi/src/locale/ru.ts +++ b/enshi/src/locale/ru.ts @@ -1,6 +1,27 @@ const ru = { hello: "Привет!", search: "Поиск...", -} + username: "Имя пользователя", + email: "Электронная почта", + password: "Пароль", + confirmPassword: "Подтвердите пароль", + submit: "Подтвердить", -export default ru; \ No newline at end of file + capsLogWarning: "Включён CapsLock", + + registerForm: "Регистрация", + loginForm: "Вход", + + errors: { + enterUsername: "Пожалуйста, введите ваше имя пользователя", + enterEmail: "Пожалуйста, введите свой адрес электронной почты", + invalidEmail: "Пожалуйста, введите корректный адрес электронной почты", + enterPassword: "Пожалуйста, введите пароль", + passwordsMismatch: "Пароли должны быть одинаковыми", + invalidLoginData: "Неверное имя пользователя или пароль", + invalidRegisterData: + "Пользователь с таким адресом электронной почты или именем пользователя уже существует", + }, +}; + +export default ru; diff --git a/enshi/src/routes/routes.tsx b/enshi/src/routes/routes.tsx index 06d4356..db1bc25 100644 --- a/enshi/src/routes/routes.tsx +++ b/enshi/src/routes/routes.tsx @@ -1,6 +1,6 @@ import { Text } from "@radix-ui/themes"; import { createRoutesFromElements, Route, useRouteError } from "react-router-dom"; -import LoginRegisterPage from "../Pages/LoginRegisterPage/LoginRegisterPage"; +import { LoginPage, RegisterPage } from "../Pages/LoginRegisterPage/LoginRegisterPage"; import MainPage from "../Pages/MainPage/MainPage"; @@ -28,9 +28,13 @@ export const routes = createRoutesFromElements( } - element={} - > + element={} + /> - + } + element={} + /> ) \ No newline at end of file diff --git a/enshi_back/global/globalVars.go b/enshi_back/global/globalVars.go index a581119..0116c2b 100644 --- a/enshi_back/global/globalVars.go +++ b/enshi_back/global/globalVars.go @@ -1,7 +1,7 @@ package global const PathForCookies = "/" -const DomainForCookies = "localhost" +const DomainForCookies = "127.0.0.1" const SecureForCookies = false const HttpOnlyForCookies = false diff --git a/enshi_back/middleware/corsMiddleware.go b/enshi_back/middleware/corsMiddleware.go index ad20f2d..d0b2b8a 100644 --- a/enshi_back/middleware/corsMiddleware.go +++ b/enshi_back/middleware/corsMiddleware.go @@ -4,7 +4,7 @@ import "github.com/gin-gonic/gin" func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { - c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173") + c.Writer.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5173") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set( "Access-Control-Allow-Headers",