Donat nezd majd át mert a backenden is lett valtozas nem tudom pontosan hogy kell e vagy sem Köszi

This commit is contained in:
2025-11-14 15:21:59 +01:00
parent a7ce891098
commit 0f85356154
10 changed files with 2007 additions and 71 deletions
@@ -2,6 +2,10 @@ import React, { useState, useEffect, useMemo, useCallback } from "react"
import { getVerticalOffset } from "../../utils/randomUtils"
import Dice from "../../utils/dice/Dice"
import { useGameWebSocket } from "../../hooks/useGameWebSocket"
import JokerApprovalModal from "./JokerApprovalModal"
import CardDisplayModal from "./CardDisplayModal"
import ConsequenceModal from "./ConsequenceModal"
import StepPredictionModal from "./StepPredictionModal"
// Constants - outside component to prevent recreation
const PLAYER_STYLES = [
@@ -47,16 +51,53 @@ const GameScreen = () => {
isConnected,
gameState,
players: backendPlayers,
boardData,
boardData: websocketBoardData,
currentTurn,
error,
rollDice,
approveJoker,
rejectJoker,
submitAnswer,
submitPositionGuess,
addEventListener,
removeEventListener
} = useGameWebSocket(gameToken)
// Try to get boardData from WebSocket, fallback to localStorage
const boardData = useMemo(() => {
if (websocketBoardData) return websocketBoardData
try {
const stored = localStorage.getItem('boardData')
if (stored) {
console.log('📦 Loading boardData from localStorage')
return JSON.parse(stored)
}
} catch (err) {
console.error('Failed to parse boardData from localStorage:', err)
}
return null
}, [websocketBoardData])
const [path, setPath] = useState([])
const [players, setPlayers] = useState([])
// Joker approval modal state
const [isJokerModalOpen, setIsJokerModalOpen] = useState(false)
const [currentJokerRequest, setCurrentJokerRequest] = useState(null)
// Card display modal state
const [isCardModalOpen, setIsCardModalOpen] = useState(false)
const [currentCard, setCurrentCard] = useState(null)
// Consequence modal state
const [isConsequenceModalOpen, setIsConsequenceModalOpen] = useState(false)
const [currentConsequence, setCurrentConsequence] = useState(null)
// Step prediction modal state
const [isPredictionModalOpen, setIsPredictionModalOpen] = useState(false)
const [currentPredictionData, setCurrentPredictionData] = useState(null)
// Memoized board dimensions
const { rows, cols, totalCells, cellSize, cellMargin, rowSpacing, topOffset, width, height } = useMemo(() => {
@@ -171,6 +212,178 @@ const GameScreen = () => {
return () => removeEventListener('game:player-moved')
}, [addEventListener, removeEventListener])
// Listen to Joker card events (csak Gamemaster számára)
useEffect(() => {
if (!addEventListener) return
const handleJokerDrawn = (jokerData) => {
console.log('🃏 Joker kártya húzva:', jokerData)
// Joker approval modal megjelenítése
setCurrentJokerRequest({
playerId: jokerData.playerId,
playerName: jokerData.playerName,
playerEmoji: jokerData.playerEmoji || "🎭",
cardTitle: jokerData.cardTitle || jokerData.jokerCard?.question,
cardDescription: jokerData.cardDescription || jokerData.jokerCard?.consequence?.description,
points: jokerData.points || jokerData.jokerCard?.consequence?.value,
cardId: jokerData.cardId || jokerData.jokerCard?.id,
requestId: jokerData.requestId, // Important: requestId from backend
timestamp: Date.now()
})
setIsJokerModalOpen(true)
}
// Listen for gamemaster decision request (correct event name per docs)
addEventListener('game:joker-drawn', handleJokerDrawn)
addEventListener('game:gamemaster-decision-request', handleJokerDrawn)
return () => {
removeEventListener('game:joker-drawn')
removeEventListener('game:gamemaster-decision-request')
}
}, [addEventListener, removeEventListener])
// Listen to card drawn events (kártya megjelenítés)
useEffect(() => {
if (!addEventListener) return
const handleCardDrawn = (cardData) => {
console.log('🎴 Kártya húzva:', cardData)
setCurrentCard({
id: cardData.cardId || cardData.id,
type: cardData.cardType || cardData.type,
question: cardData.question || cardData.text,
answerOptions: cardData.answerOptions || cardData.options || [],
correctAnswer: cardData.correctAnswer,
points: cardData.points || 0,
timeLimit: cardData.timeLimit || 60
})
setIsCardModalOpen(true)
}
// Listen for both generic and self-specific events
addEventListener('game:card-drawn', handleCardDrawn)
addEventListener('game:card-drawn-self', handleCardDrawn)
return () => {
removeEventListener('game:card-drawn')
removeEventListener('game:card-drawn-self')
}
}, [addEventListener, removeEventListener])
// Listen to answer validation (következmény megjelenítés)
useEffect(() => {
if (!addEventListener) return
const handleAnswerValidated = (resultData) => {
console.log('✅ Válasz kiértékelve:', resultData)
// Close card modal first
setIsCardModalOpen(false)
// Show consequence modal
setCurrentConsequence({
isCorrect: resultData.isCorrect || resultData.correct,
playerAnswer: resultData.playerAnswer || resultData.answer,
correctAnswer: resultData.correctAnswer,
explanation: resultData.explanation || '',
consequenceType: resultData.consequenceType || resultData.consequence?.type,
consequenceValue: resultData.consequenceValue || resultData.consequence?.value || 0,
points: resultData.pointsEarned || resultData.points || 0
})
setIsConsequenceModalOpen(true)
}
// Also listen for luck consequences (instant consequences from luck cards)
const handleLuckConsequence = (luckData) => {
console.log('🍀 Szerencse kártya következménye:', luckData)
setCurrentConsequence({
isCorrect: true, // Luck cards don't have right/wrong answers
consequenceType: luckData.consequenceType,
consequenceValue: luckData.value || luckData.consequenceValue || 0,
explanation: luckData.message || 'Szerencse kártya!',
playerAnswer: null,
correctAnswer: null
})
setIsConsequenceModalOpen(true)
}
addEventListener('game:answer-validated', handleAnswerValidated)
addEventListener('game:luck-consequence', handleLuckConsequence)
return () => {
removeEventListener('game:answer-validated')
removeEventListener('game:luck-consequence')
}
}, [addEventListener, removeEventListener])
// Listen to position guess requests (lépés tippelés)
useEffect(() => {
if (!addEventListener) return
const handlePositionGuessRequest = (predictionData) => {
console.log('🎯 Pozíció tippelés kérés:', predictionData)
setCurrentPredictionData({
currentPosition: predictionData.currentPosition,
diceRoll: predictionData.diceRoll || predictionData.dice,
fieldStepValue: predictionData.fieldStepValue || predictionData.fieldStep || 0,
patternModifier: predictionData.patternModifier || predictionData.zoneModifier || 0,
cardText: predictionData.cardText || predictionData.text || 'Tippeld meg, hova fogsz lépni!',
timeLimit: predictionData.timeLimit || 30
})
setIsPredictionModalOpen(true)
}
addEventListener('game:position-guess-request', handlePositionGuessRequest)
return () => removeEventListener('game:position-guess-request')
}, [addEventListener, removeEventListener])
// Joker jóváhagyás
const handleApproveJoker = useCallback(async (jokerRequest) => {
console.log('✅ Joker feladat jóváhagyva:', jokerRequest)
// WebSocket üzenet a backend felé
approveJoker(jokerRequest.playerId, jokerRequest.cardId, jokerRequest.requestId)
// Modal bezárása
setIsJokerModalOpen(false)
}, [approveJoker])
// Joker elutasítás
const handleRejectJoker = useCallback(async (jokerRequest) => {
console.log('❌ Joker feladat elutasítva:', jokerRequest)
// WebSocket üzenet a backend felé
rejectJoker(jokerRequest.playerId, jokerRequest.cardId, jokerRequest.requestId)
// Modal bezárása
setIsJokerModalOpen(false)
}, [rejectJoker])
// Kártya válasz beküldése
const handleSubmitAnswer = useCallback((answer) => {
console.log('📝 Válasz beküldve:', answer)
// WebSocket emit a backend felé
if (currentCard?.id) {
submitAnswer(currentCard.id, answer)
}
// A consequence modal automatikusan megnyílik a 'game:answer-validated' event hatására
}, [currentCard?.id, submitAnswer])
// Pozíció tippelés beküldése
const handleSubmitPrediction = useCallback((predictedPosition) => {
console.log('🎯 Pozíció tippelés beküldve:', predictedPosition)
// WebSocket emit a backend felé
submitPositionGuess(predictedPosition)
// Modal bezárása
setIsPredictionModalOpen(false)
}, [submitPositionGuess])
// Sorted players - memoized
const sortedPlayers = useMemo(
() => [...players].sort((a, b) => b.position - a.position),
@@ -179,7 +392,13 @@ const GameScreen = () => {
// Handle dice roll
const handleDiceRoll = useCallback((value) => {
rollDice(value)
console.log('🎲 Dobás:', value)
const success = rollDice(value)
if (success) {
console.log('✅ Kockadobás elküldve a szervernek')
} else {
console.warn('⚠️ Kockadobás sikertelen - nincs kapcsolat vagy nem te következel')
}
}, [rollDice])
// Get field style - memoized
@@ -229,18 +448,16 @@ const GameScreen = () => {
<div className={`w-3 h-3 rounded-full ${
isConnected ? 'bg-green-300 animate-pulse' : 'bg-red-300'
}`}></div>
<span className="text-sm font-medium">
{isConnected ? '🟢 Csatlakozva' : '🔴 Kapcsolódás...'}
</span>
</div>
{error && (
<div className="mt-2 px-4 py-2 rounded-lg shadow-lg bg-red-600 text-white text-xs">
{error}
</div>
)}
<span className="text-sm font-medium">
{isConnected ? '🟢 Csatlakozva' : '🔴 Kapcsolódás...'}
</span>
</div>
{/* Game Info Bar */}
{error && !error.includes('Game not found') && !error.includes('token invalid') && (
<div className="mt-2 px-4 py-2 rounded-lg shadow-lg bg-red-600 text-white text-xs">
{error}
</div>
)}
</div> {/* Game Info Bar */}
{gameState && (
<div className="fixed top-4 left-4 z-50">
<div className="bg-gray-800 border border-teal-700 px-4 py-2 rounded-lg shadow-lg">
@@ -416,6 +633,40 @@ const GameScreen = () => {
</div>
</div>
</div>
{/* Joker Approval Modal - csak Gamemaster számára */}
<JokerApprovalModal
isOpen={isJokerModalOpen}
onClose={() => setIsJokerModalOpen(false)}
jokerRequest={currentJokerRequest}
onApprove={handleApproveJoker}
onReject={handleRejectJoker}
playerName={currentJokerRequest?.playerName}
playerEmoji={currentJokerRequest?.playerEmoji}
/>
{/* Card Display Modal - kártya megjelenítés */}
<CardDisplayModal
isOpen={isCardModalOpen}
onClose={() => setIsCardModalOpen(false)}
card={currentCard}
onSubmitAnswer={handleSubmitAnswer}
/>
{/* Consequence Modal - következmények megjelenítése */}
<ConsequenceModal
isOpen={isConsequenceModalOpen}
onClose={() => setIsConsequenceModalOpen(false)}
consequence={currentConsequence}
/>
{/* Step Prediction Modal - pozíció tippelés */}
<StepPredictionModal
isOpen={isPredictionModalOpen}
onClose={() => setIsPredictionModalOpen(false)}
predictionData={currentPredictionData}
onSubmitPrediction={handleSubmitPrediction}
/>
</div>
)
}