import React, { useState } from 'react'; import { View, Text, TextInput, FlatList, StyleSheet, TouchableOpacity, Alert, Switch, ActivityIndicator } from 'react-native'; import { GameButton, LoadingSpinner } from '../../components/common/GameHeader'; import { GameModal } from '../../components/common/GameModal'; import { GameContainer } from '../../components/common/GameContainer'; import { useMultiplayerRoom, useMultiplayerLobby } from './useMultiplayer'; import { GameRoom } from './MultiplayerService'; interface MultiplayerLobbyProps { playerId: string; onRoomJoined: (room: GameRoom) => void; availableGames: { id: string; name: string }[]; } /** * Lobby component for browsing and creating multiplayer rooms */ export const MultiplayerLobby: React.FC = ({ playerId, onRoomJoined, availableGames }) => { const [showCreateRoom, setShowCreateRoom] = useState(false); const { currentRoom, connectionStatus, isLoading, error, createRoom, joinRoom, clearError } = useMultiplayerRoom(playerId); const { publicRooms, loadPublicRooms } = useMultiplayerLobby(); // Handle room joined React.useEffect(() => { if (currentRoom) { onRoomJoined(currentRoom); } }, [currentRoom, onRoomJoined]); if (connectionStatus === 'connecting') { return ( ); } if (connectionStatus === 'disconnected') { return ( לא ניתן להתחבר לשרת המשחקים window.location.reload()} style={styles.retryButton} /> ); } return ( {error && ( {error} )} setShowCreateRoom(true)} variant="primary" size="large" style={styles.createButton} /> חדרים זמינים {publicRooms.length === 0 ? ( אין חדרים זמינים כרגע צור חדר חדש או נסה שוב מאוחר יותר ) : ( item.id} renderItem={({ item }) => } style={styles.roomsList} showsVerticalScrollIndicator={false} /> )} setShowCreateRoom(false)} onCreateRoom={createRoom} availableGames={availableGames} isLoading={isLoading} /> ); }; interface RoomItemProps { room: GameRoom; onJoin: (roomId: string, password?: string) => Promise; } const RoomItem: React.FC = ({ room, onJoin }) => { const [isJoining, setIsJoining] = useState(false); const [showPasswordInput, setShowPasswordInput] = useState(false); const [password, setPassword] = useState(''); const handleJoin = async () => { if (room.isPrivate && !showPasswordInput) { setShowPasswordInput(true); return; } setIsJoining(true); try { await onJoin(room.id, room.isPrivate ? password : undefined); } catch (error) { Alert.alert('שגיאה', 'לא ניתן להצטרף לחדר'); } finally { setIsJoining(false); setShowPasswordInput(false); setPassword(''); } }; return ( {room.name} {room.players.length}/{room.maxPlayers} שחקנים • {room.gameId} {room.isPrivate && 🔒 חדר פרטי} {showPasswordInput ? ( setShowPasswordInput(false)}> ביטול ) : null} = room.maxPlayers} size="small" style={styles.joinButton} /> ); }; interface CreateRoomModalProps { visible: boolean; onClose: () => void; onCreateRoom: (gameId: string, roomName: string, maxPlayers: number, isPrivate: boolean, password?: string) => Promise; availableGames: { id: string; name: string }[]; isLoading: boolean; } const CreateRoomModal: React.FC = ({ visible, onClose, onCreateRoom, availableGames, isLoading }) => { const [selectedGame, setSelectedGame] = useState(availableGames[0]?.id || ''); const [roomName, setRoomName] = useState(''); const [maxPlayers, setMaxPlayers] = useState(4); const [isPrivate, setIsPrivate] = useState(false); const [password, setPassword] = useState(''); const handleCreate = async () => { if (!selectedGame || !roomName.trim()) { Alert.alert('שגיאה', 'נא למלא את כל השדות הנדרשים'); return; } try { await onCreateRoom(selectedGame, roomName.trim(), maxPlayers, isPrivate, isPrivate ? password : undefined); onClose(); } catch (error) { Alert.alert('שגיאה', 'לא ניתן ליצור חדר'); } }; return ( בחר משחק: {availableGames.map(game => ( setSelectedGame(game.id)} > {game.name} ))} שם החדר: מספר שחקנים מקסימלי: {[2, 3, 4, 6, 8].map(count => ( setMaxPlayers(count)} > {count} ))} חדר פרטי: {isPrivate && ( <> סיסמה: )} ); }; const styles = StyleSheet.create({ centerContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, errorText: { fontSize: 16, color: '#FF3B30', textAlign: 'center', marginBottom: 20, }, retryButton: { marginTop: 20, }, errorContainer: { backgroundColor: '#FFE5E5', padding: 15, borderRadius: 8, marginBottom: 15, flexDirection: 'row', alignItems: 'center', }, closeError: { fontSize: 18, color: '#FF3B30', marginLeft: 'auto', }, header: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 20, }, createButton: { flex: 1, marginRight: 10, }, refreshButton: { flex: 1, marginLeft: 10, }, sectionTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 15, color: '#333', }, emptyState: { alignItems: 'center', padding: 40, }, emptyText: { fontSize: 16, color: '#666', marginBottom: 8, }, emptySubtext: { fontSize: 14, color: '#999', textAlign: 'center', }, roomsList: { flex: 1, }, roomItem: { backgroundColor: '#FFF', padding: 15, borderRadius: 8, marginBottom: 10, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, roomInfo: { marginBottom: 10, }, roomName: { fontSize: 16, fontWeight: 'bold', color: '#333', marginBottom: 5, }, roomDetails: { fontSize: 14, color: '#666', }, privateRoom: { fontSize: 12, color: '#FF9500', marginTop: 5, }, roomActions: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, passwordContainer: { flexDirection: 'row', alignItems: 'center', flex: 1, marginRight: 10, }, passwordInput: { flex: 1, borderWidth: 1, borderColor: '#DDD', borderRadius: 4, padding: 8, marginRight: 10, }, cancelPassword: { color: '#007AFF', fontSize: 14, }, joinButton: { minWidth: 80, }, modalContent: { padding: 20, }, modalLabel: { fontSize: 16, fontWeight: '600', marginBottom: 8, color: '#333', }, gameSelector: { flexDirection: 'row', flexWrap: 'wrap', marginBottom: 20, }, gameOption: { paddingHorizontal: 12, paddingVertical: 8, borderRadius: 6, borderWidth: 1, borderColor: '#DDD', marginRight: 8, marginBottom: 8, }, selectedGame: { backgroundColor: '#007AFF', borderColor: '#007AFF', }, gameOptionText: { fontSize: 14, color: '#333', }, selectedGameText: { color: '#FFF', }, textInput: { borderWidth: 1, borderColor: '#DDD', borderRadius: 4, padding: 12, fontSize: 16, marginBottom: 20, }, playerCountSelector: { flexDirection: 'row', marginBottom: 20, }, playerCountOption: { width: 40, height: 40, borderRadius: 20, borderWidth: 1, borderColor: '#DDD', justifyContent: 'center', alignItems: 'center', marginRight: 10, }, selectedPlayerCount: { backgroundColor: '#007AFF', borderColor: '#007AFF', }, playerCountText: { fontSize: 16, color: '#333', }, selectedPlayerCountText: { color: '#FFF', }, privateToggle: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, }, modalButtons: { flexDirection: 'row', justifyContent: 'space-between', }, modalButton: { flex: 1, marginHorizontal: 5, }, });