- Rebuilt Player.tsx with full UI overhaul using Framer Motion animations.
- Added animated transitions between login, lobby, and match states. - Improved layout, spacing, and visual styling for modern game feel. - Added smooth auto-connect flow and integrated username lock-in behavior. - Updated matchmaking and logout buttons with animated interactions. - Integrated Leaderboard cleanly inside lobby panel.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import Leaderboard from "./Leaderboard";
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
|
||||
@@ -45,38 +46,167 @@ export default function Player({
|
||||
|
||||
return (
|
||||
<div style={{ marginBottom: "20px" }}>
|
||||
{session && !matchId && (
|
||||
<>
|
||||
<h2>Hello, {session.username}</h2>
|
||||
|
||||
{/* Game mode selection */}
|
||||
<label style={{ display: "block", marginTop: "10px" }}>
|
||||
Select Game Mode:
|
||||
</label>
|
||||
|
||||
<select
|
||||
value={selectedMode}
|
||||
onChange={(e) => setSelectedMode(e.target.value)}
|
||||
style={{ padding: "6px", marginBottom: "10px" }}
|
||||
<AnimatePresence mode="wait">
|
||||
{/* ---------------- LOGIN SCREEN ---------------- */}
|
||||
{!session && (
|
||||
<motion.div
|
||||
key="login"
|
||||
initial={{ opacity: 0, y: 20, scale: 0.97 }}
|
||||
animate={{ opacity: 1, y: 0, scale: 1 }}
|
||||
exit={{ opacity: 0, y: -20, scale: 0.97 }}
|
||||
transition={{ duration: 0.4, ease: "easeOut" }}
|
||||
style={{
|
||||
background: "#111",
|
||||
padding: "24px",
|
||||
borderRadius: "16px",
|
||||
width: "280px",
|
||||
margin: "0 auto",
|
||||
color: "white",
|
||||
boxShadow:
|
||||
"0 4px 16px rgba(0,0,0,0.4), inset 0 0 20px rgba(255,255,255,0.03)",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<option value="classic">Classic</option>
|
||||
<option value="blitz">Blitz</option>
|
||||
</select>
|
||||
<h2 style={{ marginBottom: "16px" }}>Welcome!</h2>
|
||||
|
||||
{/* Join matchmaking */}
|
||||
<button onClick={() => startQueue(selectedMode)}>Join Matchmaking</button>
|
||||
<button onClick={() => logout()}>Logout</button>
|
||||
<input
|
||||
placeholder="Enter username"
|
||||
value={username}
|
||||
disabled={username.length > 0}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
style={{
|
||||
padding: "10px",
|
||||
width: "100%",
|
||||
borderRadius: "12px",
|
||||
background: "#222",
|
||||
color: "white",
|
||||
border: "1px solid #333",
|
||||
marginBottom: "12px",
|
||||
fontSize: "14px",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/*/!* List open matches *!/*/}
|
||||
{/*<MatchList matches={openMatches} />*/}
|
||||
<Leaderboard/>
|
||||
</>
|
||||
)}
|
||||
{session && matchId && (
|
||||
<>
|
||||
<h2>Go {session.username}!</h2>
|
||||
</>
|
||||
)}
|
||||
<motion.button
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={handleConnect}
|
||||
disabled={username.length === 0}
|
||||
style={{
|
||||
width: "100%",
|
||||
padding: "10px",
|
||||
borderRadius: "12px",
|
||||
background: username.length ? "#2ecc71" : "#444",
|
||||
border: "none",
|
||||
cursor: username.length ? "pointer" : "not-allowed",
|
||||
color: "white",
|
||||
fontWeight: 600,
|
||||
fontSize: "14px",
|
||||
}}
|
||||
>
|
||||
Connect
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{/* ---------------- LOBBY SCREEN ---------------- */}
|
||||
{session && !matchId && (
|
||||
<motion.div
|
||||
key="lobby"
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -40 }}
|
||||
transition={{ duration: 0.45, ease: "easeOut" }}
|
||||
style={{
|
||||
padding: "20px",
|
||||
background: "#0f0f0f",
|
||||
borderRadius: "20px",
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<h2 style={{ marginBottom: "10px" }}>
|
||||
Hello, <span style={{ color: "#2ecc71" }}>{session.username}</span>
|
||||
</h2>
|
||||
|
||||
<label style={{ display: "block", marginTop: "10px", opacity: 0.7 }}>
|
||||
Select Game Mode
|
||||
</label>
|
||||
|
||||
<select
|
||||
value={selectedMode}
|
||||
onChange={(e) => setSelectedMode(e.target.value)}
|
||||
style={{
|
||||
padding: "8px",
|
||||
margin: "10px 0 16px",
|
||||
width: "60%",
|
||||
borderRadius: "10px",
|
||||
background: "#222",
|
||||
color: "white",
|
||||
border: "1px solid #333",
|
||||
}}
|
||||
>
|
||||
<option value="classic">Classic</option>
|
||||
<option value="blitz">Blitz</option>
|
||||
</select>
|
||||
|
||||
<motion.button
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={() => startQueue(selectedMode)}
|
||||
style={{
|
||||
padding: "10px 20px",
|
||||
borderRadius: "12px",
|
||||
background: "#3498db",
|
||||
color: "white",
|
||||
border: "none",
|
||||
marginRight: "10px",
|
||||
cursor: "pointer",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
Join Matchmaking
|
||||
</motion.button>
|
||||
|
||||
<motion.button
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={logout}
|
||||
style={{
|
||||
padding: "10px 20px",
|
||||
borderRadius: "12px",
|
||||
background: "#e74c3c",
|
||||
color: "white",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</motion.button>
|
||||
|
||||
<div style={{ marginTop: "24px" }}>
|
||||
<Leaderboard />
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{/* ---------------- MATCH SCREEN ---------------- */}
|
||||
{session && matchId && (
|
||||
<motion.div
|
||||
key="match"
|
||||
initial={{ opacity: 0, scale: 0.9, y: 30 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.9, y: -20 }}
|
||||
transition={{ duration: 0.35, ease: "easeOut" }}
|
||||
style={{
|
||||
padding: "20px",
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<h2 style={{ fontSize: "22px", color: "#f1c40f" }}>
|
||||
Go {session.username}!
|
||||
</h2>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user