import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, StyleSheet, TouchableOpacity, Alert, Dimensions } from 'react-native'; import { GameButton } from '../../components/common/GameHeader'; import { GameContainer } from '../../components/common/GameContainer'; import { ConfirmDialog, GameModal } from '../../components/common/GameModal'; import { useMultiplayerRoom, useMultiplayerGame } from './useMultiplayer'; import { GameRoom, MultiplayerPlayer } from './MultiplayerService'; const { width: screenWidth } = Dimensions.get('window'); interface MultiplayerWaitingRoomProps { room: GameRoom; playerId: string; onGameStarted: () => void; onLeaveRoom: () => void; } /** * Waiting room component for multiplayer games * Shows players, ready status, and allows host to start the game */ export const MultiplayerWaitingRoom: React.FC = ({ room, playerId, onGameStarted, onLeaveRoom }) => { const [showLeaveConfirm, setShowLeaveConfirm] = useState(false); const [showGameSettings, setShowGameSettings] = useState(false); const [gameConfig, setGameConfig] = useState({ timeLimit: 300, // 5 minutes difficulty: 'medium', rounds: 3 }); const { isHost, setReady, startGame, leaveRoom, isLoading, error } = useMultiplayerRoom(playerId); const { gameState } = useMultiplayerGame(room.id); const currentPlayer = room.players.find(p => p.playerId === playerId); const allPlayersReady = room.players.every(p => p.isReady); const canStartGame = isHost && allPlayersReady && room.players.length >= 2; // Listen for game start useEffect(() => { if (gameState && gameState.room.status === 'playing') { onGameStarted(); } }, [gameState, onGameStarted]); const handleReady = () => { if (currentPlayer) { setReady(!currentPlayer.isReady); } }; const handleStartGame = async () => { try { await startGame(gameConfig); } catch (err) { Alert.alert('שגיאה', 'לא ניתן להתחיל את המשחק'); } }; const handleLeaveRoom = async () => { setShowLeaveConfirm(false); try { await leaveRoom(); onLeaveRoom(); } catch (err) { Alert.alert('שגיאה', 'לא ניתן לעזוב את החדר'); } }; return ( {/* Room Info */} שחקנים {room.players.length}/{room.maxPlayers} מוכנים {room.players.filter(p => p.isReady).length}/{room.players.length} {room.isPrivate && ( 🔒 פרטי )} {isHost && ( 👑 אתה המארח )} {/* Players List */} שחקנים item.playerId} renderItem={({ item }) => ( )} style={styles.playersList} showsVerticalScrollIndicator={false} /> {/* Game Settings (Host Only) */} {isHost && ( setShowGameSettings(true)} > ⚙️ הגדרות משחק )} {/* Action Buttons */} setShowLeaveConfirm(true)} variant="danger" style={styles.leaveButton} /> {!isHost ? ( ) : ( )} {/* Status Messages */} {!allPlayersReady && room.players.length >= 2 && ( ממתינים שכל השחקנים יהיו מוכנים... )} {room.players.length < 2 && ( נדרשים לפחות 2 שחקנים להתחלת המשחק )} {/* Error Display */} {error && ( {error} )} {/* Modals */} setShowLeaveConfirm(false)} dangerous={true} /> setShowGameSettings(false)} gameConfig={gameConfig} onSave={setGameConfig} /> ); }; interface PlayerItemProps { player: MultiplayerPlayer; isCurrentPlayer: boolean; isHost: boolean; } const PlayerItem: React.FC = ({ player, isCurrentPlayer, isHost }) => { const getStatusIcon = () => { if (player.connectionStatus === 'disconnected') return '🔴'; if (player.connectionStatus === 'reconnecting') return '🟡'; if (player.isReady) return '✅'; return '⏳'; }; const getStatusText = () => { if (player.connectionStatus === 'disconnected') return 'לא מחובר'; if (player.connectionStatus === 'reconnecting') return 'מתחבר מחדש'; if (player.isReady) return 'מוכן'; return 'לא מוכן'; }; return ( {player.firstName || `שחקן ${player.playerId.slice(-4)}`} {isCurrentPlayer && ' (אתה)'} {isHost && ( 👑 )} {getStatusIcon()} {getStatusText()} ); }; interface GameSettingsModalProps { visible: boolean; onClose: () => void; gameConfig: any; onSave: (config: any) => void; } const GameSettingsModal: React.FC = ({ visible, onClose, gameConfig, onSave }) => { const [localConfig, setLocalConfig] = useState(gameConfig); const handleSave = () => { onSave(localConfig); onClose(); }; const timeLimitOptions = [ { label: '3 דקות', value: 180 }, { label: '5 דקות', value: 300 }, { label: '10 דקות', value: 600 }, { label: 'ללא הגבלה', value: null } ]; const difficultyOptions = [ { label: 'קל', value: 'easy' }, { label: 'בינוני', value: 'medium' }, { label: 'קשה', value: 'hard' } ]; const roundsOptions = [1, 3, 5, 10]; return ( {/* Time Limit */} מגבלת זמן {timeLimitOptions.map((option) => ( setLocalConfig({ ...localConfig, timeLimit: option.value })} > {option.label} ))} {/* Difficulty */} רמת קושי {difficultyOptions.map((option) => ( setLocalConfig({ ...localConfig, difficulty: option.value })} > {option.label} ))} {/* Rounds */} מספר סיבובים {roundsOptions.map((rounds) => ( setLocalConfig({ ...localConfig, rounds })} > {rounds} ))} ); }; const styles = StyleSheet.create({ roomInfo: { backgroundColor: '#F8F9FA', padding: 16, borderRadius: 12, marginBottom: 24, }, roomStats: { flexDirection: 'row', justifyContent: 'space-around', marginBottom: 12, }, statItem: { alignItems: 'center', }, statLabel: { fontSize: 12, color: '#666', marginBottom: 4, }, statValue: { fontSize: 18, fontWeight: 'bold', color: '#333', }, privateLabel: { fontSize: 14, color: '#FF9500', fontWeight: 'bold', }, hostIndicator: { textAlign: 'center', fontSize: 16, fontWeight: 'bold', color: '#007AFF', }, playersSection: { flex: 1, marginBottom: 24, }, sectionTitle: { fontSize: 18, fontWeight: 'bold', color: '#333', marginBottom: 16, }, playersList: { flex: 1, }, playerItem: { backgroundColor: '#FFFFFF', padding: 16, borderRadius: 12, marginBottom: 12, borderWidth: 2, borderColor: 'transparent', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, currentPlayerItem: { borderColor: '#007AFF', backgroundColor: '#F0F8FF', }, playerInfo: { flex: 1, }, playerHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, }, playerName: { fontSize: 16, fontWeight: 'bold', color: '#333', flex: 1, }, currentPlayerName: { color: '#007AFF', }, hostBadge: { fontSize: 20, }, playerStatus: { flexDirection: 'row', alignItems: 'center', }, statusIcon: { fontSize: 16, marginRight: 8, }, statusText: { fontSize: 14, color: '#666', }, settingsSection: { marginBottom: 16, }, settingsButton: { backgroundColor: '#F0F0F0', padding: 12, borderRadius: 8, alignItems: 'center', }, settingsButtonText: { fontSize: 16, color: '#333', fontWeight: 'bold', }, actions: { flexDirection: 'row', gap: 12, }, leaveButton: { flex: 1, }, readyButton: { flex: 1, }, startButton: { flex: 2, }, statusMessage: { backgroundColor: '#FFF3CD', padding: 12, borderRadius: 8, marginTop: 16, alignItems: 'center', }, statusMessageText: { color: '#856404', fontSize: 14, textAlign: 'center', }, errorContainer: { backgroundColor: '#FFEBEE', padding: 12, borderRadius: 8, marginTop: 16, }, errorText: { color: '#D32F2F', fontSize: 14, textAlign: 'center', }, settingsContainer: { paddingVertical: 8, }, settingLabel: { fontSize: 16, fontWeight: 'bold', color: '#333', marginBottom: 12, marginTop: 16, }, optionsContainer: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, }, optionButton: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, backgroundColor: '#F0F0F0', borderWidth: 1, borderColor: '#E0E0E0', }, selectedOption: { backgroundColor: '#007AFF', borderColor: '#007AFF', }, optionText: { fontSize: 14, color: '#666', }, selectedOptionText: { color: 'white', fontWeight: 'bold', }, roundOption: { width: 50, height: 50, borderRadius: 25, backgroundColor: '#F0F0F0', borderWidth: 1, borderColor: '#E0E0E0', justifyContent: 'center', alignItems: 'center', marginRight: 12, }, selectedRoundOption: { backgroundColor: '#007AFF', borderColor: '#007AFF', }, roundOptionText: { fontSize: 16, fontWeight: 'bold', color: '#666', }, selectedRoundOptionText: { color: 'white', }, modalButtons: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 24, }, modalButton: { flex: 1, marginHorizontal: 8, }, });