diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf5d60ce..c0b85432 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -175,4 +175,4 @@ jobs: echo "SSL_PASSWORD=${{ secrets.SSL_PASSWORD }}" >> .env docker compose --profile prod down docker compose --profile prod up -d --pull always - docker image prune + docker image prune -f diff --git a/api/src/main/java/lab/en2b/quizapi/commons/utils/GameModeUtils.java b/api/src/main/java/lab/en2b/quizapi/commons/utils/GameModeUtils.java index 80c294bc..047df172 100644 --- a/api/src/main/java/lab/en2b/quizapi/commons/utils/GameModeUtils.java +++ b/api/src/main/java/lab/en2b/quizapi/commons/utils/GameModeUtils.java @@ -15,11 +15,11 @@ public static List getQuestionCategoriesForGamemode(GameMode g gamemode = KIWI_QUEST; } return switch (gamemode) { - case KIWI_QUEST -> List.of(QuestionCategory.ART,/* QuestionCategory.MUSIC, */ QuestionCategory.GEOGRAPHY); + case KIWI_QUEST -> List.of(QuestionCategory.ART,QuestionCategory.GEOGRAPHY); case FOOTBALL_SHOWDOWN -> List.of(QuestionCategory.SPORTS); case GEO_GENIUS -> List.of(QuestionCategory.GEOGRAPHY); case VIDEOGAME_ADVENTURE -> List.of(QuestionCategory.VIDEOGAMES); - case ANCIENT_ODYSSEY -> List.of(/*QuestionCategory.MUSIC,*/QuestionCategory.ART); + case ANCIENT_ODYSSEY -> List.of(QuestionCategory.MUSIC,QuestionCategory.ART); case RANDOM -> List.of(QuestionCategory.values()); case CUSTOM -> questionCategoriesForCustom; }; @@ -70,12 +70,12 @@ private static List getQuestionCategoriesEn(){ .description("Are you an art expert? Prove it!") .internalRepresentation(QuestionCategory.ART) .build(), - /* + QuestionCategoryDto.builder() .name("Music") .description("Are you a music lover? Prove it!") .internalRepresentation(QuestionCategory.MUSIC) - .build(),*/ + .build(), QuestionCategoryDto.builder() .name("Geography") .description("Are you a geography expert? Prove it!") @@ -101,12 +101,12 @@ private static List getQuestionCategoriesEs(){ .description("¿Eres un experto en arte? ¡Demuéstralo!") .internalRepresentation(QuestionCategory.ART) .build(), - /* + QuestionCategoryDto.builder() .name("Música") .description("¿Eres un melómano? ¡Demuéstralo!") .internalRepresentation(QuestionCategory.MUSIC) - .build(),*/ + .build(), QuestionCategoryDto.builder() .name("Geografía") .description("¿Eres un experto en geografía? ¡Demuéstralo!") diff --git a/api/src/main/java/lab/en2b/quizapi/questions/question/QuestionCategory.java b/api/src/main/java/lab/en2b/quizapi/questions/question/QuestionCategory.java index a6f0e741..d97db494 100644 --- a/api/src/main/java/lab/en2b/quizapi/questions/question/QuestionCategory.java +++ b/api/src/main/java/lab/en2b/quizapi/questions/question/QuestionCategory.java @@ -2,6 +2,5 @@ public enum QuestionCategory { //HISTORY, GEOGRAPHY, SCIENCE, MATH, LITERATURE, ART, SPORTS, MUSIC, MOVIES, TV, POLITICS, OTHER - GEOGRAPHY, SPORTS, //MUSIC, - ART, VIDEOGAMES + GEOGRAPHY, SPORTS, MUSIC, ART, VIDEOGAMES } diff --git a/webapp/src/components/GoBack.jsx b/webapp/src/components/GoBack.jsx index bd90ef0f..856368a5 100644 --- a/webapp/src/components/GoBack.jsx +++ b/webapp/src/components/GoBack.jsx @@ -6,8 +6,8 @@ import { useNavigate } from "react-router"; export default function GoBack() { const {t} = useTranslation(); const navigate = useNavigate(); - return - diff --git a/webapp/src/components/dashboard/CustomGameMenu.jsx b/webapp/src/components/dashboard/CustomGameMenu.jsx index 603566d9..6e5079d0 100644 --- a/webapp/src/components/dashboard/CustomGameMenu.jsx +++ b/webapp/src/components/dashboard/CustomGameMenu.jsx @@ -12,27 +12,20 @@ import { newGame, gameCategories } from 'components/game/Game'; const CustomGameMenu = ({ isOpen, onClose }) => { const navigate = useNavigate(); + const [selectedCategories, setSelectedCategories] = useState([]); + const [allCategories, setAllCategories] = useState([]); const [rounds, setRounds] = useState(9); const [time, setTime] = useState(20); - const [categories, setCategories] = useState([]); + const { t, i18n } = useTranslation(); useEffect(() => { async function fetchCategories() { try { - let lang = i18n.language; - if (lang.includes("en")) { - lang = "en"; - } else if (lang.includes("es")) { - lang = "es" - } else { - lang = "en"; - } - + const lang = getNormalizedLanguage(i18n.language); const categoriesData = (await gameCategories(lang)).data; - const formattedCategories = categoriesData.map(category => category.name); - setCategories(formattedCategories); + setAllCategories(categoriesData.map(category => category)); } catch (error) { console.error("Error fetching game categories:", error); } @@ -40,45 +33,47 @@ const CustomGameMenu = ({ isOpen, onClose }) => { fetchCategories(); }, [i18n.language]); + const getNormalizedLanguage = (language) => { + if (language.includes("en")) + return "en"; + else if (language.includes("es")) + return "es"; + else + return "en"; + }; + const manageCategory = (category) => { - if (selectedCategories.includes(category)) { - setSelectedCategories(selectedCategories.filter(item => item !== category)); - } else { - setSelectedCategories([...selectedCategories, category]); - } + if (selectedCategories.includes(category.internal_representation)) + setSelectedCategories(selectedCategories.filter(item => item !== category.internal_representation)); + else + setSelectedCategories([...selectedCategories, category.internal_representation]); }; const initializeCustomGameMode = async () => { try { - let lang = i18n.language; - if (lang.includes("en")) { - lang = "en"; - } else if (lang.includes("es")) { - lang = "es" - } else { - lang = "en"; - } + const lang = getNormalizedLanguage(i18n.language); const gamemode = 'CUSTOM'; - let uppercaseCategories = selectedCategories.map(category => category.toUpperCase()); - if (uppercaseCategories.length === 0) { - uppercaseCategories = ["GEOGRAPHY", "SPORTS", "MUSIC", "ART", "VIDEOGAMES"]; - } - + + let categoriesCustom = selectedCategories; + if (categoriesCustom.length === 0) + categoriesCustom = allCategories.map(category => category.internal_representation); + const customGameDto = { rounds: rounds, - categories: uppercaseCategories, + categories: categoriesCustom, round_duration: time - } + const newGameResponse = await newGame(lang, gamemode, customGameDto); - if (newGameResponse) { - navigate("/dashboard/game"); - } - } catch (error) { + + if (newGameResponse) + navigate("/dashboard/game"); + + } catch (error) { console.error("Error initializing game:", error); - } - }; + } + }; return ( @@ -112,16 +107,16 @@ const CustomGameMenu = ({ isOpen, onClose }) => { {t("game.categories")} - {categories.map(category => ( + {allCategories.map(category => ( ))} diff --git a/webapp/src/components/game/Game.js b/webapp/src/components/game/Game.js index 18383d4c..eb1323c0 100644 --- a/webapp/src/components/game/Game.js +++ b/webapp/src/components/game/Game.js @@ -10,8 +10,8 @@ export async function getCurrentGame() { return await authManager.getAxiosInstance().get(process.env.REACT_APP_API_ENDPOINT + "/games/play"); } -export async function gameCategories() { - return await authManager.getAxiosInstance().get(process.env.REACT_APP_API_ENDPOINT + "/games/question-categories"); +export async function gameCategories(lang) { + return await authManager.getAxiosInstance().get(process.env.REACT_APP_API_ENDPOINT + "/games/question-categories?lang=" + lang); } export async function gameModes() { diff --git a/webapp/src/pages/Results.jsx b/webapp/src/pages/Results.jsx index 6ab60e96..3d8b1267 100644 --- a/webapp/src/pages/Results.jsx +++ b/webapp/src/pages/Results.jsx @@ -1,17 +1,27 @@ -import React from "react"; +import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Button, Flex, Box, Heading, Center } from "@chakra-ui/react"; import { useNavigate, useLocation } from "react-router-dom"; import UserStatistics from "../components/statistics/UserStatistics"; +import LateralMenu from '../components/menu/LateralMenu'; +import MenuButton from '../components/menu/MenuButton'; export default function Results() { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const location = useLocation(); const navigate = useNavigate(); const correctAnswers = location.state?.correctAnswers || 0; + const [isMenuOpen, setIsMenuOpen] = useState(false); + + const changeLanguage = async (selectedLanguage) => { + await i18n.changeLanguage(selectedLanguage); + }; return (
+ setIsMenuOpen(true)} /> + setIsMenuOpen(false)} changeLanguage={changeLanguage} isDashboard={false}/> + {t("common.results")} {`Correct answers: ${correctAnswers}`} diff --git a/webapp/src/pages/Statistics.jsx b/webapp/src/pages/Statistics.jsx index 7d20002e..92ace61f 100644 --- a/webapp/src/pages/Statistics.jsx +++ b/webapp/src/pages/Statistics.jsx @@ -1,4 +1,4 @@ -import { Box, Center, Heading, Stack, StackDivider, Table, Tbody, Text, +import { Box, Center, Heading, Stack, Table, Tbody, Text, Td, Th, Thead, Tr, CircularProgress} from "@chakra-ui/react"; import React, {useEffect, useState} from "react"; import { useTranslation } from "react-i18next"; @@ -80,9 +80,7 @@ export default function Statistics() { t={t} errorWhere={"error.statistics.top"}/> {t("common.statistics.title")} - } minH="50vh" - p="1rem" backgroundColor="whiteAlpha.900" shadow="1.25em" - boxShadow="md" rounded="1rem" alignItems={"center"} data-testid={"leaderboard-component"}> + {retrievedData ? @@ -111,8 +109,8 @@ export default function Statistics() { : } + -
);