Skip to content

Commit

Permalink
Merge pull request #163 from Arquisoft/feat/webapp/new-menu
Browse files Browse the repository at this point in the history
New lateral menu
  • Loading branch information
jjgancfer authored Apr 4, 2024
2 parents 496fff9 + bf05c56 commit 0b47f15
Show file tree
Hide file tree
Showing 19 changed files with 582 additions and 92 deletions.
15 changes: 14 additions & 1 deletion webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
"rules": "Rules",
"dashboard": "User's Dashboard",
"goBack": "Go Back",
"finish": "Finish"
"finish": "Finish",
"english": "English",
"spanish": "Spanish",
"language": "Language:"
},
"session": {
"username": "Username",
Expand Down Expand Up @@ -68,5 +71,15 @@
"personalWrong": "{{wrong, number}} wrong answers",
"personalRate": "{{rate, number}} %"
}
},
"game": {
"round": "Round",
"next": "Next"
},
"about": {
"title": "About",
"description1": "We are the WIQ_EN2B group and we are delighted that you like 🥝KIWIQ🥝. Enjoy!!!",
"table1": "Developers🍌🍌",
"table2": "Contact"
}
}
15 changes: 14 additions & 1 deletion webapp/public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
"rules": "Reglas",
"dashboard": "Panel de Usuario",
"goBack": "Volver",
"finish": "Finalizar"
"finish": "Finalizar",
"english": "Inglés",
"spanish": "Español",
"language": "Idioma:"
},
"session": {
"username": "Nombre de usuario",
Expand Down Expand Up @@ -67,5 +70,15 @@
"personalWrong": "{{wrong, number}} respuestas incorrectas",
"personalRate": "{{rate, number}} %"
}
},
"game": {
"round": "Ronda",
"next": "Siguiente"
},
"about": {
"title": "Sobre nosotros",
"description1": "Somos el grupo WIQ_EN2B y estamos encantados de que te guste 🥝KIWIQ🥝. Disfruta!!!",
"table1": "Desarrolladores🍌🍌",
"table2": "Contacto"
}
}
123 changes: 123 additions & 0 deletions webapp/src/components/LateralMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Box, Drawer, DrawerOverlay, DrawerContent, DrawerCloseButton, DrawerHeader, DrawerBody, DrawerFooter, Select, Button, Text, IconButton, Flex, Image } from '@chakra-ui/react';
import { FaChartBar, FaBook, FaTachometerAlt } from 'react-icons/fa';
import { InfoIcon, SettingsIcon } from '@chakra-ui/icons';

import AuthManager from "components/auth/AuthManager";

const LateralMenu = ({ isOpen, onClose, changeLanguage, currentLanguage, isDashboard }) => {
const navigate = useNavigate();
const [selectedLanguage, setSelectedLanguage] = useState(currentLanguage);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const { t } = useTranslation();

useEffect(() => {
setSelectedLanguage(currentLanguage);
checkIsLoggedIn();
}, [currentLanguage]);

const handleChangeLanguage = (e) => {
const selectedLanguage = e.target.value;
changeLanguage(selectedLanguage);
};

const handleApiClick = () => {
window.open("http://localhost:8080/swagger/swagger-ui/index.html#/auth-controller/registerUser", "_blank", "noopener");
};

const handleLogout = async () => {
try {
await new AuthManager().logout();
navigate("/");
} catch (error) {
console.error("Error al cerrar sesión:", error);
}
};

const checkIsLoggedIn = async () => {
try {
const loggedIn = await new AuthManager().isLoggedIn();
setIsLoggedIn(loggedIn);
} catch (error) {
console.error("Error al verificar el estado de inicio de sesión:", error);
}
};

return (
<Drawer isOpen={isOpen} placement="left" onClose={onClose}>
<DrawerOverlay>
<DrawerContent>
<DrawerCloseButton />
<Flex align="center">
<Image src="/kiwiq-icon.ico" alt="App icon" width="80px" height="80px"/>
<DrawerHeader color={"forest_green.500"}>KIWIQ</DrawerHeader>
</Flex>
<DrawerBody>
<Box flexDirection="column">
<Box margin={"10px"}>
<Text color={"forest_green.500"}>{t("common.language")}</Text>
<Select data-testid="language-select" onChange={handleChangeLanguage} value={selectedLanguage}>
<option value="es">{t("common.spanish")}</option>
<option value="en">{t("common.english")}</option>
</Select>
</Box>
<Box margin={"10px"} flexDirection="row">
{isLoggedIn && (
<>
{!isDashboard && (
<Box marginTop={"40px"}>
<Button data-testid="dashboard" type="submit" variant="link" colorScheme={"forest_green"} onClick={() => {navigate("/dashboard")}}>
<FaTachometerAlt />
<span style={{ marginLeft: '6px' }}>{t("common.dashboard")}</span>
</Button>
</Box>
)}
<Box marginTop={"40px"}>
<Button data-testid="statistics" type="submit" variant="link" colorScheme={"forest_green"} onClick={() => {navigate("/dashboard/statistics")}}>
<FaChartBar />
<span style={{ marginLeft: '6px' }}>{t("common.statistics.title")}</span>
</Button>
</Box>
<Box marginTop={"40px"}>
<Button data-testid="rules" type="submit" variant="link" colorScheme={"forest_green"} onClick={() => {navigate("/dashboard/rules")}}>
<FaBook />
<span style={{ marginLeft: '6px' }}>{t("common.rules")}</span>
</Button>
</Box>
<Box marginTop={"40px"}>
<Button data-testid="API" type="submit" variant="link" colorScheme={"forest_green"} onClick={handleApiClick}>
<SettingsIcon />
<span style={{ marginLeft: '6px' }}>API</span>
</Button>
</Box>
</>
)}
</Box>
</Box>
</DrawerBody>
<DrawerFooter>
<Flex justify="flex-end" align="center" w="100%">
{isLoggedIn && (
<Button data-testid={"LogOut"} type="submit" colorScheme="raw_umber" margin={"10px"} className={"custom-button effect1"} onClick={handleLogout} width="70%">{t("common.logout")}</Button>
)}
<IconButton type="submit" aria-label='About' colorScheme={"forest_green"} icon={<InfoIcon />} className={"custom-button effect1"} onClick={() => {navigate("/about");}} margin={"10px"}></IconButton>
</Flex>
</DrawerFooter>
</DrawerContent>
</DrawerOverlay>
</Drawer>
);
};

LateralMenu.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
changeLanguage: PropTypes.func.isRequired,
currentLanguage: PropTypes.string.isRequired,
isDashboard: PropTypes.bool.isRequired
};

export default LateralMenu;
44 changes: 44 additions & 0 deletions webapp/src/components/MenuButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState, useEffect } from "react";
import PropTypes from 'prop-types';
import { FaBars } from "react-icons/fa";
import { chakra, Box, IconButton } from "@chakra-ui/react";

const MenuButton = ({ onClick }) => {
const [isFixed, setIsFixed] = useState(false);

useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 0) {
setIsFixed(true);
} else {
setIsFixed(false);
}
};

window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);

return (
<Box position={isFixed ? "fixed" : "absolute"} top="1rem" left="1rem">
<IconButton
bg="pigment_green.600"
color="whiteAlpha.900"
size="lg"
borderRadius="md"
aria-label="Open Menu"
_hover={{ bg: 'pigment_green.400' }}
icon={<chakra.span as={FaBars} fontSize="1.5em" />}
onClick={onClick}
/>
</Box>
);
}

MenuButton.propTypes = {
onClick: PropTypes.func.isRequired
};

export default MenuButton;
2 changes: 2 additions & 0 deletions webapp/src/components/Router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import Results from "../pages/Results";
import Statistics from "pages/Statistics";
import ProtectedRoute from "./utils/ProtectedRoute";
import Logout from "pages/Logout";
import About from "pages/About";


export default createRoutesFromElements(
<Route path="/">
<Route index element={<Root />} />
<Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login />}/>
<Route path="/about" element={<About />} />
<Route path="/" element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />}/>
<Route path="/dashboard/rules" element={<Rules />}/>
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export default i18n.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
backend: {
loadPath: '/locales/{{lng}}/translation.json'
},
fallbackLng: "en",
debug: false
})
74 changes: 74 additions & 0 deletions webapp/src/pages/About.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useState } from "react";
import { useTranslation } from 'react-i18next';
import { Center, Heading, Stack, Box, Text, Table, Thead, Tr, Td, Th, Tbody, Container } from '@chakra-ui/react';
import { InfoIcon } from '@chakra-ui/icons';

import LateralMenu from '../components/LateralMenu';
import MenuButton from '../components/MenuButton';
import GoBack from "components/GoBack";

export default function About() {
const { t, i18n } = useTranslation();
const currentLanguage = i18n.language;
const [isMenuOpen, setIsMenuOpen] = useState(false);

const changeLanguage = (selectedLanguage) => {
i18n.changeLanguage(selectedLanguage);
};

return (
<Center bgImage="/background.svg">
<MenuButton data-testid="menu-button" onClick={() => setIsMenuOpen(true)} />
<LateralMenu isOpen={isMenuOpen} onClose={() => setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
<Container maxW="lg">
<Box textAlign="center">
<InfoIcon boxSize={10} color="pigment_green.500" />
<Heading as="h2">{t('about.title')}</Heading>
</Box>
<Stack spacing={4} p="1rem" backgroundColor="whiteAlpha.900" boxShadow="md" rounded="1rem">
<Text>{t("about.description1")}</Text>
<br></br>
<Table variant="simple">
<Thead>
<Tr>
<Th><Text fontWeight='extrabold' color={"forest_green.400"} textAlign={"center"} fontSize={"md"}>{t("about.table1")}</Text></Th>
<Th><Text fontWeight='extrabold' color={"forest_green.400"} textAlign={"center"} fontSize={"md"}>{t("about.table2")}</Text></Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Gonzalo Alonso Fernández</Td>
<Td>UO282104</Td>
</Tr>
<Tr>
<Td>Sergio Rodríguez García</Td>
<Td>UO282598</Td>
</Tr>
<Tr>
<Td>Jorge Joaquín Gancedo Fernández</Td>
<Td>UO282161</Td>
</Tr>
<Tr>
<Td>Darío Gutiérrez Mori</Td>
<Td>UO282435</Td>
</Tr>
<Tr>
<Td>Sergio Quintana Fernández</Td>
<Td>UO288090</Td>
</Tr>
<Tr>
<Td>Diego Villanueva Berros</Td>
<Td>UO283615</Td>
</Tr>
<Tr>
<Td>Gonzalo Suárez Losada</Td>
<Td>UO283928</Td>
</Tr>
</Tbody>
</Table>
<GoBack/>
</Stack>
</Container>
</Center>
);
}
37 changes: 21 additions & 16 deletions webapp/src/pages/Dashboard.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React from "react";
import { Grid, Flex, Heading, Button, Box } from "@chakra-ui/react";
import React, { useState } from "react";
import { Heading, Button, Box, Stack } from "@chakra-ui/react";
import { Center } from "@chakra-ui/layout";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import ButtonEf from '../components/ButtonEf';
import { FaTachometerAlt } from 'react-icons/fa';

import AuthManager from "components/auth/AuthManager";
import LateralMenu from '../components/LateralMenu';
import MenuButton from '../components/MenuButton';

export default function Dashboard() {
const navigate = useNavigate();
const { t } = useTranslation();
const { t, i18n } = useTranslation();

const handleLogout = async () => {
try {
Expand All @@ -19,22 +22,24 @@ export default function Dashboard() {
}
};

const [isMenuOpen, setIsMenuOpen] = useState(false);
const currentLanguage = i18n.language;
const changeLanguage = (selectedLanguage) => {
i18n.changeLanguage(selectedLanguage);
};

return (
<Center display="flex" flexDirection="column" w="100wh" h="100vh" justifyContent="center" alignItems="center" bgImage={'/background.svg'}>
<MenuButton onClick={() => setIsMenuOpen(true)} />
<LateralMenu isOpen={isMenuOpen} onClose={() => setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={true}/>
<FaTachometerAlt style={{ fontSize: '2.5rem', color: 'green' }} />
<Heading as="h2">{t("common.dashboard")}</Heading>

<Box bg="white" p={4} borderRadius="md" boxShadow="md" mt={4} mb={4} w="fit-content" shadow="2xl" rounded="1rem">
<Grid templateColumns="repeat(3, 1fr)" gap={4}>
<ButtonEf dataTestId={"Rules"} variant={"outline"} colorScheme={"green"} text={t("common.rules")} onClick={() => navigate("/dashboard/rules")}/>
<ButtonEf dataTestId={"Play"} variant={"solid"} colorScheme={"forest_green"} text={t("common.play")} onClick={() => navigate("/dashboard/game")}/>
<ButtonEf dataTestId={"Statistics"} variant={"outline"} colorScheme={"green"} text={t("common.statistics.title")} onClick={() => navigate("/dashboard/statistics")}/>
</Grid>

<Flex direction="row" justifyContent="center" alignItems="center">
<Button type="submit" colorScheme="red" margin={"10px"} className={"custom-button effect1"} onClick={handleLogout} w="100%">
{t("common.logout")}
</Button>
</Flex>
<Box minW={{ md: "400px" }} shadow="2xl">
<Stack spacing={4} p="1rem" backgroundColor="whiteAlpha.900" boxShadow="md" rounded="1rem">
<Button type="submit" data-testid={"Play"} variant={"solid"} colorScheme={"pigment_green"} margin={"5px"} size="lg" className={"custom-button effect1"} onClick={() => navigate("/dashboard/game")}>{t("common.play")}</Button>
<Button type="submit" colorScheme="raw_umber" margin={"5px"} className={"custom-button effect1"} onClick={handleLogout}>{t("common.logout")}</Button>
</Stack>
</Box>
</Center>
);
Expand Down
Loading

0 comments on commit 0b47f15

Please sign in to comment.