Merge pull request '[#122] Email verifikáció https://project.mdnd-it.cc/work_packages/122 #70' (#70) from task/122-email-verifik-ci into main

Reviewed-on: #70
This commit was merged in pull request #70.
This commit is contained in:
2025-10-24 19:08:16 +00:00
3 changed files with 104 additions and 0 deletions
+2
View File
@@ -17,6 +17,7 @@ import GameScreen from "./pages/Game/GameScreen"
import Reports from "./pages/Report/Reports"
import Lobby from "./pages/Lobby/Lobby"
import { ToastConfig } from "./components/Toastify/toastifyServices" // ✅ fontos: named import, nem default!
import VerifyEmailPage from "./pages/Auth/VerifyEmailPage"
@@ -50,6 +51,7 @@ function App() {
<>
<Router>
<Routes>
<Route path="/verify-email" element={<VerifyEmailPage />} />
<Route path="/about" element={<About />} />
<Route path="/lobby" element={<Lobby />} />
<Route path="/register" element={<AuthRegister />} />
+13
View File
@@ -45,3 +45,16 @@ export const getUserStats = async () => {
throw error
}
}
// Email verification - POST
export const verifyEmail = async (token) => {
try {
const response = await apiClient.post(`/users/verify-email/${token}`);
return response;
} catch (error) {
throw error;
}
};
@@ -0,0 +1,89 @@
import { useEffect, useState, useRef } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import Background from "../../assets/backgrounds/Background";
import { notifySuccess, notifyError } from "../../components/Toastify/toastifyServices";
import { verifyEmail } from "../../api/userApi";
export default function VerifyEmailPage() {
const navigate = useNavigate();
const location = useLocation();
const [status, setStatus] = useState("loading");
const [message, setMessage] = useState("Email címe hitelesítés alatt...");
const hasNotified = useRef(false); // <-- ez biztosítja, hogy csak egyszer legyen a toast
useEffect(() => {
const queryParams = new URLSearchParams(location.search);
const token = queryParams.get("token");
if (!token) {
setStatus("error");
setMessage("Hiányzó hitelesítő token!");
if (!hasNotified.current) {
notifyError("❌ Hiányzó hitelesítő token!");
hasNotified.current = true;
}
return;
}
const verify = async () => {
try {
const response = await verifyEmail(token);
const data = response.data;
if (data?.success) {
setStatus("success");
setMessage("Sikeres hitelesítés!");
if (!hasNotified.current) {
notifySuccess("✅ Email címe sikeresen hitelesítve!");
hasNotified.current = true;
}
setTimeout(() => navigate("/login"), 2500);
} else {
throw new Error(data?.message || "Sikertelen hitelesítés");
}
} catch (err) {
setStatus("error");
setMessage("Sikertelen hitelesítés. Kérjük, vegye fel velünk a kapcsolatot!");
if (!hasNotified.current) {
notifyError("❌ Sikertelen hitelesítés!");
hasNotified.current = true;
}
}
};
verify();
}, [location, navigate]);
return (
<div className="w-full min-h-screen flex items-center justify-center relative overflow-hidden">
<div className="fixed inset-0 -z-10">
<Background />
</div>
<div className="bg-white/10 backdrop-blur-lg p-10 rounded-2xl shadow-lg text-center border border-white/20 max-w-md">
{status === "loading" && (
<div className="flex flex-col items-center gap-3 text-white">
<div className="w-10 h-10 border-4 border-white border-t-transparent rounded-full animate-spin"></div>
<p className="text-lg font-semibold">{message}</p>
</div>
)}
{status === "success" && (
<div className="flex flex-col items-center gap-3 text-green-300">
<span className="text-4xl"></span>
<p className="text-lg font-semibold">{message}</p>
<p className="text-sm text-gray-200">Átirányítás a bejelentkezéshez...</p>
</div>
)}
{status === "error" && (
<div className="flex flex-col items-center gap-3 text-red-300">
<span className="text-4xl"></span>
<p className="text-lg font-semibold text-center">{message}</p>
<p className="text-sm text-gray-200">support@serpentrace.hu</p>
</div>
)}
</div>
</div>
);
}