Files
SerpentRace/Documentations/FRONTEND_CODING_GUIDELINES.md
GitG0r0 6d25a499b2 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
2025-11-17 09:07:05 +01:00

14 KiB

Frontend Kódolási Útmutató - SerpentRace

Tartalomjegyzék

  1. Navigáció és Routing
  2. Fájl és Mappa Struktúra
  3. Komponens Konvenciók
  4. State Management
  5. API Hívások
  6. Hibakezelés
  7. Elnevezési Konvenciók

Navigáció és Routing

Helyes gyakorlat: HandleNavigate használata

MINDIG használd a központosított HandleNavigate hook-ot navigációhoz:

import HandleNavigate from "../../utils/HandleNavigate/HandleNavigate"

const MyComponent = () => {
  const { goHome, goLogin, goDeckDetails } = HandleNavigate()
  
  const handleClick = () => {
    goHome() // Egyszerű navigáció
  }
  
  const handleDeckView = (deckId) => {
    goDeckDetails(deckId) // Dinamikus route paraméterrel
  }
  
  const handleLobby = (gameCode) => {
    goLobby({ gameCode }) // State passzolással
  }
}

Kerülendő: Direkt useNavigate használat

// SOHA NE HASZNÁLD EZT!
import { useNavigate } from "react-router-dom"

const MyComponent = () => {
  const navigate = useNavigate()
  navigate("/home") // ❌ NEM JÓ!
}

Elérhető Navigációs Függvények

HandleNavigate által biztosított függvények:

const {
  // Általános
  goTo,                    // goTo('/any-path', { state: {...} })
  goBack,                  // Vissza az előző oldalra
  
  // Authentikáció
  goHome,                  // → /home
  goLogin,                 // → /login, state: { success, message }
  goRegister,              // → /register (alias: goAuth)
  goLanding,               // → / (landing page)
  
  // Deck Management
  goDecks,                 // → /decks
  goDeckDetails,           // goDeckDetails(deckId) → /deck/:deckId
  goDeckCreator,           // → /deck-creator
  goDeckCreatorEdit,       // goDeckCreatorEdit(deckId) → /deck-creator/:deckId
  
  // Game Flow
  goLobby,                 // goLobby({ gameCode }) → /lobby
  goChooseDeck,            // goChooseDeck({ username, deckIds }) → /choosedeck
  goPlayerSetup,           // goPlayerSetup({ deckIds }) → /player-setup
  goGame,                  // goGame({ players, gameState }) → /game
  
  // Egyéb
  goContacts               // → /contacts (alias: goCompanies)
} = HandleNavigate()

Route Konstansok

Használd a centralizált route konstansokat:

// src/utils/routes.js
import { ROUTES } from '../../utils/routes'

// App.jsx-ben
<Route path={ROUTES.HOME} element={<Home />} />
<Route path={ROUTES.DECK_DETAILS} element={<DeckDetails />} />

// ❌ NE használj string literálokat:
<Route path="/home" element={<Home />} /> // NEM JÓ!

State Passzolás

Így adj át adatokat navigáció során:

// Régi mód (useNavigate) - ❌ NE!
navigate('/lobby', { state: { gameCode: 'ABC123' } })

// Új mód (HandleNavigate) - ✅ JÓ!
goLobby({ gameCode: 'ABC123' })

// Fogadó oldalon:
import { useLocation } from 'react-router-dom'

const Lobby = () => {
  const location = useLocation()
  const gameCode = location.state?.gameCode
}

Fájl és Mappa Struktúra

Mappa Szervezés

src/
├── api/                    # API hívások
│   ├── userApi.js
│   ├── deckApi.js
│   └── gameApi.js
├── assets/                 # Statikus fájlok
│   ├── backgrounds/
│   ├── images/
│   └── icons/
├── components/             # Újrahasználható komponensek
│   ├── Buttons/
│   ├── Inputs/
│   ├── Navbar/
│   └── PopUp/
├── hooks/                  # Custom Hooks
│   └── useRequireAuth.jsx
├── pages/                  # Oldal komponensek
│   ├── Auth/
│   ├── Game/
│   ├── Decks/
│   └── Landing/
├── utils/                  # Utility függvények
│   ├── HandleNavigate/
│   └── routes.js
└── App.jsx                # Fő alkalmazás komponens

Fájl Elnevezési Konvenciók

  • Komponensek: PascalCase

    • LoginForm.jsx, DeckCreator.jsx, ButtonGreen.jsx
  • Utility fájlok: camelCase

    • routes.js, randomUtils.js, userApi.js
  • Hook fájlok: camelCase, "use" prefix

    • useRequireAuth.jsx, useLocalStorage.jsx

Komponens Konvenciók

Funkcionális Komponens Sablon

import React, { useState, useEffect } from 'react'
import HandleNavigate from '../../utils/HandleNavigate/HandleNavigate'

/**
 * Komponens rövid leírása
 * @returns {JSX.Element}
 */
const MyComponent = () => {
  // 1. Hooks (HandleNavigate, useState, useEffect, stb.)
  const { goHome } = HandleNavigate()
  const [data, setData] = useState(null)
  
  // 2. Effect hooks
  useEffect(() => {
    // Component mount logic
  }, [])
  
  // 3. Event handlers
  const handleClick = () => {
    // Logic
  }
  
  // 4. Render
  return (
    <div>
      {/* JSX */}
    </div>
  )
}

export default MyComponent

Import Sorrend

// 1. React és third-party library-k
import React, { useState } from 'react'
import { motion } from 'framer-motion'

// 2. React Router hooks (useLocation, useParams - NEM useNavigate!)
import { useLocation } from 'react-router-dom'

// 3. Custom hooks és utils
import HandleNavigate from '../../utils/HandleNavigate/HandleNavigate'
import useRequireAuth from '../../hooks/useRequireAuth'

// 4. API
import { getUserData } from '../../api/userApi'

// 5. Komponensek
import Button from '../../components/Buttons/Button'
import Navbar from '../../components/Navbar/Navbar'

// 6. Assets
import Background from '../../assets/backgrounds/Background'

State Management

Local State

// Egyszerű state
const [count, setCount] = useState(0)

// Object state
const [user, setUser] = useState({
  name: '',
  email: ''
})

// Array state
const [items, setItems] = useState([])

LocalStorage Használat

useRequireAuth hook használata auth kezeléshez:

import useRequireAuth from '../../hooks/useRequireAuth'

const MyComponent = () => {
  const [username] = useRequireAuth({ 
    key: 'username', 
    redirectTo: '/login' 
  })
  
  // username automatikusan szinkronizálva van localStorage-el
  // Ha nincs username, automatikus redirect /login-re
}

Manuális localStorage:

// Írás
localStorage.setItem('gameToken', token)

// Olvasás
const token = localStorage.getItem('gameToken')

// Törlés
localStorage.removeItem('gameToken')

API Hívások

API File Struktúra

Minden API endpoint egy külön file-ban (userApi.js, deckApi.js, gameApi.js):

// src/api/userApi.js
import axiosInstance from './axiosInstance'

export const getUserData = async (userId) => {
  try {
    const response = await axiosInstance.get(`/users/${userId}`)
    return response.data
  } catch (error) {
    console.error('Error fetching user data:', error)
    throw error
  }
}

export const updateUser = async (userId, userData) => {
  try {
    const response = await axiosInstance.put(`/users/${userId}`, userData)
    return response.data
  } catch (error) {
    console.error('Error updating user:', error)
    throw error
  }
}

API Hívás Komponensben

import { getUserData } from '../../api/userApi'

const MyComponent = () => {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const [data, setData] = useState(null)
  
  const fetchData = async () => {
    setLoading(true)
    setError(null)
    
    try {
      const result = await getUserData(userId)
      setData(result)
    } catch (err) {
      setError(err.message || 'Hiba történt')
    } finally {
      setLoading(false)
    }
  }
  
  useEffect(() => {
    fetchData()
  }, [userId])
  
  if (loading) return <div>Betöltés...</div>
  if (error) return <div>Hiba: {error}</div>
  
  return <div>{/* data megjelenítése */}</div>
}

Hibakezelés

Try-Catch Blokkok

const handleSubmit = async () => {
  try {
    const response = await createDeck(deckData)
    // Siker kezelése
    notifySuccess('Deck sikeresen létrehozva!')
    goDecks()
  } catch (error) {
    // Hiba kezelése
    const errorMessage = error.response?.data?.message || 'Ismeretlen hiba'
    setError(errorMessage)
    notifyError(errorMessage)
  }
}

Toast Notifications

import { notifySuccess, notifyError } from '../../components/Toastify/toastifyServices'

// Siker üzenet
notifySuccess('✅ Művelet sikeres!')

// Hiba üzenet
notifyError('❌ Hiba történt!')

// Egyedi konfiguráció
notifySuccess('Mentve!', { autoClose: 2000 })

Elnevezési Konvenciók

JavaScript/React

Típus Konvenció Példa
Komponensek PascalCase LoginForm, DeckCreator
Függvények camelCase handleClick, fetchUserData
Változók camelCase userName, isLoading
Konstansok UPPER_SNAKE_CASE API_BASE_URL, MAX_PLAYERS
Private változók _camelCase _internalState
Event handlers handle + PascalCase handleSubmit, handleInputChange
Boolean változók is/has/can prefix isLoading, hasError, canEdit

CSS Classes (Tailwind)

// Használj explicit class neveket
<div className="flex items-center justify-between p-4 bg-white rounded-lg shadow-md">

// Kerüld a túl hosszú class stringeket - bontsd több sorra
<div 
  className="
    flex items-center justify-between 
    p-4 bg-white rounded-lg shadow-md
    hover:shadow-lg transition-shadow duration-200
  "
>

Fájl Nevek

  • Egyedi komponens: LoginForm.jsx (nem login-form.jsx)
  • Index fájlok: index.jsx (ha könyvtárban több file van)
  • Utility fájlok: randomUtils.js (camelCase)
  • API fájlok: userApi.js (camelCase + Api postfix)

Teljes Példa - Best Practices

// src/pages/Example/ExamplePage.jsx

import React, { useState, useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import { motion } from 'framer-motion'

import HandleNavigate from '../../utils/HandleNavigate/HandleNavigate'
import useRequireAuth from '../../hooks/useRequireAuth'
import { fetchExampleData, updateExampleData } from '../../api/exampleApi'
import { notifySuccess, notifyError } from '../../components/Toastify/toastifyServices'

import Navbar from '../../components/Navbar/Navbar'
import Button from '../../components/Buttons/Button'
import Background from '../../assets/backgrounds/Background'

/**
 * Example Page - Komponens rövid leírása
 * @returns {JSX.Element}
 */
const ExamplePage = () => {
  // 1. Auth & Navigation
  const [username] = useRequireAuth({ key: 'username', redirectTo: '/login' })
  const { goHome, goBack } = HandleNavigate()
  const location = useLocation()
  
  // 2. State
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  
  // 3. Effects
  useEffect(() => {
    loadData()
  }, [])
  
  // 4. Functions
  const loadData = async () => {
    setLoading(true)
    setError(null)
    
    try {
      const result = await fetchExampleData()
      setData(result)
    } catch (err) {
      const errorMsg = err.response?.data?.message || 'Hiba történt'
      setError(errorMsg)
      notifyError(errorMsg)
    } finally {
      setLoading(false)
    }
  }
  
  const handleSave = async () => {
    try {
      await updateExampleData(data)
      notifySuccess('✅ Sikeresen mentve!')
      goHome()
    } catch (err) {
      notifyError('❌ Mentés sikertelen')
    }
  }
  
  const handleCancel = () => {
    goBack()
  }
  
  // 5. Conditional Rendering
  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div>Betöltés...</div>
      </div>
    )
  }
  
  if (error) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-red-500">Hiba: {error}</div>
      </div>
    )
  }
  
  // 6. Main Render
  return (
    <div className="min-h-screen bg-gray-100">
      <Background />
      <Navbar />
      
      <main className="container mx-auto px-4 py-8">
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.5 }}
        >
          <h1 className="text-3xl font-bold mb-6">Example Page</h1>
          
          {/* Content */}
          <div className="bg-white rounded-lg shadow-md p-6">
            {data && (
              <div>
                {/* Render data */}
              </div>
            )}
          </div>
          
          {/* Actions */}
          <div className="flex gap-4 mt-6">
            <Button onClick={handleSave} text="Mentés" />
            <Button onClick={handleCancel} text="Mégse" variant="secondary" />
          </div>
        </motion.div>
      </main>
    </div>
  )
}

export default ExamplePage

Összefoglalás - Legfontosabb Szabályok

  1. MINDIG használd HandleNavigate-et navigációhoz
  2. Használd a ROUTES konstansokat az App.jsx-ben
  3. API hívások külön file-okban (userApi.js, deckApi.js, stb.)
  4. Try-catch minden async műveletnél
  5. Toast notifications a felhasználói visszajelzéshez
  6. useRequireAuth hook auth védett oldalaknál
  7. Konzisztens import sorrend
  8. PascalCase komponenseknek, camelCase változóknak
  9. SOHA ne használj useNavigate közvetlen
  10. Ne használj string literal route-okat

Verzió: 1.0
Utolsó frissítés: 2025-01-17
Készítette: SerpentRace Development Team