diff --git a/SerpentRace_Frontend/src/api/userApi.js b/SerpentRace_Frontend/src/api/userApi.js
index 80d99ca5..db92ba47 100644
--- a/SerpentRace_Frontend/src/api/userApi.js
+++ b/SerpentRace_Frontend/src/api/userApi.js
@@ -1,67 +1,75 @@
-import axios from 'axios';
-
+import axios from "axios"
export const API_CONFIG = {
- baseURL: import.meta.env.VITE_API_URL+'/api',
- wsURL: 'http://localhost:3000',
+ baseURL: import.meta.env.VITE_API_URL + "/api",
+ wsURL: "http://localhost:3000",
timeout: 10000,
- retryAttempts: 3
-};
+ retryAttempts: 3,
+}
const apiClient = axios.create({
baseURL: API_CONFIG.baseURL,
timeout: API_CONFIG.timeout,
withCredentials: true, // Important for cookie-based auth
headers: {
- 'Content-Type': 'application/json'
- }
-});
-
+ "Content-Type": "application/json",
+ },
+})
// Add request interceptor for debugging
apiClient.interceptors.request.use(
(config) => {
- console.log('Request URL:', config.url);
- console.log('Request headers:', config.headers);
- console.log('Current cookies:', document.cookie);
- return config;
+ console.log("Request URL:", config.url)
+ console.log("Request headers:", config.headers)
+ console.log("Current cookies:", document.cookie)
+ return config
},
(error) => {
- return Promise.reject(error);
+ return Promise.reject(error)
}
-);
+)
// Add response interceptor for debugging cookies
apiClient.interceptors.response.use(
(response) => {
- console.log('Response status:', response.status);
- console.log('Response headers:', response.headers);
- console.log('Set-Cookie headers:', response.headers['set-cookie']);
- console.log('Cookies after response:', document.cookie);
- return response;
+ console.log("Response status:", response.status)
+ console.log("Response headers:", response.headers)
+ console.log("Set-Cookie headers:", response.headers["set-cookie"])
+ console.log("Cookies after response:", document.cookie)
+ return response
},
(error) => {
- console.error('API Error:', error.response?.data || error.message);
- return Promise.reject(error);
+ console.error("API Error:", error.response?.data || error.message)
+ return Promise.reject(error)
}
-);
+)
//login
export const login = async (username, password) => {
- try {
- const response = await apiClient.post('/users/login', { username, password });
- return response.data;
- } catch (error) {
- throw error;
- }
-};
+ try {
+ const response = await apiClient.post("/users/login", { username, password })
+ return response.data
+ } catch (error) {
+ throw error
+ }
+}
//register
export const register = async (username, email, password, fname, lname, phone) => {
- try {
- const response = await apiClient.post('/users/create', { username, email, password, fname, lname, phone });
- return response.data;
- } catch (error) {
- throw error;
- }
-};
\ No newline at end of file
+ try {
+ const response = await apiClient.post("/users/create", { username, email, password, fname, lname, phone })
+ return { ...response.data, status: response.status }
+ } catch (error) {
+ throw error
+ }
+}
+
+//verify email
+export const verifyEmail = async (token) => {
+ try {
+ const response = await apiClient.get(`/users/verify-email/${token}`)
+ return response.data
+ } catch (error) {
+ throw error
+ }
+}
diff --git a/SerpentRace_Frontend/src/pages/Auth/AuthCard.jsx b/SerpentRace_Frontend/src/pages/Auth/AuthCard.jsx
index 520b4381..43278921 100644
--- a/SerpentRace_Frontend/src/pages/Auth/AuthCard.jsx
+++ b/SerpentRace_Frontend/src/pages/Auth/AuthCard.jsx
@@ -1,46 +1,44 @@
// src/pages/Auth/AuthLogin.jsx
// Kártya amelyiken a bejelentkezés és regisztráció van
-import { motion, AnimatePresence } from "framer-motion";
-import Animation from "../../assets/SerpentRace_Animation/SerpentRace_Animation";
-import LoginForm from "./LoginForm";
-import RegisterForm from "./RegisterForm";
-import Logo from "../../assets/pictures/Logo";
+import { motion, AnimatePresence } from "framer-motion"
+import Animation from "../../assets/SerpentRace_Animation/SerpentRace_Animation"
+import LoginForm from "./LoginForm"
+import RegisterForm from "./RegisterForm"
+import Logo from "../../assets/pictures/Logo"
export default function AuthCard({ isRegistering, setIsRegistering }) {
return (
{/* Bal oldali kép és szöveg */}
-
+
- Lépj be és légy a legjobb!
+ Lépj be és légy a legjobb!
{/* Jobb oldali űrlap */}
-
- {isRegistering ? : }
-
+
{isRegistering ? : }
setIsRegistering(!isRegistering)}
>
- {isRegistering
- ? "Már van fiókod? Jelentkezz be itt!"
- : "Nincs még fiókod? Regisztrálj itt!"}
+ {isRegistering ? "Már van fiókod? Jelentkezz be itt!" : "Nincs még fiókod? Regisztrálj itt!"}
- );
+ )
}
diff --git a/SerpentRace_Frontend/src/pages/Auth/EmailVerification.jsx b/SerpentRace_Frontend/src/pages/Auth/EmailVerification.jsx
index 1a018745..5566eadc 100644
--- a/SerpentRace_Frontend/src/pages/Auth/EmailVerification.jsx
+++ b/SerpentRace_Frontend/src/pages/Auth/EmailVerification.jsx
@@ -1,58 +1,94 @@
// src/pages/Auth/EmailVerification.jsx
// Rublikák a kód beírásához, email ellenőrzéshez
-import { useState, useRef } from "react";
-import Background from "../../assets/backgrounds/Background";
-import { motion } from "framer-motion";
-import Button from "../../components/Buttons/Button";
-
+import { useState, useRef, useEffect } from "react"
+import Background from "../../assets/backgrounds/Background"
+import { motion } from "framer-motion"
+import Button from "../../components/Buttons/Button"
+import { useLocation } from "react-router-dom"
export default function EmailVerification() {
- const [code, setCode] = useState(Array(6).fill(""));
- const inputRefs = useRef([]);
+ const [code, setCode] = useState(Array(6).fill(""))
+ const inputRefs = useRef([])
+ const location = useLocation()
+ const [showSuccess, setShowSuccess] = useState(false)
+ const [error, setError] = useState("")
+
+ useEffect(() => {
+ if (location.state && location.state.success) {
+ setShowSuccess(true)
+ setTimeout(() => setShowSuccess(false), 1500)
+ }
+ }, [location.state])
const handleChange = (e, index) => {
- const { value } = e.target;
+ const { value } = e.target
if (/^\d*$/.test(value) && value.length <= 1) {
- const newCode = [...code];
- newCode[index] = value;
- setCode(newCode);
+ const newCode = [...code]
+ newCode[index] = value
+ setCode(newCode)
if (value && index < 5) {
- inputRefs.current[index + 1].focus();
+ inputRefs.current[index + 1].focus()
}
}
- };
+ }
const handleKeyDown = (e, index) => {
if (e.key === "Backspace" && !code[index] && index > 0) {
- inputRefs.current[index - 1].focus();
+ inputRefs.current[index - 1].focus()
} else if (e.key === "ArrowLeft" && index > 0) {
- inputRefs.current[index - 1].focus();
+ inputRefs.current[index - 1].focus()
} else if (e.key === "ArrowRight" && index < 5) {
- inputRefs.current[index + 1].focus();
+ inputRefs.current[index + 1].focus()
} else if (/^\d$/.test(e.key) && code[index]) {
- e.preventDefault();
- const newCode = [...code];
- newCode[index] = e.key;
- setCode(newCode);
-
+ e.preventDefault()
+ const newCode = [...code]
+ newCode[index] = e.key
+ setCode(newCode)
+
if (index < 5) {
setTimeout(() => {
- inputRefs.current[index + 1].focus();
- }, 0);
+ inputRefs.current[index + 1].focus()
+ }, 0)
}
}
- };
+ }
- const handleSubmit = (e) => {
- e.preventDefault();
- console.log("Kód:", code.join(""));
- // Backend API
- };
+ const handleSubmit = async (e) => {
+ e.preventDefault()
+ setError("")
+ const token = code.join("")
+ if (token.length !== 6) {
+ setError("A kód 6 számjegyből áll.")
+ return
+ }
+ try {
+ const res = await fetch(`/verify-email/${token}`)
+ const data = await res.json()
+ if (data.success) {
+ setShowSuccess(true)
+ setTimeout(() => setShowSuccess(false), 2000)
+ } else {
+ setError(data.message || "Sikertelen ellenőrzés.")
+ }
+ } catch (err) {
+ setError("Hiba történt az ellenőrzés során.")
+ }
+ }
return (
+ {showSuccess && (
+
+ Sikeres email ellenőrzés!
+
+ )}
+ {error && (
+
+ {error}
+
+ )}
handleChange(e, index)}
onKeyDown={(e) => handleKeyDown(e, index)}
ref={(el) => (inputRefs.current[index] = el)}
- className={`w-12 h-12 px-2 py-3 border rounded-lg focus:ring-4 focus:ring-indigo-400 text-gray-700 placeholder-gray-400 bg-gray-50 text-center text-2xl tracking-widest ${!digit ? 'placeholder-opacity-100' : 'placeholder-opacity-0'}`}
+ className={`w-12 h-12 px-2 py-3 border rounded-lg focus:ring-4 focus:ring-indigo-400 text-gray-700 placeholder-gray-400 bg-gray-50 text-center text-2xl tracking-widest ${
+ !digit ? "placeholder-opacity-100" : "placeholder-opacity-0"
+ }`}
// nem tudom, hogy hogyan jobb
// placeholder="_"
maxLength="1"
@@ -85,5 +123,5 @@ export default function EmailVerification() {
- );
-}
\ No newline at end of file
+ )
+}
diff --git a/SerpentRace_Frontend/src/pages/Auth/LoginForm.jsx b/SerpentRace_Frontend/src/pages/Auth/LoginForm.jsx
index 5d5df321..f06de31c 100644
--- a/SerpentRace_Frontend/src/pages/Auth/LoginForm.jsx
+++ b/SerpentRace_Frontend/src/pages/Auth/LoginForm.jsx
@@ -1,42 +1,52 @@
// src/pages/Auth/LoginForm.jsx
// Bejelentkezési űrlap
-import InputBox from "../../components/Inputs/InputBox";
-import Button from "../../components/Buttons/Button";
-import { motion } from "framer-motion";
-import { useState } from "react";
-import { login } from "../../api/userApi";
+import InputBox from "../../components/Inputs/InputBox"
+import Button from "../../components/Buttons/Button"
+import { motion } from "framer-motion"
+import { useState, useEffect } from "react"
+import { useLocation } from "react-router-dom"
+import { login } from "../../api/userApi"
export default function LoginForm() {
- const [email, setEmail] = useState("");
- const [password, setPassword] = useState("");
- const [error, setError] = useState("");
+ const [email, setEmail] = useState("")
+ const [password, setPassword] = useState("")
+ const [error, setError] = useState("")
+ const location = useLocation()
+ const [showSuccess, setShowSuccess] = useState(false)
+
+ useEffect(() => {
+ if (location.state && location.state.success) {
+ setShowSuccess(true)
+ setTimeout(() => setShowSuccess(false), 4000)
+ }
+ }, [location.state])
function validateEmail(email) {
- return /\S+@\S+\.\S+/.test(email);
+ return /\S+@\S+\.\S+/.test(email)
}
const handleSubmit = (e) => {
- e.preventDefault();
- setError("");
+ e.preventDefault()
+ setError("")
if (!email || !password) {
- setError("Minden mező kitöltése kötelező.");
- return;
+ setError("Minden mező kitöltése kötelező.")
+ return
}
if (!validateEmail(email)) {
- setError("Hibás email formátum.");
- return;
+ setError("Hibás email formátum.")
+ return
}
// Backend API
login(email, password)
.then((data) => {
- console.log(data);
- console.log("Bejelentkezés:", { email, password });
+ console.log(data)
+ console.log("Bejelentkezés:", { email, password })
})
.catch((error) => {
- setError("Hibás bejelentkezési adatok.");
- });
- };
+ setError("Hibás bejelentkezési adatok.")
+ })
+ }
return (
Bejelentkezés
- {error && (
- {error}
+ {showSuccess && (
+
+ Sikeres regisztráció! Az email ellenőrzése után be tudsz lépni.
+
)}
+ {error && {error}
}
- );
+ )
}
diff --git a/SerpentRace_Frontend/src/pages/Auth/RegisterForm.jsx b/SerpentRace_Frontend/src/pages/Auth/RegisterForm.jsx
index 8dbf46f6..b3a9ea4d 100644
--- a/SerpentRace_Frontend/src/pages/Auth/RegisterForm.jsx
+++ b/SerpentRace_Frontend/src/pages/Auth/RegisterForm.jsx
@@ -1,51 +1,79 @@
// src/pages/Auth/RegisterForm.jsx
// Regisztrációs űrlap
-import InputBox from "../../components/Inputs/InputBox";
-import Button from "../../components/Buttons/Button";
-import { motion } from "framer-motion";
-import { useState } from "react";
-import { register } from "../../api/userApi";
+import InputBox from "../../components/Inputs/InputBox"
+import Button from "../../components/Buttons/Button"
+import { motion } from "framer-motion"
+import { useState } from "react"
+import { register } from "../../api/userApi"
+import { useNavigate } from "react-router-dom"
export default function RegisterForm() {
- const [lastname, setLastname] = useState("");
- const [firstname, setFirstname] = useState("");
- const [username, setUsername] = useState("");
- const [email, setEmail] = useState("");
- const [password, setPassword] = useState("");
- const [confirmPassword, setConfirmPassword] = useState("");
- const [phone, setPhone] = useState("");
- const [error, setError] = useState("");
+ const [lastname, setLastname] = useState("")
+ const [firstname, setFirstname] = useState("")
+ const [username, setUsername] = useState("")
+ const [email, setEmail] = useState("")
+ const [password, setPassword] = useState("")
+ const [confirmPassword, setConfirmPassword] = useState("")
+ const [phone, setPhone] = useState("")
+ const [error, setError] = useState("")
+ const [showErrorPopup, setShowErrorPopup] = useState(false)
+ const navigate = useNavigate()
function validateEmail(email) {
- return /\S+@\S+\.\S+/.test(email);
+ return /\S+@\S+\.\S+/.test(email)
}
const handleSubmit = async (e) => {
- e.preventDefault();
- setError("");
+ e.preventDefault()
+ setError("")
+ setShowErrorPopup(false)
if (!lastname || !firstname || !username || !email || !password || !confirmPassword || !phone) {
- setError("Minden mező kitöltése kötelező.");
- return;
+ setError("Minden mező kitöltése kötelező.")
+ return
}
if (!validateEmail(email)) {
- setError("Hibás email formátum.");
- return;
+ setError("Hibás email formátum.")
+ return
}
if (password.length < 6) {
- setError("A jelszónak legalább 6 karakter hosszúnak kell lennie.");
- return;
+ setError("A jelszónak legalább 6 karakter hosszúnak kell lennie.")
+ return
}
if (password !== confirmPassword) {
- setError("A jelszavak nem egyeznek.");
- return;
+ setError("A jelszavak nem egyeznek.")
+ return
}
// Backend API
- const response = await register(username, email, password, firstname, lastname, phone);
- console.log(response);
- console.log("Regisztráció:", { username, email, password, firstname, lastname, phone });
- };
+ try {
+ const response = await register(username, email, password, firstname, lastname, phone)
+ // Check for 201 Created status
+ if (response && response.status === 201) {
+ navigate("/login", { state: { success: true } })
+ console.log(response)
+ console.log("Regisztráció:", { username, email, password, firstname, lastname, phone })
+ } else {
+ let msg = "Sikertelen regisztráció."
+ if (response && response.error) {
+ msg = response.error
+ }
+ setError(msg)
+ setShowErrorPopup(true)
+ setTimeout(() => setShowErrorPopup(false), 2000)
+ }
+ } catch (err) {
+ let msg = "Ismeretlen hiba történt."
+ if (err.response && err.response.data && err.response.data.error) {
+ msg = err.response.data.error
+ } else if (err.message) {
+ msg = err.message
+ }
+ setError(msg)
+ setShowErrorPopup(true)
+ setTimeout(() => setShowErrorPopup(false), 2000)
+ }
+ }
return (
Regisztráció
- {error && (
- {error}
+ {showErrorPopup && error && (
+
+ {error}
+
)}
- );
+ )
}