210 lines
7.6 KiB
React
210 lines
7.6 KiB
React
import React, { useState, useEffect } from "react"
|
|
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"
|
|
import useRequireAuth from "../../hooks/useRequireAuth.jsx"
|
|
import ButtonGreen from "../../components/Buttons/ButtonGreen.jsx"
|
|
import { motion } from "framer-motion"
|
|
import { createGame, joinGame } from "../../api/gameApi.js"
|
|
|
|
const GameLobbySetup = () => {
|
|
const [username] = useRequireAuth({ key: "username", redirectTo: "/login" })
|
|
const { goLobby, goChooseDeck } = HandleNavigate()
|
|
const location = useLocation()
|
|
|
|
const deckIds = location.state?.deckIds || []
|
|
|
|
const [maxPlayers, setMaxPlayers] = useState(4)
|
|
const [isPublic, setIsPublic] = useState(true)
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState(null)
|
|
const [createdGameCode, setCreatedGameCode] = useState("")
|
|
const [showSuccess, setShowSuccess] = useState(false)
|
|
|
|
const handleCreateLobby = async () => {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
const username = localStorage.getItem("username")
|
|
|
|
console.log("Creating game - username:", username)
|
|
|
|
if (!username) {
|
|
setError("Kérlek jelentkezz be először!")
|
|
setLoading(false)
|
|
return
|
|
}
|
|
|
|
// Backend expects deckids (array), maxplayers (number), logintype (0=PUBLIC, 1=PRIVATE)
|
|
const gameData = {
|
|
deckids: deckIds, // Array of deck UUIDs
|
|
maxplayers: maxPlayers, // Number
|
|
logintype: isPublic ? 0 : 1, // 0=PUBLIC, 1=PRIVATE, 2=ORGANIZATION
|
|
}
|
|
|
|
console.log("Creating game with data:", gameData)
|
|
const response = await createGame(gameData)
|
|
console.log("Game created:", response)
|
|
|
|
// Verify localStorage still has username
|
|
console.log("After create - username:", localStorage.getItem("username"))
|
|
|
|
// Backend returns game object directly
|
|
const code = response.gamecode || response.gameCode
|
|
if (code) {
|
|
setCreatedGameCode(code)
|
|
setShowSuccess(true)
|
|
}
|
|
|
|
// Creator needs to join their own game to get a gameToken
|
|
// This allows the WebSocket to recognize them as the gamemaster
|
|
try {
|
|
const username = localStorage.getItem("username")
|
|
const joinResponse = await joinGame({
|
|
gameCode: code,
|
|
playerName: username,
|
|
})
|
|
|
|
if (joinResponse.gameToken) {
|
|
localStorage.setItem("gameToken", joinResponse.gameToken)
|
|
console.log("Creator joined game as gamemaster, token stored")
|
|
}
|
|
} catch (joinError) {
|
|
console.error("Failed to join game as creator:", joinError)
|
|
// Continue anyway - the creator can still try to join manually
|
|
}
|
|
|
|
// Azonnali navigáció a lobbyhoz, amint létrejött a játék
|
|
console.log("Navigating to lobby with code:", code)
|
|
goLobby({ gameCode: code })
|
|
} catch (err) {
|
|
console.error("Create game error:", err)
|
|
console.error("Error response:", err.response?.data)
|
|
console.error("Error status:", err.response?.status)
|
|
setError(
|
|
err.response?.data?.message || err.response?.data?.error || "Nem sikerült létrehozni a játékot"
|
|
)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
if (deckIds.length === 0) {
|
|
goChooseDeck()
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col min-h-screen overflow-y-auto relative">
|
|
<div className="fixed top-0 left-0 w-full h-full -z-10">
|
|
<Background />
|
|
</div>
|
|
|
|
<div className="fixed top-0 left-0 right-0 z-30">
|
|
<Navbar />
|
|
</div>
|
|
|
|
<main className="flex-grow text-white px-6 pt-24 pb-20">
|
|
<motion.section
|
|
className="max-w-2xl mx-auto"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.7 }}
|
|
>
|
|
<motion.h1
|
|
className="text-5xl font-extrabold text-green-300 mb-6 text-center tracking-wide drop-shadow-lg"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8, delay: 0.1 }}
|
|
>
|
|
Lobby Beállítások
|
|
</motion.h1>
|
|
|
|
<motion.p
|
|
className="text-lg leading-relaxed text-zinc-200 mb-10 text-center"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8, delay: 0.2 }}
|
|
>
|
|
{deckIds.length} pakli kiválasztva. Add meg a játék részleteit.
|
|
</motion.p>
|
|
|
|
{error && <div className="bg-red-500/20 border border-red-500 rounded-lg p-4 mb-6">{error}</div>}
|
|
|
|
{/* ...a kód kiírása törölve, lobbyban jelenik meg... */}
|
|
|
|
<div className="bg-[color:var(--color-surface)]/80 backdrop-blur-lg rounded-2xl p-8 shadow-lg space-y-6">
|
|
{/* Max Players */}
|
|
<div>
|
|
<label className="block text-[color:var(--color-text)] font-semibold mb-2">
|
|
Maximális játékosszám:
|
|
</label>
|
|
<input
|
|
type="number"
|
|
min="2"
|
|
max="10"
|
|
value={maxPlayers}
|
|
onChange={(e) => setMaxPlayers(parseInt(e.target.value) || 2)}
|
|
className="w-full px-4 py-2 rounded-lg bg-[color:var(--color-card)] text-[color:var(--color-text)] border border-[color:var(--color-surface)] focus:ring-2 focus:ring-[color:var(--color-success)] outline-none"
|
|
/>
|
|
</div>
|
|
|
|
{/* Public/Private */}
|
|
<div>
|
|
<label className="block text-[color:var(--color-text)] font-semibold mb-2">Játék típusa:</label>
|
|
<div className="flex gap-4">
|
|
<button
|
|
className={`flex-1 px-4 py-3 rounded-lg font-medium transition-all duration-200 ${
|
|
isPublic
|
|
? "bg-[color:var(--color-success)] text-[color:var(--color-text-inverse)]"
|
|
: "bg-[color:var(--color-card)] text-[color:var(--color-text)] hover:bg-[color:var(--color-success)]/30"
|
|
}`}
|
|
onClick={() => setIsPublic(true)}
|
|
>
|
|
🌐 Publikus
|
|
</button>
|
|
<button
|
|
className={`flex-1 px-4 py-3 rounded-lg font-medium transition-all duration-200 ${
|
|
!isPublic
|
|
? "bg-[color:var(--color-success)] text-[color:var(--color-text-inverse)]"
|
|
: "bg-[color:var(--color-card)] text-[color:var(--color-text)] hover:bg-[color:var(--color-success)]/30"
|
|
}`}
|
|
onClick={() => setIsPublic(false)}
|
|
>
|
|
🔒 Privát
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex justify-center gap-4 mt-8">
|
|
<ButtonGreen
|
|
text="Vissza"
|
|
onClick={() => goChooseDeck()}
|
|
width="w-auto px-8"
|
|
className="bg-gray-600 hover:bg-gray-700"
|
|
disabled={loading}
|
|
/>
|
|
<ButtonGreen
|
|
text={loading ? "Létrehozás..." : "Lobby Létrehozása"}
|
|
onClick={handleCreateLobby}
|
|
width="w-auto px-8"
|
|
disabled={loading}
|
|
/>
|
|
</div>
|
|
</motion.section>
|
|
</main>
|
|
|
|
<footer className="mt-auto">
|
|
<Footer />
|
|
</footer>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default GameLobbySetup
|