Skip to content

Commit

Permalink
Merge pull request #248 from Arquisoft/feat/webapp/user-menu
Browse files Browse the repository at this point in the history
Feat: changing the dashboard
  • Loading branch information
jjgancfer authored Apr 19, 2024
2 parents 637ea18 + 2e2bdb5 commit 8dffc4c
Show file tree
Hide file tree
Showing 26 changed files with 573 additions and 104 deletions.
19 changes: 19 additions & 0 deletions webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-icons": "^5.0.1",
"react-nice-avatar": "^1.5.0",
"react-router": "^6.21.3",
"react-router-dom": "^6.21.3",
"react-scripts": "5.0.1",
Expand Down
19 changes: 15 additions & 4 deletions webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"finish": "Finish",
"english": "English",
"spanish": "Spanish",
"language": "Language:"
"language": "Language:",
"results": "Results",
"welcome": "Welcome"
},
"session": {
"username": "Username",
Expand All @@ -27,7 +29,8 @@
"confirm_password": "Confirm password",
"welcome": "Are you ready to test your ingenuity?",
"account": "Don't have an account?",
"clickHere": "Click here"
"clickHere": "Click here",
"resume": "Resume game"
},
"error": {
"login": "Login error: ",
Expand Down Expand Up @@ -76,12 +79,20 @@
},
"game": {
"round": "Round ",
"answer": "Answer"
"answer": "Answer",
"gamemodes": "Game modes",
"userinfo": "User panel",
"custom": "Custom",
"customgame": "Custom game",
"settings": "Game settings",
"rounds": "Rounds:",
"time": "Time:",
"categories": "Categories"
},
"about": {
"title": "About",
"description1": "We are the WIQ_EN2B group and we are delighted that you like 🥝KIWIQ🥝. Enjoy!!!",
"table1": "Developers🍌🍌",
"table1": "Developers",
"table2": "Contact"
}
}
19 changes: 15 additions & 4 deletions webapp/public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"finish": "Finalizar",
"english": "Inglés",
"spanish": "Español",
"language": "Idioma:"
"language": "Idioma:",
"results": "Resultados",
"welcome": "Bienvenid@"
},
"session": {
"username": "Nombre de usuario",
Expand All @@ -27,7 +29,8 @@
"confirm_password": "Confirmar contraseña",
"welcome": "¿Estás listo para poner a prueba tu ingenio?",
"account": "¿No tienes una cuenta?",
"clickHere": "Haz clic aquí"
"clickHere": "Haz clic aquí",
"resume": "Resumir partida"
},
"error": {
"login": "Error en el inicio de sesión: ",
Expand Down Expand Up @@ -75,12 +78,20 @@
},
"game": {
"round": "Ronda ",
"answer": "Responder"
"answer": "Responder",
"gamemodes": "Modos de juego",
"userinfo": "Panel de usuario",
"custom": "Personalizado",
"customgame": "Partida personalizada",
"settings": "Ajustes de la partida",
"rounds": "Rondas:",
"time": "Duración:",
"categories": "Categorías"
},
"about": {
"title": "Sobre nosotros",
"description1": "Somos el grupo WIQ_EN2B y estamos encantados de que te guste 🥝KIWIQ🥝. Disfruta!!!",
"table1": "Desarrolladores🍌🍌",
"table1": "Desarrolladores",
"table2": "Contacto"
}
}
1 change: 0 additions & 1 deletion webapp/src/components/Router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import ProtectedRoute from "./utils/ProtectedRoute";
import Logout from "pages/Logout";
import About from "pages/About";


export default createRoutesFromElements(
<Route path="/">
<Route index element={<Root />} />
Expand Down
32 changes: 32 additions & 0 deletions webapp/src/components/dashboard/CustomGameButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import PropTypes from 'prop-types';
import { Button, Box } from "@chakra-ui/react";
import { SettingsIcon } from '@chakra-ui/icons';

const SettingsButton = ({ onClick, name }) => {
return (
<Button
colorScheme="green"
variant="outline"
textAlign="center"
m="1em"
display="flex"
flexDirection="column"
alignItems="center"
size="lg"
height="4rem"
maxW={{ base: "100%", md: "calc(100% / 3 - 2em)" }}
onClick={onClick}
>
<SettingsIcon style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.5em' }} />
<Box>{name}</Box>
</Button>
);
}

SettingsButton.propTypes = {
onClick: PropTypes.func.isRequired,
name: PropTypes.string.isRequired
};

export default SettingsButton;
151 changes: 151 additions & 0 deletions webapp/src/components/dashboard/CustomGameMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import {
Box, Drawer, DrawerOverlay, DrawerContent, DrawerCloseButton,
DrawerHeader, DrawerBody, DrawerFooter, Button, Text, Flex,
NumberInput, NumberInputField, NumberInputStepper,
NumberIncrementStepper, NumberDecrementStepper
} from '@chakra-ui/react';
import { newGame, gameCategories } from 'components/game/Game';

const CustomGameMenu = ({ isOpen, onClose }) => {
const navigate = useNavigate();
const [selectedCategories, setSelectedCategories] = 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 categoriesData = await gameCategories(lang);
const formattedCategories = categoriesData.map(category => category.name);
setCategories(formattedCategories);
} catch (error) {
console.error("Error fetching game categories:", error);
}
}
fetchCategories();
}, [i18n.language]);

const manageCategory = (category) => {
if (selectedCategories.includes(category)) {
setSelectedCategories(selectedCategories.filter(item => item !== category));
} else {
setSelectedCategories([...selectedCategories, category]);
}
};

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 gamemode = 'CUSTOM';
let uppercaseCategories = selectedCategories.map(category => category.toUpperCase());
if (uppercaseCategories.length === 0)
uppercaseCategories = ["GEOGRAPHY", "SPORTS", "MUSIC", "ART", "VIDEOGAMES"];
const customGameDto = {
rounds: rounds,
categories: uppercaseCategories,
round_duration: time

}
const newGameResponse = await newGame(lang, gamemode, customGameDto);
if (newGameResponse)
navigate("/dashboard/game");
} catch (error) {
console.error("Error initializing game:", error);
}
};

return (
<Drawer isOpen={isOpen} placement="right" onClose={onClose}>
<DrawerOverlay>
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader color={"forest_green.500"}>{t("game.customgame")}</DrawerHeader>
<DrawerBody>
<Box flexDirection="column">
<Box>
<Text fontWeight='extrabold' color={"forest_green.400"}>{t("game.settings")}</Text>
<Flex direction="column">
<Text color={"forest_green.400"}>{t("game.rounds")}</Text>
<NumberInput defaultValue={rounds} min={1} max={100} onChange={valueString => setRounds(parseInt(valueString))}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Text color={"forest_green.400"}>{t("game.time")}</Text>
<NumberInput defaultValue={time} min={5} max={100} onChange={valueString => setTime(parseInt(valueString))}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Flex>
</Box>
<Box marginTop="2em">
<Text color={"forest_green.500"}>{t("game.categories")}</Text>
<Flex direction="column">
{categories.map(category => (
<Button
key={category}
className={"custom-button effect2"}
variant={selectedCategories.includes(category) ? "solid" : "outline"}
colorScheme="green"
margin={"10px"}
onClick={() => manageCategory(category)}
>
{category}
</Button>
))}
</Flex>
</Box>
</Box>
</DrawerBody>
<DrawerFooter>
<Flex justify="flex-end" align="center" w="100%">
<Button
className={"custom-button effect1"}
data-testid={"Play"}
type="submit"
colorScheme="forest_green"
margin={"10px"}
width="100%"
onClick={initializeCustomGameMode}
>
{t("common.play")}
</Button>
</Flex>
</DrawerFooter>
</DrawerContent>
</DrawerOverlay>
</Drawer>
);
};

CustomGameMenu.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
};

export default CustomGameMenu;
62 changes: 62 additions & 0 deletions webapp/src/components/dashboard/DashboardButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from "react";
import PropTypes from 'prop-types';
import { Button, Box } from "@chakra-ui/react";
import { FaKiwiBird, FaRandom, FaPalette } from "react-icons/fa";
import { TbWorld } from "react-icons/tb";
import { IoIosFootball, IoLogoGameControllerB } from "react-icons/io";

const DashboardButton = ({ label, selectedButton, onClick, iconName }) => {
const isSelected = label === selectedButton;
let icon = null;

switch (iconName) {
case "FaKiwiBird":
icon = <FaKiwiBird style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
case "IoIosFootball":
icon = <IoIosFootball style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
case "FaGlobeAmericas":
icon = <TbWorld style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
case "IoLogoGameControllerB":
icon = <IoLogoGameControllerB style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
case "FaPalette":
icon = <FaPalette style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
case "FaRandom":
icon = <FaRandom style={{ marginBottom: '0.5em', marginRight: '0.25em', fontSize: '1.8em' }} />;
break;
default:
break;
}

return (
<Button
colorScheme={"green"}
variant={isSelected ? "solid" : "ghost"}
textAlign="center"
m="1em"
display="flex"
flexDirection="column"
alignItems="center"
size="lg"
height="4rem"
maxW={{ base: "100%", md: "calc(100% / 3 - 2em)" }}
onClick={() => onClick(label)}
>
{icon}
<Box>{label}</Box>
</Button>
);
};

DashboardButton.propTypes = {
label: PropTypes.string.isRequired,
selectedButton: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
iconName: PropTypes.string.isRequired
};

export default DashboardButton;
Loading

0 comments on commit 8dffc4c

Please sign in to comment.