220 lines
6.5 KiB
React
220 lines
6.5 KiB
React
|
|
import React, { useEffect, useState } from 'react';
|
|||
|
|
import { useParams, useNavigate } from 'react-router-dom';
|
|||
|
|
import { useAuth } from '../context/AuthContext';
|
|||
|
|
import { useRoom } from '../hooks/useRoom';
|
|||
|
|
import { questionsApi } from '../services/api';
|
|||
|
|
import Game from '../components/Game';
|
|||
|
|
import './GamePage.css';
|
|||
|
|
|
|||
|
|
const GamePage = () => {
|
|||
|
|
const { roomCode } = useParams();
|
|||
|
|
const navigate = useNavigate();
|
|||
|
|
const { user } = useAuth();
|
|||
|
|
const {
|
|||
|
|
room,
|
|||
|
|
participants,
|
|||
|
|
loading,
|
|||
|
|
error,
|
|||
|
|
updateQuestionPack,
|
|||
|
|
} = useRoom(roomCode);
|
|||
|
|
|
|||
|
|
const [questions, setQuestions] = useState([]);
|
|||
|
|
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
|
|||
|
|
const [loadingQuestions, setLoadingQuestions] = useState(true);
|
|||
|
|
const [questionPacks, setQuestionPacks] = useState([]);
|
|||
|
|
const [selectedPackId, setSelectedPackId] = useState('');
|
|||
|
|
const [updatingPack, setUpdatingPack] = useState(false);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
const loadQuestions = async () => {
|
|||
|
|
if (!room) return;
|
|||
|
|
|
|||
|
|
setLoadingQuestions(true);
|
|||
|
|
try {
|
|||
|
|
if (room.questionPackId) {
|
|||
|
|
// Загружаем вопросы из пака
|
|||
|
|
if (room.questionPack && room.questionPack.questions) {
|
|||
|
|
const packQuestions = room.questionPack.questions;
|
|||
|
|
if (Array.isArray(packQuestions)) {
|
|||
|
|
setQuestions(packQuestions);
|
|||
|
|
} else {
|
|||
|
|
setQuestions([]);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// Загружаем пак отдельно, если он не включен в room
|
|||
|
|
const response = await questionsApi.getPack(room.questionPackId);
|
|||
|
|
if (response.data && response.data.questions) {
|
|||
|
|
setQuestions(
|
|||
|
|
Array.isArray(response.data.questions)
|
|||
|
|
? response.data.questions
|
|||
|
|
: [],
|
|||
|
|
);
|
|||
|
|
} else {
|
|||
|
|
setQuestions([]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// Пак не выбран, начинаем с пустого списка вопросов
|
|||
|
|
setQuestions([]);
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Error loading questions:', error);
|
|||
|
|
setQuestions([]);
|
|||
|
|
} finally {
|
|||
|
|
setLoadingQuestions(false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
loadQuestions();
|
|||
|
|
}, [room]);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
const fetchPacks = async () => {
|
|||
|
|
if (user && room && room.hostId === user.id) {
|
|||
|
|
try {
|
|||
|
|
const response = await questionsApi.getPacks(user.id);
|
|||
|
|
setQuestionPacks(response.data);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Error fetching question packs:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
fetchPacks();
|
|||
|
|
}, [user, room]);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (room && room.questionPackId) {
|
|||
|
|
setSelectedPackId(room.questionPackId);
|
|||
|
|
} else {
|
|||
|
|
setSelectedPackId('');
|
|||
|
|
}
|
|||
|
|
}, [room]);
|
|||
|
|
|
|||
|
|
const handleUpdateQuestionPack = async () => {
|
|||
|
|
if (!selectedPackId) {
|
|||
|
|
alert('Выберите пак вопросов');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
setUpdatingPack(true);
|
|||
|
|
await updateQuestionPack(selectedPackId);
|
|||
|
|
// Перезагружаем вопросы после обновления пака
|
|||
|
|
const response = await questionsApi.getPack(selectedPackId);
|
|||
|
|
if (response.data && response.data.questions) {
|
|||
|
|
setQuestions(
|
|||
|
|
Array.isArray(response.data.questions)
|
|||
|
|
? response.data.questions
|
|||
|
|
: [],
|
|||
|
|
);
|
|||
|
|
setCurrentQuestionIndex(0);
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Error updating question pack:', error);
|
|||
|
|
alert('Ошибка при обновлении пака вопросов');
|
|||
|
|
} finally {
|
|||
|
|
setUpdatingPack(false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleQuestionsChange = (newQuestions) => {
|
|||
|
|
setQuestions(newQuestions);
|
|||
|
|
if (currentQuestionIndex >= newQuestions.length) {
|
|||
|
|
setCurrentQuestionIndex(0);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (loading || loadingQuestions) {
|
|||
|
|
return <div className="loading">Загрузка игры...</div>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (error) {
|
|||
|
|
return (
|
|||
|
|
<div className="error-page">
|
|||
|
|
<h1>Ошибка</h1>
|
|||
|
|
<p>{error}</p>
|
|||
|
|
<button onClick={() => navigate('/')}>На главную</button>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!room) {
|
|||
|
|
return (
|
|||
|
|
<div className="error-page">
|
|||
|
|
<h1>Комната не найдена</h1>
|
|||
|
|
<button onClick={() => navigate('/')}>На главную</button>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const isHost = user && room.hostId === user.id;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="game-page">
|
|||
|
|
{isHost && (
|
|||
|
|
<div className="host-controls">
|
|||
|
|
<div className="pack-selector-inline">
|
|||
|
|
<label>Пак вопросов:</label>
|
|||
|
|
<select
|
|||
|
|
value={selectedPackId}
|
|||
|
|
onChange={(e) => setSelectedPackId(e.target.value)}
|
|||
|
|
disabled={updatingPack}
|
|||
|
|
>
|
|||
|
|
<option value="">
|
|||
|
|
{room.questionPackId
|
|||
|
|
? 'Изменить пак вопросов'
|
|||
|
|
: 'Выберите пак вопросов'}
|
|||
|
|
</option>
|
|||
|
|
{questionPacks.map((pack) => (
|
|||
|
|
<option key={pack.id} value={pack.id}>
|
|||
|
|
{pack.name} ({pack.questionCount} вопросов)
|
|||
|
|
</option>
|
|||
|
|
))}
|
|||
|
|
</select>
|
|||
|
|
<button
|
|||
|
|
onClick={handleUpdateQuestionPack}
|
|||
|
|
disabled={
|
|||
|
|
!selectedPackId ||
|
|||
|
|
selectedPackId === room.questionPackId ||
|
|||
|
|
updatingPack
|
|||
|
|
}
|
|||
|
|
className="secondary"
|
|||
|
|
>
|
|||
|
|
{updatingPack ? 'Сохранение...' : 'Применить'}
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
onClick={() => navigate(`/room/${roomCode}`)}
|
|||
|
|
className="secondary"
|
|||
|
|
>
|
|||
|
|
Назад в комнату
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
<div className="game-container">
|
|||
|
|
{questions.length === 0 && (
|
|||
|
|
<div className="no-questions-banner">
|
|||
|
|
<p>
|
|||
|
|
Вопросы не загружены.
|
|||
|
|
{isHost
|
|||
|
|
? ' Выберите пак вопросов выше, чтобы начать игру.'
|
|||
|
|
: ' Ожидайте, пока ведущий добавит вопросы.'}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
<Game
|
|||
|
|
questions={questions}
|
|||
|
|
currentQuestionIndex={currentQuestionIndex}
|
|||
|
|
onQuestionIndexChange={setCurrentQuestionIndex}
|
|||
|
|
onQuestionsChange={handleQuestionsChange}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default GamePage;
|