feat: Centralized navigation system with HandleNavigate hook

BREAKING CHANGE: Replaced all direct useNavigate() usage with HandleNavigate hook

## Summary
- Complete frontend navigation refactoring
- Centralized route management with routes.js
- Converted 18+ components to use HandleNavigate
- Enhanced navigation with 20+ type-safe functions

## New Files
- src/utils/routes.js - Central route constants and helpers
- Documentations/FRONTEND_CODING_GUIDELINES.md - Frontend best practices (300+ lines)
- Documentations/NAVIGATION_REFACTORING_REPORT.md - Detailed refactoring report (400+ lines)

## Modified Components (18+)
### Pages
- Home.jsx, LoginForm.jsx, RegisterForm.jsx
- ResetPassword.jsx, VerifyEmailPage.jsx
- DeckCreator.jsx, Card_display.jsx
- Lobby.jsx, GameTest.jsx, ChooseDeck.jsx, PlayerSetup.jsx
- Landingpage.jsx

### Components
- Userdetails.jsx, DeckInfoPopUp.jsx
- PlayMenu.jsx, LandingPage.jsx, DeckManager.jsx

### Hooks
- useRequireAuth.jsx

### Core
- App.jsx - Route constants integration
- HandleNavigate.jsx - Enhanced with 20+ navigation functions

## Key Improvements
 Type-safe navigation (goDeckDetails(id) vs navigate('/deck/'+id))
 Automatic scroll management
 Centralized state passing
 Single source of truth for routes
 Backwards compatibility aliases
 Zero compile errors
 Production ready

## Validation
- useNavigate: Only in HandleNavigate.jsx
- navigate() calls: 0 direct usage
- Compile errors: 0
- Documentation: Complete
This commit is contained in:
GitG0r0
2025-11-17 09:07:05 +01:00
parent 51e79b00d4
commit 6d25a499b2
23 changed files with 1165 additions and 106 deletions
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react"
import { useNavigate, useLocation } from "react-router-dom"
import { useLocation } from "react-router-dom"
import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate"
import Navbar from "../../components/Navbar/Navbar.jsx"
import Background from "../../assets/backgrounds/Background.jsx"
import Footer from "../../components/Footer/Footer.jsx"
@@ -45,7 +46,7 @@ const ChooseDeck = () => {
// prefer passed username (from navigate state) over authenticated username
const username = locationUsername ?? authUsername
const navigate = useNavigate()
const { goPlayerSetup } = HandleNavigate()
const [selectedType, setSelectedType] = useState("All")
const [selectedOrigin, setSelectedOrigin] = useState("Mind")
@@ -130,7 +131,7 @@ const ChooseDeck = () => {
return
}
console.log("Kiválasztott pakli ID-k:", selectedDeckIds)
navigate("/playersetup", { state: { deckIds: selectedDeckIds } })
goPlayerSetup({ deckIds: selectedDeckIds })
}
return (
@@ -1,9 +1,9 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import HandleNavigate from '../../utils/HandleNavigate/HandleNavigate';
import { createGame, joinGame } from '../../api/gameApi';
const GameTest = () => {
const navigate = useNavigate();
const { goLobby, goGame } = HandleNavigate();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [gameCode, setGameCode] = useState('');
@@ -44,7 +44,7 @@ const GameTest = () => {
// Wait 3 seconds to show code, then navigate
setTimeout(() => {
navigate('/lobby', { state: { gameCode: code } });
goLobby({ gameCode: code });
}, 3000);
} catch (err) {
setError(err.response?.data?.message || 'Failed to create game');
@@ -75,7 +75,7 @@ const GameTest = () => {
// Store game token
if (response.data?.gameToken) {
localStorage.setItem('gameToken', response.data.gameToken);
navigate('/lobby', { state: { gameCode: gameCode.toUpperCase() } });
goLobby({ gameCode: gameCode.toUpperCase() });
}
} catch (err) {
setError(err.response?.data?.message || 'Nem sikerült csatlakozni a játékhoz');
@@ -145,7 +145,7 @@ const GameTest = () => {
<button
onClick={() => {
localStorage.setItem('gameToken', 'test-token-123');
navigate('/game');
goGame();
}}
className="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded text-sm"
>
@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from "react"
import { useNavigate, useLocation } from "react-router-dom"
import { useLocation } from "react-router-dom"
import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate"
import Navbar from "../../components/Navbar/Navbar.jsx"
import Background from "../../assets/backgrounds/Background.jsx"
import useRequireAuth from "../../hooks/useRequireAuth.jsx"
@@ -9,7 +10,7 @@ import { startGame } from "../../api/gameApi.js"
const Lobby = () => {
const [visible, setVisible] = useState(false)
const sectionRef = useRef(null)
const navigate = useNavigate()
const { goHome, goGame } = HandleNavigate()
const location = useLocation()
const [user, setUser] = useRequireAuth()
@@ -53,14 +54,14 @@ const Lobby = () => {
useEffect(() => {
if (gameStarted) {
console.log('🎮 Game started, navigating to /game')
navigate("/game")
goGame()
}
}, [gameStarted, navigate])
}, [gameStarted, goGame])
const handleExit = () => {
if (window.confirm("Biztosan ki szeretnél lépni a lobbyból?")) {
localStorage.removeItem('gameToken')
navigate("/home")
goHome()
}
}
@@ -79,7 +80,7 @@ const Lobby = () => {
// Backend will broadcast game:started event to all players
// Navigate to game page
navigate("/game")
goGame()
} catch (error) {
console.error('Failed to start game:', error)
alert(`Nem sikerült elindítani a játékot: ${error.response?.data?.error || error.message}`)
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from "react"
import { useNavigate, useLocation } from "react-router-dom"
import { useLocation } from "react-router-dom"
import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate"
import Navbar from "../../components/Navbar/Navbar.jsx"
import Background from "../../assets/backgrounds/Background.jsx"
import Footer from "../../components/Footer/Footer.jsx"
@@ -10,7 +11,7 @@ import { createGame, joinGame } from "../../api/gameApi.js"
const GameLobbySetup = () => {
const [username] = useRequireAuth({ key: "username", redirectTo: "/login" })
const navigate = useNavigate()
const { goLobby, goChooseDeck } = HandleNavigate()
const location = useLocation()
const deckIds = location.state?.deckIds || []
@@ -79,7 +80,7 @@ const GameLobbySetup = () => {
// Wait 3 seconds to show code, then navigate to lobby
setTimeout(() => {
console.log('Navigating to lobby with code:', code)
navigate('/lobby', { state: { gameCode: code } })
goLobby({ gameCode: code })
}, 3000)
} catch (err) {
console.error('Create game error:', err)
@@ -92,7 +93,7 @@ const GameLobbySetup = () => {
}
if (deckIds.length === 0) {
navigate("/choosedeck")
goChooseDeck()
return null
}
@@ -200,7 +201,7 @@ const GameLobbySetup = () => {
<div className="flex justify-center gap-4 mt-8">
<ButtonGreen
text="Vissza"
onClick={() => navigate("/choosedeck")}
onClick={() => goChooseDeck()}
width="w-auto px-8"
className="bg-gray-600 hover:bg-gray-700"
disabled={loading}