From 94943d49881cefd7b0ebe09110881a58ae230f3f Mon Sep 17 00:00:00 2001 From: Barni03 Date: Sun, 26 Oct 2025 17:46:21 +0100 Subject: [PATCH 1/2] Handlenavigate --- .../src/components/Footer/Footer.jsx | 50 ++++++---- .../src/components/Navbar/Navbar.jsx | 92 +++++++++++++------ .../src/pages/Landing/Landingpage.jsx | 24 +---- .../utils/HandleNavigate/HandleNavigate.jsx | 28 ++++++ 4 files changed, 126 insertions(+), 68 deletions(-) create mode 100644 SerpentRace_Frontend/src/utils/HandleNavigate/HandleNavigate.jsx diff --git a/SerpentRace_Frontend/src/components/Footer/Footer.jsx b/SerpentRace_Frontend/src/components/Footer/Footer.jsx index 1c2f277e..2c04d798 100644 --- a/SerpentRace_Frontend/src/components/Footer/Footer.jsx +++ b/SerpentRace_Frontend/src/components/Footer/Footer.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef, useState } from "react" -import { Link } from "react-router-dom" import Logo from "../../assets/pictures/Logo" +import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate" const ArrowUpIcon = () => @@ -8,6 +8,9 @@ const Footer = () => { const [isVisible, setIsVisible] = useState(false) const footerRef = useRef(null) + // ✅ Használjuk a navigációs függvényeket + const { goLanding, goAbout, goContacts } = HandleNavigate() + useEffect(() => { const observer = new IntersectionObserver( ([entry]) => { @@ -16,14 +19,10 @@ const Footer = () => { { threshold: 0.3 } ) - if (footerRef.current) { - observer.observe(footerRef.current) - } + if (footerRef.current) observer.observe(footerRef.current) return () => { - if (footerRef.current) { - observer.unobserve(footerRef.current) - } + if (footerRef.current) observer.unobserve(footerRef.current) } }, []) @@ -40,10 +39,18 @@ const Footer = () => {
{/* Logó */}
- + +
{/* Oldalak */} @@ -51,15 +58,24 @@ const Footer = () => { Oldalak - + + +
{/* Közösség */} @@ -103,7 +119,7 @@ const Footer = () => { {isVisible && ( + {/* Desktop Menu */}
{/* Bal oldali linkek */} - Főoldal - Rólunk - Kapcsolat + + + {/* Csak bejelentkezve */} {isLoggedIn && ( <> - Paklik - Statisztikák + + Paklik + + + Statisztikák + )} {/* Játék gomb */} - Játék + {/* Jobb oldali akciók */} {!isLoggedIn ? (
- Bejelentkezés - + {/* Elválasztó vonal */}
@@ -108,9 +129,19 @@ const Navbar = () => { xmlns="http://www.w3.org/2000/svg" > {menuOpen ? ( - + ) : ( - + )} @@ -121,26 +152,27 @@ const Navbar = () => { {/* Mobile Menu */} {menuOpen && (
- setMenuOpen(false)} className={navLinkClass}>Főoldal - setMenuOpen(false)} className={navLinkClass}>Rólunk - setMenuOpen(false)} className={navLinkClass}>Kapcsolat + + + + {isLoggedIn && ( <> setMenuOpen(false)} className={navLinkClass}>Paklik setMenuOpen(false)} className={navLinkClass}>Statisztikák )} - setMenuOpen(false)} className={navLinkClassPlay}>Játék + + {!isLoggedIn ? (
- setMenuOpen(false)} + {/* Elválasztó vonal mobilon */}
diff --git a/SerpentRace_Frontend/src/pages/Landing/Landingpage.jsx b/SerpentRace_Frontend/src/pages/Landing/Landingpage.jsx index 3b1f8a8a..21f3bf83 100644 --- a/SerpentRace_Frontend/src/pages/Landing/Landingpage.jsx +++ b/SerpentRace_Frontend/src/pages/Landing/Landingpage.jsx @@ -7,28 +7,10 @@ import Navbar from "../../components/Navbar/Navbar" import Footer from "../../components/Footer/Footer.jsx" import Background from "../../assets/backgrounds/Background.jsx" import LandingPage from "../../components/Landingpage/LandingPage.jsx" +import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate.jsx" export default function LandingPageMain() { - const navigate = useNavigate(); - - const handleNavigateToPlay = () => { - navigate("/login", { preventScrollReset: false }); - window.scrollTo(0, 0); - }; - - const handleNavigateToAuth = () => { - navigate("/companies", { preventScrollReset: false }); - window.scrollTo(0, 0); - }; - - const handleNavigateToGame = () => { - navigate("/home", { preventScrollReset: false }); - window.scrollTo(0, 0); - }; - - const handleNavigateToContacts = () => { - navigate("/contacts"); - }; + const { goHome, goLogin, goContacts, goAuth, } = HandleNavigate() return (
@@ -39,7 +21,7 @@ export default function LandingPageMain() {
- +
diff --git a/SerpentRace_Frontend/src/utils/HandleNavigate/HandleNavigate.jsx b/SerpentRace_Frontend/src/utils/HandleNavigate/HandleNavigate.jsx new file mode 100644 index 00000000..3e35b5d4 --- /dev/null +++ b/SerpentRace_Frontend/src/utils/HandleNavigate/HandleNavigate.jsx @@ -0,0 +1,28 @@ +// src/hooks/useAppNavigation.jsx +import { useNavigate } from "react-router-dom" + +/** + * Egy általános navigációs helper hook, amit bármelyik komponensben használhatsz. + * Minden funkció automatikusan a megfelelő útvonalra visz és visszagörget az oldal tetejére. + */ +export default function HandleNavigate() { + const navigate = useNavigate() + + const scrollTop = () => window.scrollTo(0, 0) + + const goTo = (path, preventScrollReset = false) => { + navigate(path, { preventScrollReset }) + scrollTop() + } + + return { + goTo, // általános útvonalváltó + goHome: () => goTo("/home"), + goLogin: () => goTo("/login"), + goAuth: () => goTo("/register"), + goCompanies: () => goTo("/companies"), + goContacts: () => goTo("/contacts"), + goAbout: () => goTo("/about"), + goLanding: () => goTo("/"), + } +} From 8c25c56e88b878103616497e3a95874c3675e748 Mon Sep 17 00:00:00 2001 From: magdo Date: Sun, 26 Oct 2025 19:59:02 +0100 Subject: [PATCH 2/2] Email verification Backend --- SerpentRace_Backend/src/Api/routers/userRouter.ts | 13 ++++++++----- .../src/Application/DTOs/DeckDto.ts | 2 +- .../src/Application/DTOs/Mappers/DeckMapper.ts | 4 ++-- .../Application/User/commands/CreateUserCommand.ts | 1 + .../User/commands/CreateUserCommandHandler.ts | 14 +++++++++++--- .../User/commands/RequestPasswordResetCommand.ts | 1 + .../commands/RequestPasswordResetCommandHandler.ts | 13 ++++++++++--- 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/SerpentRace_Backend/src/Api/routers/userRouter.ts b/SerpentRace_Backend/src/Api/routers/userRouter.ts index 6691c60c..db8c1625 100644 --- a/SerpentRace_Backend/src/Api/routers/userRouter.ts +++ b/SerpentRace_Backend/src/Api/routers/userRouter.ts @@ -77,10 +77,12 @@ userRouter.post('/create', email: req.body.email }); - const result = await container.createUserCommandHandler.execute(req.body); - - logRequest('User created successfully', req, res, { - username: result.username + const language = req.header('Accept-Language') || 'en'; + + const result = await container.createUserCommandHandler.execute({ ...req.body, language }); + + logRequest('User created successfully', req, res, { + username: result.username }); res.status(201).json(result); @@ -268,10 +270,11 @@ userRouter.post('/forgot-password', async (req, res) => { try { const { email } = req.body; + const language = req.header('Accept-Language') || 'en'; logRequest('Forgot password endpoint accessed', req, res, { email }); - const result = await container.requestPasswordResetCommandHandler.execute({ email }); + const result = await container.requestPasswordResetCommandHandler.execute({ language, email }); if (result) { logAuth('Password reset request successful', undefined, { email }, req, res); diff --git a/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts b/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts index 5c1f1421..9c89a59a 100644 --- a/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts +++ b/SerpentRace_Backend/src/Application/DTOs/DeckDto.ts @@ -15,7 +15,7 @@ export interface ShortDeckDto { type: number; playedNumber: number; ctype: number; - cardsCount: number; + cardCount: number; creator: string; creationdate: Date; } diff --git a/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts b/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts index a2d8e420..b98991aa 100644 --- a/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts +++ b/SerpentRace_Backend/src/Application/DTOs/Mappers/DeckMapper.ts @@ -10,7 +10,7 @@ export class DeckMapper { type: deck.type, playedNumber: deck.playedNumber, ctype: deck.ctype, - cardsCount: deck.cards.length, + cardCount: deck.cards.length, creator: deck.user?.username || 'Unknown', creationdate: deck.creationdate }; @@ -36,7 +36,7 @@ export class DeckMapper { type: deck.type, playedNumber: deck.playedNumber, ctype: deck.ctype, - cardsCount: deck.cards.length, + cardCount: deck.cards.length, creator: deck.user?.username || 'Unknown', creationdate: deck.creationdate })); diff --git a/SerpentRace_Backend/src/Application/User/commands/CreateUserCommand.ts b/SerpentRace_Backend/src/Application/User/commands/CreateUserCommand.ts index b8bed6a0..08219c3c 100644 --- a/SerpentRace_Backend/src/Application/User/commands/CreateUserCommand.ts +++ b/SerpentRace_Backend/src/Application/User/commands/CreateUserCommand.ts @@ -7,4 +7,5 @@ export interface CreateUserCommand { code?: string; orgid?: string; phone?: string; + language: string; } diff --git a/SerpentRace_Backend/src/Application/User/commands/CreateUserCommandHandler.ts b/SerpentRace_Backend/src/Application/User/commands/CreateUserCommandHandler.ts index d359c6ce..51bae307 100644 --- a/SerpentRace_Backend/src/Application/User/commands/CreateUserCommandHandler.ts +++ b/SerpentRace_Backend/src/Application/User/commands/CreateUserCommandHandler.ts @@ -43,7 +43,7 @@ export class CreateUserCommandHandler { const created = await this.userRepo.create(user); // Send verification email (non-blocking) - this.sendVerificationEmailAsync(created, verificationTokenData.token); + this.sendVerificationEmailAsync(cmd.language, created, verificationTokenData.token); return UserMapper.toShortDto(created); } catch (error) { @@ -67,16 +67,24 @@ export class CreateUserCommandHandler { } } - private async sendVerificationEmailAsync(user: UserAggregate, token: string): Promise { + private async sendVerificationEmailAsync(language: string, user: UserAggregate, token: string): Promise { try { const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173'; const verificationUrl = TokenService.generateVerificationUrl(baseUrl, token); + var lang: 'en' | 'hu' | 'de' = 'en'; + if (language) { + lang = language.toLowerCase() as 'en' | 'hu' | 'de'; + } + + + const emailSent = await this.emailService.sendVerificationEmail( user.email, `${user.fname} ${user.lname}`, token, - verificationUrl + verificationUrl, + lang ); if (!emailSent) { diff --git a/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommand.ts b/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommand.ts index ed314d11..809b9a0a 100644 --- a/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommand.ts +++ b/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommand.ts @@ -1,3 +1,4 @@ export interface RequestPasswordResetCommand { + language: string; email: string; } diff --git a/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommandHandler.ts b/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommandHandler.ts index e3d667f2..dca3f536 100644 --- a/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommandHandler.ts +++ b/SerpentRace_Backend/src/Application/User/commands/RequestPasswordResetCommandHandler.ts @@ -38,14 +38,21 @@ export class RequestPasswordResetCommandHandler { // Send password reset email try { - const baseUrl = process.env.APP_BASE_URL || 'http://localhost:3000'; + const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173'; const resetUrl = TokenService.generatePasswordResetUrl(baseUrl, resetTokenData.token); - + + var lang: 'en' | 'hu' | 'de' = 'en'; + if (cmd.language) { + lang = cmd.language.toLowerCase() as 'en' | 'hu' | 'de'; + } + + const emailSent = await this.emailService.sendPasswordResetEmail( user.email, `${user.fname} ${user.lname}`, resetTokenData.token, - resetUrl + resetUrl, + lang ); if (!emailSent) {