sto-k-odnomu/src/components/GameManagementModal.jsx

301 lines
10 KiB
React
Raw Normal View History

2026-01-08 20:14:58 +00:00
import { useState } from 'react'
import './GameManagementModal.css'
const GameManagementModal = ({
isOpen,
onClose,
room,
participants,
currentQuestion,
currentQuestionIndex,
totalQuestions,
revealedAnswers,
onStartGame,
onEndGame,
onNextQuestion,
onPreviousQuestion,
onRevealAnswer,
onHideAnswer,
onShowAllAnswers,
onHideAllAnswers,
onAwardPoints,
onPenalty,
}) => {
const [activeTab, setActiveTab] = useState('players') // players | game | answers | scoring
const [selectedPlayer, setSelectedPlayer] = useState(null)
const [customPoints, setCustomPoints] = useState(10)
if (!isOpen) return null
const gameStatus = room?.status || 'WAITING'
const areAllAnswersRevealed = currentQuestion
? revealedAnswers.length === currentQuestion.answers.length
: false
// Handlers
const handleBackdropClick = (e) => {
if (e.target === e.currentTarget) onClose()
}
const handleRevealAnswer = (index) => {
if (revealedAnswers.includes(index)) {
onHideAnswer(index)
} else {
onRevealAnswer(index)
}
}
const handleAwardPoints = (points) => {
if (selectedPlayer) {
onAwardPoints(selectedPlayer, points)
}
}
const handlePenalty = () => {
if (selectedPlayer) {
onPenalty(selectedPlayer)
}
}
return (
<div className="game-mgmt-modal-backdrop" onClick={handleBackdropClick}>
<div className="game-mgmt-modal-content">
{/* Header with title and close button */}
<div className="game-mgmt-modal-header">
<h2>🎛 Управление игрой</h2>
<button className="game-mgmt-close" onClick={onClose}>×</button>
</div>
{/* Tabs navigation */}
<div className="game-mgmt-tabs">
<button
className={`tab ${activeTab === 'players' ? 'active' : ''}`}
onClick={() => setActiveTab('players')}
>
👥 Игроки
</button>
<button
className={`tab ${activeTab === 'game' ? 'active' : ''}`}
onClick={() => setActiveTab('game')}
>
🎮 Игра
</button>
<button
className={`tab ${activeTab === 'answers' ? 'active' : ''}`}
onClick={() => setActiveTab('answers')}
disabled={gameStatus !== 'PLAYING' || !currentQuestion}
>
👁 Ответы
</button>
<button
className={`tab ${activeTab === 'scoring' ? 'active' : ''}`}
onClick={() => setActiveTab('scoring')}
disabled={gameStatus !== 'PLAYING' || participants.length === 0}
>
Очки
</button>
</div>
{/* Tab content */}
<div className="game-mgmt-body">
{/* PLAYERS TAB */}
{activeTab === 'players' && (
<div className="tab-content">
<h3>Участники ({participants.length})</h3>
<div className="players-list">
{participants.length === 0 ? (
<p className="empty-message">Нет участников</p>
) : (
participants.map((participant) => (
<div key={participant.id} className="player-item">
<div className="player-info">
<span className="player-name">{participant.name}</span>
<span className="player-role">
{participant.role === 'HOST' && '👑 Ведущий'}
{participant.role === 'SPECTATOR' && '👀 Зритель'}
</span>
</div>
<div className="player-score">
{participant.score || 0} очков
</div>
</div>
))
)}
</div>
</div>
)}
{/* GAME CONTROLS TAB */}
{activeTab === 'game' && (
<div className="tab-content">
<h3>Управление игрой</h3>
<div className="game-status">
<strong>Статус:</strong>
{gameStatus === 'WAITING' && ' Ожидание'}
{gameStatus === 'PLAYING' && ' Идет игра'}
{gameStatus === 'FINISHED' && ' Завершена'}
</div>
{gameStatus === 'WAITING' && (
<button
className="mgmt-button start-button"
onClick={onStartGame}
disabled={participants.length < 2}
>
Начать игру
</button>
)}
{gameStatus === 'PLAYING' && (
<div className="game-controls">
<div className="question-nav">
<button
className="mgmt-button"
onClick={onPreviousQuestion}
disabled={currentQuestionIndex === 0}
>
Предыдущий
</button>
<span className="question-indicator">
Вопрос {currentQuestionIndex + 1} / {totalQuestions}
</span>
<button
className="mgmt-button"
onClick={onNextQuestion}
disabled={currentQuestionIndex >= totalQuestions - 1}
>
Следующий
</button>
</div>
<button
className="mgmt-button end-button"
onClick={onEndGame}
>
Завершить игру
</button>
</div>
)}
<div className="game-info">
<div className="info-item">
<span>Игроков:</span> <strong>{participants.length}</strong>
</div>
{gameStatus === 'PLAYING' && totalQuestions > 0 && (
<div className="info-item">
<span>Вопросов:</span> <strong>{totalQuestions}</strong>
</div>
)}
</div>
</div>
)}
{/* ANSWERS CONTROL TAB */}
{activeTab === 'answers' && currentQuestion && (
<div className="tab-content">
<h3>Управление ответами</h3>
<button
className="mgmt-button toggle-all-button"
onClick={areAllAnswersRevealed ? onHideAllAnswers : onShowAllAnswers}
>
{areAllAnswersRevealed ? '🙈 Скрыть все' : '👁 Показать все'}
</button>
<div className="answers-grid">
{currentQuestion.answers.map((answer, index) => (
<button
key={index}
className={`answer-button ${
revealedAnswers.includes(index) ? 'revealed' : 'hidden'
}`}
onClick={() => handleRevealAnswer(index)}
>
<span className="answer-num">{index + 1}</span>
<span className="answer-txt">{answer.text}</span>
<span className="answer-pts">{answer.points}</span>
</button>
))}
</div>
</div>
)}
{/* SCORING TAB */}
{activeTab === 'scoring' && (
<div className="tab-content">
<h3>Начисление очков</h3>
<div className="player-selector">
<label>Выберите игрока:</label>
<select
value={selectedPlayer || ''}
onChange={(e) => setSelectedPlayer(e.target.value || null)}
>
<option value="">-- Выберите игрока --</option>
{participants
.filter((p) => p.role === 'PLAYER')
.map((player) => (
<option key={player.id} value={player.id}>
{player.name} ({player.score || 0} очков)
</option>
))}
</select>
</div>
{selectedPlayer && (
<div className="scoring-section">
<div className="quick-points">
<button
className="mgmt-button points-button"
onClick={() => handleAwardPoints(5)}
>
+5
</button>
<button
className="mgmt-button points-button"
onClick={() => handleAwardPoints(10)}
>
+10
</button>
<button
className="mgmt-button points-button"
onClick={() => handleAwardPoints(20)}
>
+20
</button>
<button
className="mgmt-button penalty-button"
onClick={handlePenalty}
>
Промах
</button>
</div>
<div className="custom-points">
<input
type="number"
min="1"
max="100"
value={customPoints}
onChange={(e) => setCustomPoints(parseInt(e.target.value) || 0)}
/>
<button
className="mgmt-button custom-button"
onClick={() => handleAwardPoints(customPoints)}
>
Начислить {customPoints}
</button>
</div>
</div>
)}
</div>
)}
</div>
</div>
</div>
)
}
export default GameManagementModal