Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Front javier #50

Merged
merged 2 commits into from
Mar 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions webapp/src/components/game/Game.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,28 @@ import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
import Spinner from 'react-bootstrap/Spinner';
import { useNavigate } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
import './game.css';
import "bootstrap/dist/css/bootstrap.min.css";
import { getNextQuestion } from '../../services/GameService';
import { useConfig } from './GameConfigProvider';


/**
* React component that represents a wichat game with his timer, question, image,
* answers and chat with the LLM to ask for clues.
*
* @param {Number} questionTime - The initial time in seconds to answer the question.
* @param {Array} answers - The array of answers with the text and if it is the correct answer.
* @returns the hole game screen with the timer, question, image, answers and chat with the LLM.
*/
export const Game = () => {

// Game configuration
const { config } = useConfig();
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();

const questionTime = location.state?.questionTime || 120; // Get the question time from the location state or set it to 120 seconds by default
const questionTime = config.timePerRound; // Get the question time from the configuration
const numberOfQuestions = config.questions; // Get the number of questions from tge configuration
const topics = config.topics; // Get the topics from the configuration

// State that stores the answers of the current question with the text and if it is the correct answer
const [answers, setAnswers] = useState([]);
Expand All @@ -47,6 +48,7 @@ export const Game = () => {
// with attributes: topic, imageUrl, wasUserCorrect, selectedAnswer (text of the answer selected)
// and answers (an array of objects with text and isCorrect)
const [questionResults, setQuestionResults] = useState([]);
const [numberOfQuestionsAnswered, setNumberOfQuestionsAnswered] = useState(0);

const onTimeUp = () => {
blockAnswerButtons();
Expand All @@ -57,7 +59,12 @@ export const Game = () => {

const askForNextQuestion = () => {
prepareUIForNextQuestion();
setNumberOfQuestionsAnswered(numberOfQuestionsAnswered + 1);

if (numberOfQuestionsAnswered === numberOfQuestions) {
navigate('/game-results'); // TODO: Send game info to the results page
return;
}
getNextQuestion().then((questionInfo) => {
setIsLoading(false);
setQuestion(questionInfo.question);
Expand Down
43 changes: 43 additions & 0 deletions webapp/src/components/game/GameConfigProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Component } from "react";
import { createContext, useContext, useState, useEffect } from "react";

const ConfigContext = createContext();

const defaultConfig = { questions: 30, timePerRound: 120, topics: [] };

/**
* Provider for the game configuration, it will store the configuration in the local storage
*
* @param {Component} children Component that will be wrapped by the provider
* @returns
*/
export const GameConfigProvider = ({ children }) => {

// State to store the configuration
// its initial value is the value stored in the local storage
const [config, setConfig] = useState(() => {
const savedConfig = localStorage.getItem("gameConfig");
return savedConfig ? JSON.parse(savedConfig) : defaultConfig;
});

// Save the configuration in the local storage when it changes
useEffect(() => {
localStorage.setItem("gameConfig", JSON.stringify(config));
}, [config]);

// Function to reset the configuration to the default values
const resetConfig = () => {
setConfig(defaultConfig);
localStorage.setItem("gameConfig", JSON.stringify(defaultConfig));
}

return (
<ConfigContext.Provider value={{ config, setConfig, resetConfig }}>
{children}
</ConfigContext.Provider>
);
};

export const useConfig = () => {
return useContext(ConfigContext);
};
46 changes: 38 additions & 8 deletions webapp/src/components/home/Configuration.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { Button, Dropdown } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import { GoXCircle } from "react-icons/go";
Expand All @@ -7,29 +7,59 @@ import "./configuration.css";
import ToggleButton from "react-bootstrap/ToggleButton";
import ToggleButtonGroup from "react-bootstrap/ToggleButtonGroup";
import { useNavigate } from "react-router-dom";
import { useConfig } from "../game/GameConfigProvider";

const Configuration = ({ onClose }) => {

// Constant to store the configuration of the game
const { config, setConfig, resetConfig } = useConfig();

const [questions, setQuestions] = useState(30);
const [time, setTime] = useState(120);
const { t } = useTranslation();
const [selectedButtons, setSelectedButtons] = useState([]);
const [selectedButtons, setSelectedButtons] = useState([]);
const [topics, setTopics] = useState([]);

const topicList = ["history", "science", "art", "sport", "geography"];

const navigate = useNavigate();

const handleClose = () => {
resetConfig();
onClose();
};

const navigate = useNavigate();
// Function to update the numberOfQuestionsSelected
const handleQuestionsChange = (value) => {
setQuestions(value);
setConfig((prevConfig) => ({ ...prevConfig, questions: value }));
};

// Function to update the timePerRound
const handleTimeChange = (value) => {
setTime(value);
setConfig((prevConfig) => ({ ...prevConfig, timePerRound: value }));
};

const handleButtonClick = (value) => {
setSelectedButtons((prevSelected) =>
prevSelected.includes(value)
? prevSelected.filter((item) => item !== value)
: [...prevSelected, value]
? prevSelected.filter((item) => item !== value)
: [...prevSelected, value]
);
const topic = topicList[value - 1];

// Adds or removes the topic from the list of topics
const updatedTopics = selectedButtons.includes(value)
? topics.filter((item) => item !== topic) // If value is in topics, remove it
: [...topics, topic]; // If value is not in topics, add it

setTopics(updatedTopics);
setConfig((prevConfig) => ({ ...prevConfig, topics: updatedTopics }));
};

const startGame = () => {
navigate('/game', { state: { questionTime: time }})
navigate('/game', { state: { questionTime: time } })
}

return (
Expand All @@ -39,7 +69,7 @@ const Configuration = ({ onClose }) => {
<h2 className="title">{t("title-configuration")}</h2>
<div className="config-option">
<label>{t("numberQuestions-configuration")}</label>
<Dropdown onSelect={(value) => setQuestions(Number(value))}>
<Dropdown onSelect={(value) => handleQuestionsChange(Number(value))}>
<Dropdown.Toggle variant="light">{questions}</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item eventKey={10}>10</Dropdown.Item>
Expand All @@ -50,7 +80,7 @@ const Configuration = ({ onClose }) => {
</div>
<div className="config-option">
<label>{t("time-configuration")}</label>
<Dropdown onSelect={(value) => setTime(Number(value))}>
<Dropdown onSelect={(value) => handleTimeChange(Number(value))}>
<Dropdown.Toggle variant="light">{time}s</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item eventKey={60}>60s</Dropdown.Item>
Expand Down
8 changes: 7 additions & 1 deletion webapp/src/components/home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import Button from "react-bootstrap/Button";
import Configuration from "./Configuration";
import { useTranslation } from "react-i18next";
import NavBar from "../NavBar";
import { GameConfigProvider } from '../game/GameConfigProvider';
import './home.css';

export const Home = () => {
const [showConfig, setShowConfig] = useState(false);
const { t } = useTranslation();


return (
<div className="home-container">
{/* NavBar */}
Expand All @@ -28,7 +30,11 @@ export const Home = () => {
</Button>
</div>

{showConfig && <Configuration onClose={() => setShowConfig(false)} />}
{showConfig &&
<GameConfigProvider key={Date.now()}> {/* Key to force re-render and configurate again */}
<Configuration onClose={() => setShowConfig(false)} />
</GameConfigProvider>
}
</div>
);
};
Loading
Loading