Compare commits

..

No commits in common. "19cdd9ab0d1595e59b78c5ee80e7e7ebb6b18ad9" and "1e48626808eed2176d3a7f96738b4f318917069f" have entirely different histories.

4 changed files with 10 additions and 308 deletions

View file

@ -7,7 +7,6 @@ import Home from './pages/Home';
import CreateRoom from './pages/CreateRoom';
import JoinRoom from './pages/JoinRoom';
import RoomPage from './pages/RoomPage';
import GamePage from './pages/GamePage';
import LocalGame from './pages/LocalGame';
import './App.css';
@ -23,7 +22,6 @@ function App() {
<Route path="/create-room" element={<CreateRoom />} />
<Route path="/join-room" element={<JoinRoom />} />
<Route path="/room/:roomCode" element={<RoomPage />} />
<Route path="/game/:roomCode" element={<GamePage />} />
<Route path="/local-game" element={<LocalGame />} />
</Routes>
</>

View file

@ -1,80 +0,0 @@
.game-page {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.host-controls {
background: var(--bg-secondary, #f5f5f5);
padding: 1rem;
border-bottom: 1px solid var(--border-color, #ddd);
}
.pack-selector-inline {
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.pack-selector-inline label {
font-weight: 500;
}
.pack-selector-inline select {
flex: 1;
min-width: 200px;
padding: 0.5rem;
border: 1px solid var(--border-color, #ddd);
border-radius: 4px;
font-size: 1rem;
}
.pack-selector-inline button {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
white-space: nowrap;
}
.pack-selector-inline button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.game-container {
flex: 1;
display: flex;
flex-direction: column;
}
.no-questions-banner {
text-align: center;
padding: 2rem;
background: var(--bg-secondary, #f5f5f5);
border-radius: 8px;
margin: 2rem;
}
.no-questions-banner p {
font-size: 1.2rem;
color: var(--text-secondary, #666);
margin-bottom: 1rem;
}
@media (max-width: 768px) {
.pack-selector-inline {
flex-direction: column;
align-items: stretch;
}
.pack-selector-inline select {
width: 100%;
}
.pack-selector-inline button {
width: 100%;
}
}

View file

@ -1,219 +0,0 @@
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;

View file

@ -100,6 +100,10 @@ const RoomPage = () => {
}, [room]);
const handleStartGame = () => {
if (!room.questionPackId) {
alert('Выберите пак вопросов перед началом игры');
return;
}
startGame();
navigate(`/game/${roomCode}`);
};
@ -177,22 +181,21 @@ const RoomPage = () => {
<strong>{room.questionPack.name}</strong> (
{room.questionPack.questionCount || 0} вопросов)
</p>
{isHost && (
{isHost && room.status === 'WAITING' && (
<p className="pack-hint">
Можете изменить пак вопросов в любой момент
Можете изменить пак вопросов перед началом игры
</p>
)}
</div>
) : (
<div className="pack-info">
<p className="pack-hint">
Пак вопросов не выбран. Вы можете начать игру без пака и
добавить его позже.
<p className="pack-warning">
Пак вопросов не выбран. Выберите пак для начала игры.
</p>
</div>
)}
{isHost && (
{isHost && room.status === 'WAITING' && (
<div className="pack-selector">
<select
value={selectedPackId}
@ -232,7 +235,7 @@ const RoomPage = () => {
{isHost && room.status === 'WAITING' && (
<button
onClick={handleStartGame}
disabled={participants.length < 2}
disabled={participants.length < 2 || !room.questionPackId}
className="primary"
>
Начать игру