| import { useState, useEffect } from 'react'; |
| import { motion } from 'framer-motion'; |
| import { useGameStore } from '../../store/gameStore'; |
| import { emitCreateRoom, emitJoinRoom, emitGetRooms } from '../../socket/socket'; |
|
|
| export function Lobby() { |
| const [roomName, setRoomName] = useState(''); |
| const [joinCode, setJoinCode] = useState(''); |
| const [activeTab, setActiveTab] = useState<'create' | 'join' | 'browse'>('create'); |
| |
| const playerName = useGameStore((state) => state.playerName); |
| const roomList = useGameStore((state) => state.roomList); |
| const setScreen = useGameStore((state) => state.setScreen); |
|
|
| useEffect(() => { |
| emitGetRooms(); |
| const interval = setInterval(emitGetRooms, 5000); |
| return () => clearInterval(interval); |
| }, []); |
|
|
| const handleCreateRoom = () => { |
| if (!roomName.trim()) { |
| useGameStore.getState().addToast('Please enter a room name!', 'warning'); |
| return; |
| } |
| emitCreateRoom(playerName, roomName.trim()); |
| }; |
|
|
| const handleJoinByCode = () => { |
| if (!joinCode.trim()) { |
| useGameStore.getState().addToast('Please enter a room code!', 'warning'); |
| return; |
| } |
| emitJoinRoom(playerName, joinCode.trim().toUpperCase()); |
| }; |
|
|
| const handleJoinRoom = (roomId: string) => { |
| emitJoinRoom(playerName, roomId); |
| }; |
|
|
| const handleBack = () => { |
| setScreen('menu'); |
| }; |
|
|
| const availableRooms = roomList.filter(r => !r.isPlaying && r.playerCount < r.maxPlayers); |
|
|
| return ( |
| <div |
| className="flex-1 flex flex-col items-center justify-center p-2 md:p-4 overflow-auto" |
| style={{ |
| backgroundImage: 'url(/Assests/menu_background.png)', |
| backgroundSize: 'cover', |
| backgroundPosition: 'center', |
| }} |
| > |
| <motion.div |
| initial={{ opacity: 0, scale: 0.9 }} |
| animate={{ opacity: 1, scale: 1 }} |
| className="bg-black/70 backdrop-blur-sm rounded-xl md:rounded-2xl p-2 md:p-6 max-w-lg w-full" |
| > |
| {/* Header */} |
| <div className="flex items-center justify-between mb-2 md:mb-6"> |
| <button onClick={handleBack} className="text-egyptian-gold hover:text-yellow-400 text-xs md:text-base"> |
| ← Back |
| </button> |
| <h1 className="text-base md:text-2xl font-bold text-egyptian-gold">Lobby</h1> |
| <span className="text-papyrus text-xs md:text-base">{playerName}</span> |
| </div> |
| |
| {/* Tabs */} |
| <div className="flex border-b border-egyptian-gold/30 mb-2 md:mb-6"> |
| {(['create', 'join', 'browse'] as const).map((tab) => ( |
| <button |
| key={tab} |
| onClick={() => setActiveTab(tab)} |
| className={`flex-1 py-1 md:py-2 text-center capitalize transition-colors text-xs md:text-base ${ |
| activeTab === tab |
| ? 'text-egyptian-gold border-b-2 border-egyptian-gold' |
| : 'text-papyrus/60 hover:text-papyrus' |
| }`} |
| > |
| {tab} |
| </button> |
| ))} |
| </div> |
| |
| {/* Create Tab */} |
| {activeTab === 'create' && ( |
| <motion.div |
| initial={{ opacity: 0, x: -20 }} |
| animate={{ opacity: 1, x: 0 }} |
| > |
| <p className="text-papyrus text-xs md:text-base mb-2 md:mb-4">Create a new room for friends to join.</p> |
| |
| <div className="mb-2 md:mb-4"> |
| <label className="block text-papyrus text-xs md:text-sm mb-1 md:mb-2">Room Name</label> |
| <input |
| type="text" |
| value={roomName} |
| onChange={(e) => setRoomName(e.target.value)} |
| placeholder="My Game Room" |
| className="w-full text-sm md:text-base" |
| maxLength={30} |
| /> |
| </div> |
| |
| <button onClick={handleCreateRoom} className="btn btn-primary w-full text-xs md:text-base py-1.5 md:py-2"> |
| Create Room |
| </button> |
| </motion.div> |
| )} |
| |
| {/* Join Tab */} |
| {activeTab === 'join' && ( |
| <motion.div |
| initial={{ opacity: 0, x: -20 }} |
| animate={{ opacity: 1, x: 0 }} |
| > |
| <p className="text-papyrus text-xs md:text-base mb-2 md:mb-4">Enter a room code to join.</p> |
| |
| <div className="mb-2 md:mb-4"> |
| <label className="block text-papyrus text-xs md:text-sm mb-1 md:mb-2">Room Code</label> |
| <input |
| type="text" |
| value={joinCode} |
| onChange={(e) => setJoinCode(e.target.value.toUpperCase())} |
| placeholder="ABC123" |
| className="w-full uppercase tracking-widest text-center text-base md:text-xl" |
| maxLength={6} |
| /> |
| </div> |
| |
| <button onClick={handleJoinByCode} className="btn btn-primary w-full text-xs md:text-base py-1.5 md:py-2"> |
| Join Room |
| </button> |
| </motion.div> |
| )} |
| |
| {/* Browse Tab */} |
| {activeTab === 'browse' && ( |
| <motion.div |
| initial={{ opacity: 0, x: -20 }} |
| animate={{ opacity: 1, x: 0 }} |
| > |
| <p className="text-papyrus text-xs md:text-base mb-2 md:mb-4">Available rooms:</p> |
| |
| {availableRooms.length === 0 ? ( |
| <p className="text-center text-papyrus/60 py-4 md:py-8 text-xs md:text-base"> |
| No rooms available. Create one! |
| </p> |
| ) : ( |
| <div className="space-y-1 md:space-y-2 max-h-32 md:max-h-60 overflow-y-auto"> |
| {availableRooms.map((room) => ( |
| <motion.div |
| key={room.id} |
| className="bg-nile-blue/50 rounded-lg p-2 md:p-3 flex items-center justify-between" |
| initial={{ opacity: 0, y: 10 }} |
| animate={{ opacity: 1, y: 0 }} |
| > |
| <div> |
| <p className="text-papyrus text-xs md:text-base font-semibold">{room.name}</p> |
| <p className="text-egyptian-gold/60 text-[10px] md:text-sm"> |
| {room.playerCount}/{room.maxPlayers} players |
| </p> |
| </div> |
| <button |
| onClick={() => handleJoinRoom(room.id)} |
| className="btn btn-secondary text-xs py-1 px-2 md:text-sm md:py-1 md:px-3" |
| > |
| Join |
| </button> |
| </motion.div> |
| ))} |
| </div> |
| )} |
| |
| <button onClick={emitGetRooms} className="btn btn-secondary w-full text-xs md:text-base py-1.5 md:py-2 mt-2 md:mt-4"> |
| Refresh |
| </button> |
| </motion.div> |
| )} |
| </motion.div> |
| </div> |
| ); |
| } |
|
|