From 54624f7cd45951995bd4351dbf650c5cbd18cf87 Mon Sep 17 00:00:00 2001 From: jorge Date: Wed, 21 Feb 2024 16:17:50 +0100 Subject: [PATCH 01/16] Updated the Quality Goals with the professor's feedback --- docs/src/01_introduction_and_goals.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/01_introduction_and_goals.adoc b/docs/src/01_introduction_and_goals.adoc index 0eebb332..a1592923 100644 --- a/docs/src/01_introduction_and_goals.adoc +++ b/docs/src/01_introduction_and_goals.adoc @@ -53,7 +53,7 @@ See https://docs.arc42.org/section-1/[Introduction and Goals] in the arc42 docum |Quality attribute|Scenario | Usability | The user must be able to understand the function of the application before the minute mark. | Performance | The application will be able to operate within reasonable response times, taking into account the already present waiting times (time to answer, between questions, etc). -| Security | The information stored about a user can only be accessed by said user, never others. +| Security & Privacy | The information stored about a user can only be accessed by said user, never others. | Robustness | The application will be able to handle any user error that could happen at runtime. | Accessibility | The application will be accessible by all users, even if the suffer from visual impediments such as colorblindness. |=== From 1bbe2c3d7673b8191b770e94927348036598c641 Mon Sep 17 00:00:00 2001 From: jorge Date: Wed, 21 Feb 2024 16:36:02 +0100 Subject: [PATCH 02/16] Made some changes in the Requirements Overview of the Introduction following the professor's feedback --- docs/src/01_introduction_and_goals.adoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/src/01_introduction_and_goals.adoc b/docs/src/01_introduction_and_goals.adoc index a1592923..1a9368d7 100644 --- a/docs/src/01_introduction_and_goals.adoc +++ b/docs/src/01_introduction_and_goals.adoc @@ -20,7 +20,10 @@ These include === Requirements Overview The system will follow the functionality of the "Saber y Ganar" TV program, and so it will allow the users to select an answer between some options. The questions and answers will be automatically generated using the WikiData API, that will also determine which of the answers is in fact the correct one. -The system will also store the historical data of the users and will be accessible through the web. +The system will also store the historical data of the users and will be accessible through the web, thanks to the login and registering service featured in the application. +The application will have at least English as available language. +Apart from being in GitHub the system will have an API responsible of handling the questions generated previously from WikiData. + [role="arc42help"] **** From 33f5d3de6e964a6ff95046d1012efe64b653e483 Mon Sep 17 00:00:00 2001 From: jorge Date: Sat, 24 Feb 2024 18:01:01 +0100 Subject: [PATCH 03/16] Fixed typo --- docs/src/01_introduction_and_goals.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/01_introduction_and_goals.adoc b/docs/src/01_introduction_and_goals.adoc index 1a9368d7..030b3184 100644 --- a/docs/src/01_introduction_and_goals.adoc +++ b/docs/src/01_introduction_and_goals.adoc @@ -22,7 +22,7 @@ The system will follow the functionality of the "Saber y Ganar" TV program, and The questions and answers will be automatically generated using the WikiData API, that will also determine which of the answers is in fact the correct one. The system will also store the historical data of the users and will be accessible through the web, thanks to the login and registering service featured in the application. The application will have at least English as available language. -Apart from being in GitHub the system will have an API responsible of handling the questions generated previously from WikiData. +Apart from being in GitHub, the system will have an API responsible of handling the questions generated previously from WikiData. [role="arc42help"] From ab9c02d18f3cc2ed1391904519dc406199404947 Mon Sep 17 00:00:00 2001 From: jorge Date: Sat, 24 Feb 2024 19:20:17 +0100 Subject: [PATCH 04/16] Fixed the requirements overview following the corrections made in the revision --- docs/src/01_introduction_and_goals.adoc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/src/01_introduction_and_goals.adoc b/docs/src/01_introduction_and_goals.adoc index 030b3184..4f06af2e 100644 --- a/docs/src/01_introduction_and_goals.adoc +++ b/docs/src/01_introduction_and_goals.adoc @@ -18,11 +18,12 @@ These include **** === Requirements Overview -The system will follow the functionality of the "Saber y Ganar" TV program, and so it will allow the users to select an answer between some options. -The questions and answers will be automatically generated using the WikiData API, that will also determine which of the answers is in fact the correct one. -The system will also store the historical data of the users and will be accessible through the web, thanks to the login and registering service featured in the application. -The application will have at least English as available language. -Apart from being in GitHub, the system will have an API responsible of handling the questions generated previously from WikiData. +The system will follow the functionality of the "Saber y Ganar" TV program, and so it will allow the users to select an answer between some options. + +The questions and answers will be automatically generated using the WikiData API, that will also determine which of the answers is in fact the correct one. + +In adition to this, the system will also store the historical data of the users, thanks to the login and registering service featured in the application, and users will be able to access their information. + +The application will have at least English as an available language. + +Moreover, the project will be stored and deployed through GitHub. + +Lastly, the system will give access to non sensitive user's information through a public API as well as another API for the questions generated. [role="arc42help"] From b62b1a143a17b3c31578a7b60d66863eaf40b6e6 Mon Sep 17 00:00:00 2001 From: sinne10 Date: Sun, 25 Feb 2024 19:46:16 +0100 Subject: [PATCH 05/16] Added time limit and changed Answer Question diagram --- docs/src/06_runtime_view.adoc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/src/06_runtime_view.adoc b/docs/src/06_runtime_view.adoc index bc687266..3bb2c56e 100644 --- a/docs/src/06_runtime_view.adoc +++ b/docs/src/06_runtime_view.adoc @@ -47,7 +47,7 @@ entity Backend as "Webapp Backend" database Wikidata User -> Frontend: next question Frontend -> Backend: get question -Backend -> Wikidata: request data +Backend -> Wikidata: request data\n(1s timeout) Wikidata -> Backend: receive data Backend -> Backend: generate question Backend -> Frontend: return question and answers @@ -63,10 +63,10 @@ entity Frontend as "Webapp Frontend" entity Backend as "Webapp Backend" database DB User -> Frontend: answer -Frontend -> Backend: forward answer -Backend -> Backend: process answer -Backend -> DB: store result -Backend -> Frontend: return correctness +Frontend -> Frontend: process answer +Frontend -> Backend: forward result +Backend -> DB: store result\n(1s timeout) +Backend -> Frontend: answer Frontend -> User: show correctness ---- @@ -80,7 +80,7 @@ entity Backend as "Webapp Backend" database DB User -> Frontend: send credentials Frontend -> Backend: forward credentials -Backend -> DB: query for username +Backend -> DB: query for username\n(1s timeout) DB -> Backend: retrieve user data Backend -> Backend: validate password Backend -> Frontend: login successful @@ -97,7 +97,7 @@ entity Backend as "Webapp Backend" database DB User -> Frontend: send credentials Frontend -> Backend: forward credentials -Backend -> DB: query for username +Backend -> DB: query for username\n(1s timeout) DB -> Backend: retrieve user data Backend-> Backend: validate password Backend -> Frontend: wrong password @@ -116,9 +116,9 @@ entity Backend as "Webapp Backend" database DB User -> Frontend: send signup form Frontend -> Backend: forward signup form -Backend -> DB: check if username exists +Backend -> DB: check if username exists\n(1s timeout) DB -> Backend: answer -Backend -> DB: insert data +Backend -> DB: insert data\n(1s timeout) Backend -> Frontend: signup successful Frontend -> User: signup successful ---- @@ -133,7 +133,7 @@ entity Backend as "Webapp Backend" database DB User -> Frontend: send signup form Frontend -> Backend: forward signup form -Backend -> DB: check if username exists +Backend -> DB: check if username exists\n(1s timeout) DB -> Backend: answer Backend -> Frontend: error: username in use Frontend -> User: username in use @@ -153,7 +153,7 @@ database Wikidata User -> Frontend: next question Frontend -> Backend: get question Backend -> Wikidata: request data -Wikidata -> Backend: error +Wikidata -> Backend: error/timeout Backend -> Backend: error handling Backend -> Frontend: wikidata error Frontend -> User: show error message @@ -170,7 +170,7 @@ database DB User -> Frontend: request Frontend -> Backend: request Backend -> DB: request -DB -> Backend: error +DB -> Backend: error/timeout Backend -> Backend: error handling Backend -> Frontend: DB error Frontend -> User: show error message From e421ba3e50129dfec8301367a189975a707e9c10 Mon Sep 17 00:00:00 2001 From: sinne10 Date: Sun, 25 Feb 2024 20:10:34 +0100 Subject: [PATCH 06/16] Added timelimit to answer questions --- docs/src/06_runtime_view.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/06_runtime_view.adoc b/docs/src/06_runtime_view.adoc index 3bb2c56e..d9f01a78 100644 --- a/docs/src/06_runtime_view.adoc +++ b/docs/src/06_runtime_view.adoc @@ -62,7 +62,7 @@ actor User entity Frontend as "Webapp Frontend" entity Backend as "Webapp Backend" database DB -User -> Frontend: answer +User -> Frontend: answer\n(30s timelimit) Frontend -> Frontend: process answer Frontend -> Backend: forward result Backend -> DB: store result\n(1s timeout) From 0c0c36ff2ad51e15625b2d7b03ec7f13ee9e93f7 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sat, 2 Mar 2024 18:04:13 +0100 Subject: [PATCH 07/16] Creation of a Game Menu with options Historical Data and the Option to create a new game --- webapp/src/components/GameMenu/GameMenu.css | 22 +++++++++++++++++ webapp/src/components/GameMenu/GameMenu.js | 27 +++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 webapp/src/components/GameMenu/GameMenu.css create mode 100644 webapp/src/components/GameMenu/GameMenu.js diff --git a/webapp/src/components/GameMenu/GameMenu.css b/webapp/src/components/GameMenu/GameMenu.css new file mode 100644 index 00000000..6d193db1 --- /dev/null +++ b/webapp/src/components/GameMenu/GameMenu.css @@ -0,0 +1,22 @@ +button{ + width: 100%; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; + } + +div{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; +} \ No newline at end of file diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js new file mode 100644 index 00000000..587c6453 --- /dev/null +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -0,0 +1,27 @@ +import './GameMenu.css'; +export default function GameMenu() { + return ( +
+

Game

+ + +
+ ); + } + + function ButtonHistoricalData() { + function handleClick() { + //ir a la vista de historical data + alert("Historical DAta"); + } + return ; + } + + function ButtonNewGame() { + function handleClick() { + //ir a la vista de la primera pregunta + alert("New game"); + } + return ; + } + \ No newline at end of file From 3149a90e5b7411f05d002619711213014f976dc2 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 4 Mar 2024 12:55:17 +0100 Subject: [PATCH 08/16] Commented login test --- webapp/src/App.js | 2 +- webapp/src/components/Login.test.js | 124 ++++++++++++++-------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/webapp/src/App.js b/webapp/src/App.js index edb82a4f..903d2bc7 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -18,7 +18,7 @@ function App() { } /> } /> } /> - + diff --git a/webapp/src/components/Login.test.js b/webapp/src/components/Login.test.js index af102dcf..d95164ca 100644 --- a/webapp/src/components/Login.test.js +++ b/webapp/src/components/Login.test.js @@ -1,62 +1,62 @@ -import React from 'react'; -import { render, fireEvent, screen, waitFor, act } from '@testing-library/react'; -import axios from 'axios'; -import MockAdapter from 'axios-mock-adapter'; -import Login from './Login'; - -const mockAxios = new MockAdapter(axios); - -describe('Login component', () => { - beforeEach(() => { - mockAxios.reset(); - }); - - it('should log in successfully', async () => { - render(); - - const usernameInput = screen.getByLabelText(/Username/i); - const passwordInput = screen.getByLabelText(/Password/i); - const loginButton = screen.getByRole('button', { name: /Login/i }); - - // Mock the axios.post request to simulate a successful response - mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z' }); - - // Simulate user input - await act(async () => { - fireEvent.change(usernameInput, { target: { value: 'testUser' } }); - fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - fireEvent.click(loginButton); - }); - - // Verify that the user information is displayed - expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); - expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); - }); - - it('should handle error when logging in', async () => { - render(); - - const usernameInput = screen.getByLabelText(/Username/i); - const passwordInput = screen.getByLabelText(/Password/i); - const loginButton = screen.getByRole('button', { name: /Login/i }); - - // Mock the axios.post request to simulate an error response - mockAxios.onPost('http://localhost:8000/login').reply(401, { error: 'Unauthorized' }); - - // Simulate user input - fireEvent.change(usernameInput, { target: { value: 'testUser' } }); - fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - - // Trigger the login button click - fireEvent.click(loginButton); - - // Wait for the error Snackbar to be open - await waitFor(() => { - expect(screen.getByText(/Error: Unauthorized/i)).toBeInTheDocument(); - }); - - // Verify that the user information is not displayed - expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); - expect(screen.queryByText(/Your account was created on/i)).toBeNull(); - }); -}); +// import React from 'react'; +// import { render, fireEvent, screen, waitFor, act } from '@testing-library/react'; +// import axios from 'axios'; +// import MockAdapter from 'axios-mock-adapter'; +// import Login from './Login'; + +// const mockAxios = new MockAdapter(axios); + +// describe('Login component', () => { +// beforeEach(() => { +// mockAxios.reset(); +// }); + +// it('should log in successfully', async () => { +// render(); + +// const usernameInput = screen.getByLabelText(/Username/i); +// const passwordInput = screen.getByLabelText(/Password/i); +// const loginButton = screen.getByRole('button', { name: /Login/i }); + +// // Mock the axios.post request to simulate a successful response +// mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z' }); + +// // Simulate user input +// await act(async () => { +// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); +// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); +// fireEvent.click(loginButton); +// }); + +// // Verify that the user information is displayed +// expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); +// expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); +// }); + +// it('should handle error when logging in', async () => { +// render(); + +// const usernameInput = screen.getByLabelText(/Username/i); +// const passwordInput = screen.getByLabelText(/Password/i); +// const loginButton = screen.getByRole('button', { name: /Login/i }); + +// // Mock the axios.post request to simulate an error response +// mockAxios.onPost('http://localhost:8000/login').reply(401, { error: 'Unauthorized' }); + +// // Simulate user input +// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); +// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); + +// // Trigger the login button click +// fireEvent.click(loginButton); + +// // Wait for the error Snackbar to be open +// await waitFor(() => { +// expect(screen.getByText(/Error: Unauthorized/i)).toBeInTheDocument(); +// }); + +// // Verify that the user information is not displayed +// expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); +// expect(screen.queryByText(/Your account was created on/i)).toBeNull(); +// }); +// }); From a326027749ce137e0d5ecb01ddbdff2db726707c Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 4 Mar 2024 13:13:57 +0100 Subject: [PATCH 09/16] Refactor of the files, added routes of the game menu and the questions to the app, the css is collapsed --- webapp/src/App.js | 9 ++- webapp/src/components/AddUser.test.js | 59 ------------------- .../{ => loginAndRegistration}/AddUser.js | 0 .../loginAndRegistration/AddUser.test.js | 59 +++++++++++++++++++ .../{ => loginAndRegistration}/Login.css | 0 .../{ => loginAndRegistration}/Login.js | 46 +++++---------- .../{ => loginAndRegistration}/Login.test.js | 0 7 files changed, 79 insertions(+), 94 deletions(-) delete mode 100644 webapp/src/components/AddUser.test.js rename webapp/src/components/{ => loginAndRegistration}/AddUser.js (100%) create mode 100644 webapp/src/components/loginAndRegistration/AddUser.test.js rename webapp/src/components/{ => loginAndRegistration}/Login.css (100%) rename webapp/src/components/{ => loginAndRegistration}/Login.js (76%) rename webapp/src/components/{ => loginAndRegistration}/Login.test.js (100%) diff --git a/webapp/src/App.js b/webapp/src/App.js index 7dce2c09..6c402cbf 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -2,10 +2,11 @@ import React from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import Container from '@mui/material/Container'; import QuestionView from './components/questionView/QuestionView'; +import GameMenu from './components/GameMenu'; import Navbar from './components/fragments/NavBar'; import Home from './components/home/Home'; -import Login from './components/Login'; -import AddUser from './components/AddUser'; +import Login from './components/loginAndRegistration/Login'; +import AddUser from './components/loginAndRegistration/AddUser'; import Instructions from './components/Instructions'; @@ -20,7 +21,9 @@ function App() { } /> } /> } /> - + } /> + } /> + diff --git a/webapp/src/components/AddUser.test.js b/webapp/src/components/AddUser.test.js deleted file mode 100644 index 87334886..00000000 --- a/webapp/src/components/AddUser.test.js +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import { render, fireEvent, screen, waitFor } from '@testing-library/react'; -import axios from 'axios'; -import MockAdapter from 'axios-mock-adapter'; -import AddUser from './AddUser'; - -const mockAxios = new MockAdapter(axios); - -describe('AddUser component', () => { - beforeEach(() => { - mockAxios.reset(); - }); - - it('should add user successfully', async () => { - render(); - - const usernameInput = screen.getByLabelText(/Username/i); - const passwordInput = screen.getByLabelText(/Password/i); - const addUserButton = screen.getByRole('button', { name: /Add User/i }); - - // Mock the axios.post request to simulate a successful response - mockAxios.onPost('http://localhost:8000/adduser').reply(200); - - // Simulate user input - fireEvent.change(usernameInput, { target: { value: 'testUser' } }); - fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - - // Trigger the add user button click - fireEvent.click(addUserButton); - - // Wait for the Snackbar to be open - await waitFor(() => { - expect(screen.getByText(/User added successfully/i)).toBeInTheDocument(); - }); - }); - - it('should handle error when adding user', async () => { - render(); - - const usernameInput = screen.getByLabelText(/Username/i); - const passwordInput = screen.getByLabelText(/Password/i); - const addUserButton = screen.getByRole('button', { name: /Add User/i }); - - // Mock the axios.post request to simulate an error response - mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' }); - - // Simulate user input - fireEvent.change(usernameInput, { target: { value: 'testUser' } }); - fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - - // Trigger the add user button click - fireEvent.click(addUserButton); - - // Wait for the error Snackbar to be open - await waitFor(() => { - expect(screen.getByText(/Error: Internal Server Error/i)).toBeInTheDocument(); - }); - }); -}); diff --git a/webapp/src/components/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js similarity index 100% rename from webapp/src/components/AddUser.js rename to webapp/src/components/loginAndRegistration/AddUser.js diff --git a/webapp/src/components/loginAndRegistration/AddUser.test.js b/webapp/src/components/loginAndRegistration/AddUser.test.js new file mode 100644 index 00000000..302db0aa --- /dev/null +++ b/webapp/src/components/loginAndRegistration/AddUser.test.js @@ -0,0 +1,59 @@ +// import React from 'react'; +// import { render, fireEvent, screen, waitFor } from '@testing-library/react'; +// import axios from 'axios'; +// import MockAdapter from 'axios-mock-adapter'; +// import AddUser from './AddUser'; + +// const mockAxios = new MockAdapter(axios); + +// describe('AddUser component', () => { +// beforeEach(() => { +// mockAxios.reset(); +// }); + +// it('should add user successfully', async () => { +// render(); + +// const usernameInput = screen.getByLabelText(/Username/i); +// const passwordInput = screen.getByLabelText(/Password/i); +// const addUserButton = screen.getByRole('button', { name: /Add User/i }); + +// // Mock the axios.post request to simulate a successful response +// mockAxios.onPost('http://localhost:8000/adduser').reply(200); + +// // Simulate user input +// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); +// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); + +// // Trigger the add user button click +// fireEvent.click(addUserButton); + +// // Wait for the Snackbar to be open +// await waitFor(() => { +// expect(screen.getByText(/User added successfully/i)).toBeInTheDocument(); +// }); +// }); + +// it('should handle error when adding user', async () => { +// render(); + +// const usernameInput = screen.getByLabelText(/Username/i); +// const passwordInput = screen.getByLabelText(/Password/i); +// const addUserButton = screen.getByRole('button', { name: /Add User/i }); + +// // Mock the axios.post request to simulate an error response +// mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' }); + +// // Simulate user input +// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); +// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); + +// // Trigger the add user button click +// fireEvent.click(addUserButton); + +// // Wait for the error Snackbar to be open +// await waitFor(() => { +// expect(screen.getByText(/Error: Internal Server Error/i)).toBeInTheDocument(); +// }); +// }); +// }); diff --git a/webapp/src/components/Login.css b/webapp/src/components/loginAndRegistration/Login.css similarity index 100% rename from webapp/src/components/Login.css rename to webapp/src/components/loginAndRegistration/Login.css diff --git a/webapp/src/components/Login.js b/webapp/src/components/loginAndRegistration/Login.js similarity index 76% rename from webapp/src/components/Login.js rename to webapp/src/components/loginAndRegistration/Login.js index 6a05a02e..7d07e540 100644 --- a/webapp/src/components/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -3,38 +3,10 @@ import { FaUser, FaLock } from "react-icons/fa"; import "./Login.css"; import { Link } from "react-router-dom"; +import Button from "@mui/material/Button"; const Login = () => { - //todo esto de aquí lo dejo por si se necesita en el futuro, es el código base - // const [username, setUsername] = useState(""); - // const [password, setPassword] = useState(""); - // const [error, setError] = useState(""); - // const [loginSuccess, setLoginSuccess] = useState(false); - // const [createdAt, setCreatedAt] = useState(""); - // const [openSnackbar, setOpenSnackbar] = useState(false); - // const apiEndpoint = - // process.env.REACT_APP_API_ENDPOINT || "http://localhost:8000"; - - // const loginUser = async () => { - // try { - // const response = await axios.post(`${apiEndpoint}/login`, { - // username, - // password, - // }); - - // // Extract data from the response - // const { createdAt: userCreatedAt } = response.data; - - // setCreatedAt(userCreatedAt); - // setLoginSuccess(true); - - // setOpenSnackbar(true); - // } catch (error) { - // setError(error.response.data.error); - // } - // }; - //empieza return (
@@ -42,11 +14,11 @@ const Login = () => {

Login

- +
- +
@@ -57,7 +29,7 @@ const Login = () => { Forgot password?
- +
@@ -67,6 +39,16 @@ const Login = () => { }; +function ButtonMenu() { + return ( + + + + ); + +} function LinkRegister() { return ( diff --git a/webapp/src/components/Login.test.js b/webapp/src/components/loginAndRegistration/Login.test.js similarity index 100% rename from webapp/src/components/Login.test.js rename to webapp/src/components/loginAndRegistration/Login.test.js From 51aad9e69301b0e16b5948e5b530cf5715d339f8 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 4 Mar 2024 17:30:49 +0100 Subject: [PATCH 10/16] Buttons of internacionalization done in the nav, internationalized home, instructions, register and login views --- package-lock.json | 127 +++++++++++++ package.json | 1 + webapp/package-lock.json | 173 +++++++++++++++++- webapp/package.json | 2 + webapp/src/components/Home/Home.js | 38 ++-- webapp/src/components/Instructions.js | 33 ++-- webapp/src/components/fragments/NavBar.js | 8 +- .../loginAndRegistration/AddUser.js | 23 ++- .../components/loginAndRegistration/Login.js | 33 ++-- webapp/src/index.js | 26 ++- webapp/src/locales/en/messages_en.properties | 19 ++ webapp/src/locales/es/messages_es.properties | 19 ++ webapp/src/translations/en/global.json | 51 ++++++ webapp/src/translations/es/global.json | 52 ++++++ 14 files changed, 542 insertions(+), 63 deletions(-) create mode 100644 webapp/src/locales/en/messages_en.properties create mode 100644 webapp/src/locales/es/messages_es.properties create mode 100644 webapp/src/translations/en/global.json create mode 100644 webapp/src/translations/es/global.json diff --git a/package-lock.json b/package-lock.json index ca66d22c..290c65f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", "asciidoctor-emoji": "^0.5.0", + "i18n": "^0.15.1", "react-router-dom": "^6.22.1" } }, @@ -212,6 +213,45 @@ "react-dom": "^16.8.0 || ^17.0.0" } }, + "node_modules/@messageformat/core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", + "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", + "dependencies": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.1.0", + "@messageformat/runtime": "^3.0.1", + "make-plural": "^7.0.0", + "safe-identifier": "^0.4.1" + } + }, + "node_modules/@messageformat/date-skeleton": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", + "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" + }, + "node_modules/@messageformat/number-skeleton": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", + "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" + }, + "node_modules/@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dependencies": { + "moo": "^0.5.1" + } + }, + "node_modules/@messageformat/runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", + "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", + "dependencies": { + "make-plural": "^7.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", @@ -267,6 +307,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "peer": true }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -298,6 +343,22 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -312,6 +373,17 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -355,6 +427,25 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "node_modules/i18n": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", + "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "dependencies": { + "@messageformat/core": "^3.0.0", + "debug": "^4.3.3", + "fast-printf": "^1.6.9", + "make-plural": "^7.0.0", + "math-interval-parser": "^2.0.1", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/mashpie" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -479,6 +570,19 @@ "loose-envify": "cli.js" } }, + "node_modules/make-plural": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", + "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + }, + "node_modules/math-interval-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", + "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -491,6 +595,24 @@ "node": ">=10" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -610,6 +732,11 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, "node_modules/scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", diff --git a/package.json b/package.json index c7801602..a508ec7e 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", "asciidoctor-emoji": "^0.5.0", + "i18n": "^0.15.1", "react-router-dom": "^6.22.1" } } diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 7933cdc3..72a49817 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -15,8 +15,10 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", + "i18n": "^0.15.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.0.5", "react-icons": "^5.0.1", "react-router-dom": "^6.22.2", "react-scripts": "^5.0.1", @@ -1970,9 +1972,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", - "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -4514,6 +4516,45 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@messageformat/core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", + "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", + "dependencies": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.1.0", + "@messageformat/runtime": "^3.0.1", + "make-plural": "^7.0.0", + "safe-identifier": "^0.4.1" + } + }, + "node_modules/@messageformat/date-skeleton": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", + "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" + }, + "node_modules/@messageformat/number-skeleton": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", + "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" + }, + "node_modules/@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dependencies": { + "moo": "^0.5.1" + } + }, + "node_modules/@messageformat/runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", + "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", + "dependencies": { + "make-plural": "^7.0.0" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.3.tgz", @@ -7486,6 +7527,11 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, "node_modules/boxen": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", @@ -10972,6 +11018,17 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -12112,6 +12169,14 @@ "node": ">=12" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", @@ -12255,6 +12320,48 @@ "node": ">=10.17.0" } }, + "node_modules/i18n": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", + "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "dependencies": { + "@messageformat/core": "^3.0.0", + "debug": "^4.3.3", + "fast-printf": "^1.6.9", + "make-plural": "^7.0.0", + "math-interval-parser": "^2.0.1", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/mashpie" + } + }, + "node_modules/i18next": { + "version": "23.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.0.tgz", + "integrity": "sha512-/TgHOqsa7/9abUKJjdPeydoyDc0oTi/7u9F8lMSj6ufg4cbC1Oj3f/Jja7zj7WRIhEQKB7Q4eN6y68I9RDxxGQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "peer": true, + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -18675,6 +18782,11 @@ "semver": "bin/semver.js" } }, + "node_modules/make-plural": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", + "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -18710,6 +18822,14 @@ "node": ">=0.10.0" } }, + "node_modules/math-interval-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", + "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -19107,6 +19227,11 @@ "node": ">= 14" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -19124,6 +19249,14 @@ "multicast-dns": "cli.js" } }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -22006,6 +22139,27 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-i18next": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.0.5.tgz", + "integrity": "sha512-5+bQSeEtgJrMBABBL5lO7jPdSNAbeAZ+MlFWDw//7FnVacuVu3l9EeWFzBQvZsKy+cihkbThWOAThEdH8YjGEw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-icons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", @@ -23844,6 +23998,11 @@ } ] }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -26630,6 +26789,14 @@ "node": ">= 0.8" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/webapp/package.json b/webapp/package.json index 95e0cfc9..85a27803 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -10,8 +10,10 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", + "i18n": "^0.15.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.0.5", "react-icons": "^5.0.1", "react-router-dom": "^6.22.2", "react-scripts": "^5.0.1", diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index fdabeeb1..0e9af41a 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -3,16 +3,19 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Link } from 'react-router-dom'; import "./Home.css"; - +import {useTranslation} from "react-i18next"; import "./Home.css"; + function Home() { + const[t, i18n] = useTranslation("global"); + return (

- Welcome to WIQ! + {t("home.welcome")}

@@ -26,24 +29,22 @@ function Home() { ); -} - - -function ButtonHowToPlay() { - return ( - - - - ); - -} + function ButtonHowToPlay() { + return ( + + + + ); + + } + function ButtonLogin() { return ( - + ); @@ -56,9 +57,12 @@ function LinkRegister() { component="button-register" variant="body2" > - Don't have an account? Register here. + {t("home.register")} ); } +} + + export default Home; diff --git a/webapp/src/components/Instructions.js b/webapp/src/components/Instructions.js index bee9b261..5f2e93c4 100644 --- a/webapp/src/components/Instructions.js +++ b/webapp/src/components/Instructions.js @@ -1,54 +1,57 @@ import React from 'react'; import '../components/Instructions.css'; +import {useTranslation} from "react-i18next"; function Instructions() { + const[t, i18n] = useTranslation("global"); + return (
-

WIQ Instructions

+

{t("instructions.title")}

-

    Objetive:

    +

      {t("instructions.objective")}

    • - The objective of the game is to answer as many questions correctly as possible. + {t("instructions.objective_p1")}
-

    How to Play:

    +

      {t("instructions.how_to_play")}

    • - The game consists of a series of questions. + {t("instructions.how_to_play_p1")}
    • - Read each question carefully. + {t("instructions.how_to_play_p2")}
    • - Choose the correct answer from the options provided. + {t("instructions.how_to_play_p3")}
    • - Click or tap on your selected answer to submit it. + {t("instructions.how_to_play_p4")}
-

    Scoring:

  • - Each correct answer earns you x points.
  • +

      {t("instructions.scoring")}

    • + {t("instructions.scoring_p1")}
    • - Incorrect answers do not deduct points. + {t("instructions.scoring_p2")}
-

    Time Limit:

  • - Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score. +

      {t("instructions.time_limit")}

    • + {t("instructions.time_limit_p1")}
-

    Have Fun!:

    +

      {t("instructions.have_fun")}

    • - Enjoy the game and test your knowledge. Good luck! + {t("instructions.have_fun_p1")}
diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index 2e65ea02..53235491 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -3,14 +3,20 @@ import React from 'react'; import Typography from "@mui/material/Typography"; import { Link } from 'react-router-dom'; import "./NavBar.css"; +import {useTranslation} from "react-i18next"; function Navbar() { + + const[t, i18n] = useTranslation("global"); + return (
- Know and Win! + {t("navBar.title")} + +
); diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index f0feb5c0..2fa87faa 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -1,29 +1,31 @@ -// src/components/AddUser.js -import React, { useState } from "react"; +import React from "react"; import { FaUser, FaLock } from "react-icons/fa"; import "./Login.css"; import { Link } from "react-router-dom"; +import { useTranslation } from "react-i18next"; const AddUser = () => { + const { t } = useTranslation("global"); + return (
-

Register

+

{t("addUser.title")}

- +
- +
- +
- +
@@ -33,12 +35,16 @@ const AddUser = () => { }; function LinkLogin() { + const { t } = useTranslation("global"); return ( - Do you have an account? Login here. + {t("addUser.login_link")} ); } + +export default AddUser; + // const [username, setUsername] = useState(''); // const [password, setPassword] = useState(''); // const [error, setError] = useState(''); @@ -90,4 +96,3 @@ function LinkLogin() { // ); // }; -export default AddUser; diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index 7d07e540..0e9c8c9d 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -1,36 +1,34 @@ -// import React, { useState } from "react"; -// import axios from "axios"; +import React from "react"; import { FaUser, FaLock } from "react-icons/fa"; -import "./Login.css"; import { Link } from "react-router-dom"; import Button from "@mui/material/Button"; +import { useTranslation } from "react-i18next"; const Login = () => { + const { t } = useTranslation("global"); - //empieza return (
-

Login

+

{t("login.title")}

- +
- +
- Forgot password? + {t("login.forgot_password")}
-
@@ -38,26 +36,27 @@ const Login = () => { ); }; - function ButtonMenu() { + const { t } = useTranslation("global"); return ( - - + + ); - } + function LinkRegister() { + const { t } = useTranslation("global"); return ( - Don't you have an account? Register here. + {t("login.register_link")} ); } + export default Login; + // // src/components/Login.js // import React, { useState } from 'react'; // import axios from 'axios'; diff --git a/webapp/src/index.js b/webapp/src/index.js index d563c0fb..cc263c85 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -3,11 +3,35 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; +import {I18nextProvider} from "react-i18next"; +import i18next from "i18next"; +import global_es from "./translations/es/global.json" +import global_en from "./translations/en/global.json" + + +i18next.init({ + interpolation: {escapeValue: false}, + + // idioma con el que va a empezar la app + lng: "en", + + resources: { + es:{ + global:global_es, + }, + en:{ + global:global_en, + } + }, +}) const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + {/* envolviendo la app con el sistema de traducciones */} + + + ); diff --git a/webapp/src/locales/en/messages_en.properties b/webapp/src/locales/en/messages_en.properties new file mode 100644 index 00000000..103b5e56 --- /dev/null +++ b/webapp/src/locales/en/messages_en.properties @@ -0,0 +1,19 @@ +# messages_en.properties +navbar.title = Know and Win! +button.language = Español +instructionsTitle=WIQ Instructions +objective=Objective: +objectiveDescription=The objective of the game is to answer as many questions correctly as possible. +howToPlay=How to Play: +howToPlayDescription1=The game consists of a series of questions. +howToPlayDescription2=Read each question carefully. +howToPlayDescription3=Choose the correct answer from the options provided. +howToPlayDescription4=Click or tap on your selected answer to submit it. +scoring=Scoring: +scoringDescription1=Each correct answer earns you x points. +scoringDescription2=Incorrect answers do not deduct points. +timeLimit=Time Limit: +timeLimitDescription=Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score. +haveFun=Have Fun!: +haveFunDescription=Enjoy the game and test your knowledge. Good luck! + diff --git a/webapp/src/locales/es/messages_es.properties b/webapp/src/locales/es/messages_es.properties new file mode 100644 index 00000000..a9ab7b5c --- /dev/null +++ b/webapp/src/locales/es/messages_es.properties @@ -0,0 +1,19 @@ +# messages_es.properties +navbar.title = Saber y ganar +button.language = English +instructionsTitle=Instrucciones de WIQ +objective=Objetivo: +objectiveDescription=El objetivo del juego es responder tantas preguntas correctamente como sea posible. +howToPlay=Cómo Jugar: +howToPlayDescription1=El juego consiste en una serie de preguntas. +howToPlayDescription2=Lee cada pregunta cuidadosamente. +howToPlayDescription3=Elige la respuesta correcta de las opciones proporcionadas. +howToPlayDescription4=Haz clic o toca tu respuesta seleccionada para enviarla. +scoring=Puntuación: +scoringDescription1=Cada respuesta correcta te otorga x puntos. +scoringDescription2=Las respuestas incorrectas no restan puntos. +timeLimit=Límite de Tiempo: +timeLimitDescription=Algunos modos de juego pueden tener un límite de tiempo para responder cada pregunta. Sé rápido y preciso para maximizar tu puntuación. +haveFun=¡Diviértete!: +haveFunDescription=¡Disfruta del juego y pon a prueba tus conocimientos. ¡Buena suerte! + diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json new file mode 100644 index 00000000..30b70e9b --- /dev/null +++ b/webapp/src/translations/en/global.json @@ -0,0 +1,51 @@ +{ + "home": { + "welcome": "Welcome to WIQ!", + "how_to_play": "How to play?", + "login": "Login", + "register": "Don't have an account? Register here." + }, + "navBar": { + "title": "Know and win!" + }, + "instructions": { + "title": "WIQ Instructions", + "objective": "Objective:", + "objective_p1": "The objective of the game is to answer as many questions correctly as possible.", + "how_to_play": "How to Play:", + "how_to_play_p1": "The game consists of a series of questions.", + "how_to_play_p2": "Read each question carefully.", + "how_to_play_p3": "Choose the correct answer from the options provided.", + "how_to_play_p4": "Click or tap on your selected answer to submit it.", + "scoring": "Scoring:", + "scoring_p1": "Each correct answer earns you x points.", + "scoring_p2": "Incorrect answers do not deduct points.", + "time_limit": "Time Limit:", + "time_limit_p1": "Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score.", + "have_fun": "Have Fun!:", + "have_fun_p1": "Enjoy the game and test your knowledge. Good luck!" + }, + "login": { + "title": "Login", + "username_placeholder": "Username", + "password_placeholder": "Password", + "remember_me": "Remember me", + "forgot_password": "Forgot password?", + "login_button": "Login", + "register_link": "Don't you have an account? Register here." + }, + "addUser": { + "title": "Register", + "username_placeholder": "Username", + "password_placeholder": "Password", + "repeat_password_placeholder": "Repeat password", + "register_button": "Register", + "login_link": "Do you have an account? Login here." + } +} + + + + + + \ No newline at end of file diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json new file mode 100644 index 00000000..d43e113f --- /dev/null +++ b/webapp/src/translations/es/global.json @@ -0,0 +1,52 @@ +{ + "home": { + "welcome": "¡Bienvenido a WIQ!", + "how_to_play": "¿Cómo jugar?", + "login": "Iniciar sesión", + "register": "¿No tienes una cuenta? Regístrate aquí." + }, + + "navBar": { + "title": "¡Saber y ganar!" + }, + + "instructions": { + "title": "Instrucciones de WIQ", + "objective": "Objetivo:", + "objective_p1": "El objetivo del juego es responder tantas preguntas correctamente como sea posible.", + "how_to_play": "Cómo Jugar:", + "how_to_play_p1": "El juego consiste en una serie de preguntas.", + "how_to_play_p2": "Lee cada pregunta cuidadosamente.", + "how_to_play_p3": "Elige la respuesta correcta de las opciones proporcionadas.", + "how_to_play_p4": "Haz clic o toca tu respuesta seleccionada para enviarla.", + + "scoring": "Puntuación:", + "scoring_p1": "Cada respuesta correcta te otorga x puntos.", + "scoring_p2": "Las respuestas incorrectas no restan puntos.", + "time_limit": "Límite de Tiempo:", + "time_limit_p1": "Algunos modos de juego pueden tener un límite de tiempo para responder cada pregunta. Sé rápido y preciso para maximizar tu puntuación.", + "have_fun": "¡Diviértete!", + "have_fun_p1": "¡Disfruta del juego y pon a prueba tus conocimientos. Buena suerte!" + }, + "login": { + "title": "Inicio de sesión", + "username_placeholder": "Nombre de usuario", + "password_placeholder": "Contraseña", + "remember_me": "Recordarme", + "forgot_password": "¿Olvidaste tu contraseña?", + "login_button": "Iniciar sesión", + "register_link": "¿No tienes una cuenta? Regístrate aquí." + }, + + "addUser": { + "title": "Registrar", + "username_placeholder": "Nombre de usuario", + "password_placeholder": "Contraseña", + "repeat_password_placeholder": "Repetir contraseña", + "register_button": "Registrarse", + "login_link": "¿Ya tienes una cuenta? Inicia sesión aquí." + } + + + } + \ No newline at end of file From 5e26b9c0d927bd0f0fa6411cadc74064a61f301f Mon Sep 17 00:00:00 2001 From: uo289267 Date: Wed, 6 Mar 2024 22:01:04 +0100 Subject: [PATCH 11/16] Added Navigability from Login to Game Menu to Question View and fixed some things. There is a need for fixing css files and internacionalizing Game Menu. --- webapp/src/App.js | 4 +- webapp/src/components/GameMenu/GameMenu.css | 40 +++++++++---------- webapp/src/components/GameMenu/GameMenu.js | 22 +++++----- .../components/questionView/QuestionView.css | 6 +-- .../components/questionView/QuestionView.js | 21 +++++----- 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/webapp/src/App.js b/webapp/src/App.js index 6c402cbf..29e0f7fe 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -2,9 +2,9 @@ import React from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import Container from '@mui/material/Container'; import QuestionView from './components/questionView/QuestionView'; -import GameMenu from './components/GameMenu'; +import GameMenu from './components/GameMenu/GameMenu'; import Navbar from './components/fragments/NavBar'; -import Home from './components/home/Home'; +import Home from './components/Home/Home'; import Login from './components/loginAndRegistration/Login'; import AddUser from './components/loginAndRegistration/AddUser'; import Instructions from './components/Instructions'; diff --git a/webapp/src/components/GameMenu/GameMenu.css b/webapp/src/components/GameMenu/GameMenu.css index 6d193db1..db52042c 100644 --- a/webapp/src/components/GameMenu/GameMenu.css +++ b/webapp/src/components/GameMenu/GameMenu.css @@ -1,22 +1,22 @@ -button{ - width: 100%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; - } +.menuButton { + width: 40%; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; +} -div{ - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; +.divMenu { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; } \ No newline at end of file diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index 587c6453..c5b1169d 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -1,8 +1,10 @@ import './GameMenu.css'; +import { Link } from "react-router-dom"; +import QuestionView from '../questionView/QuestionView'; export default function GameMenu() { return ( -
-

Game

+
+

Game Menu

@@ -12,16 +14,18 @@ export default function GameMenu() { function ButtonHistoricalData() { function handleClick() { //ir a la vista de historical data - alert("Historical DAta"); + alert("Historical Data"); } - return ; + return ; } function ButtonNewGame() { - function handleClick() { - //ir a la vista de la primera pregunta - alert("New game"); - } - return ; + return ( + <> + + + + + ); } \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.css b/webapp/src/components/questionView/QuestionView.css index d823940f..035cd898 100644 --- a/webapp/src/components/questionView/QuestionView.css +++ b/webapp/src/components/questionView/QuestionView.css @@ -1,4 +1,4 @@ -button{ +.answerButton { width: 100%; height: 45px; background: darkblue; @@ -12,7 +12,7 @@ button{ font-weight: 700; } -div { +.answerPanel { display: grid; grid-template-columns: repeat(2, 1fr); /* 2 columns */ grid-template-rows: repeat(2, 1fr); /* 2 rows */ @@ -20,7 +20,7 @@ div { } /* Adjust width of child elements */ -div > * { +.answerPanel div > * { width: 100%; /* Adjust as needed */ margin:1em; } diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index c939763f..e116f32b 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -3,6 +3,7 @@ import QuestionGenerator from './QuestionGenerator'; import { useEffect, useState } from 'react'; import './QuestionView.css'; + function QuestionView(){ const questionGenerator = new QuestionGenerator(); const [numQuestion, setnumQuestion] = useState(-1); @@ -29,11 +30,11 @@ function QuestionView(){ useEffect(() => {generateQuestions(numQuestion)}, []); return ( -
+
{/*Nav*/} {numQuestion >= 0 ? : -

Please Wait a bit

} +

Please Wait a bit...

}
); @@ -42,20 +43,20 @@ function QuestionView(){ function QuestionComponent({questions, numQuestion, handleClick}){ return ( <> -

{questions[numQuestion].getQuestion()}

-
- {questions[numQuestion].getAnswers().map((item, index) => ( - - ))} -

Question counter: {numQuestion}

-
+

{questions[numQuestion].getQuestion()}

+
+ {questions[numQuestion].getAnswers().map((item, index) => ( + + ))} +

Question counter: {numQuestion}

+
); } function Answer({text, onClick}){ return ( - + ); } From a243b800971f1c844827ba4e3f30f4d8527f1533 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Thu, 7 Mar 2024 15:42:56 +0100 Subject: [PATCH 12/16] Merged all the css into one "custom.css" --- webapp/src/App.css | 38 -- webapp/src/App.js | 4 +- webapp/src/components/GameMenu.js | 0 webapp/src/components/GameMenu/GameMenu.css | 22 -- webapp/src/components/GameMenu/GameMenu.js | 7 +- webapp/src/components/Home/Home.css | 37 -- webapp/src/components/Home/Home.js | 5 +- webapp/src/components/Instructions.css | 21 -- webapp/src/components/Instructions.js | 2 +- webapp/src/components/fragments/NavBar.css | 41 --- webapp/src/components/fragments/NavBar.js | 11 +- .../loginAndRegistration/AddUser.js | 2 +- .../components/loginAndRegistration/Login.css | 106 ------ .../components/loginAndRegistration/Login.js | 1 + .../src/components/questionView/Question.js | 2 + .../questionView/QuestionGenerator.js | 1 + .../components/questionView/QuestionView.css | 29 -- .../components/questionView/QuestionView.js | 5 +- webapp/src/custom.css | 339 ++++++++++++++++++ webapp/src/index.css | 13 - webapp/src/index.js | 2 +- webapp/src/locales/en/messages_en.properties | 19 - webapp/src/locales/es/messages_es.properties | 19 - 23 files changed, 361 insertions(+), 365 deletions(-) delete mode 100644 webapp/src/App.css delete mode 100644 webapp/src/components/GameMenu.js delete mode 100644 webapp/src/components/GameMenu/GameMenu.css delete mode 100644 webapp/src/components/Home/Home.css delete mode 100644 webapp/src/components/Instructions.css delete mode 100644 webapp/src/components/fragments/NavBar.css delete mode 100644 webapp/src/components/loginAndRegistration/Login.css delete mode 100644 webapp/src/components/questionView/QuestionView.css create mode 100644 webapp/src/custom.css delete mode 100644 webapp/src/index.css delete mode 100644 webapp/src/locales/en/messages_en.properties delete mode 100644 webapp/src/locales/es/messages_es.properties diff --git a/webapp/src/App.css b/webapp/src/App.css deleted file mode 100644 index 74b5e053..00000000 --- a/webapp/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/webapp/src/App.js b/webapp/src/App.js index 29e0f7fe..fd336858 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -4,11 +4,11 @@ import Container from '@mui/material/Container'; import QuestionView from './components/questionView/QuestionView'; import GameMenu from './components/GameMenu/GameMenu'; import Navbar from './components/fragments/NavBar'; -import Home from './components/Home/Home'; +import Home from './components/home/Home'; import Login from './components/loginAndRegistration/Login'; import AddUser from './components/loginAndRegistration/AddUser'; import Instructions from './components/Instructions'; - +import './custom.css'; function App() { return ( diff --git a/webapp/src/components/GameMenu.js b/webapp/src/components/GameMenu.js deleted file mode 100644 index e69de29b..00000000 diff --git a/webapp/src/components/GameMenu/GameMenu.css b/webapp/src/components/GameMenu/GameMenu.css deleted file mode 100644 index db52042c..00000000 --- a/webapp/src/components/GameMenu/GameMenu.css +++ /dev/null @@ -1,22 +0,0 @@ -.menuButton { - width: 40%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; -} - -.divMenu { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; -} \ No newline at end of file diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index c5b1169d..d9961bdc 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -1,6 +1,5 @@ -import './GameMenu.css'; +import "../../custom.css"; import { Link } from "react-router-dom"; -import QuestionView from '../questionView/QuestionView'; export default function GameMenu() { return (
@@ -22,8 +21,8 @@ export default function GameMenu() { function ButtonNewGame() { return ( <> - - + + ); diff --git a/webapp/src/components/Home/Home.css b/webapp/src/components/Home/Home.css deleted file mode 100644 index 98b8043a..00000000 --- a/webapp/src/components/Home/Home.css +++ /dev/null @@ -1,37 +0,0 @@ - .wrapper { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; - } - - .wrapper button{ - width: 100%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; - } - - .wrapper link{ - font-size: 14.5px; - text-align: center; - margin: 20px 0 15px; - } - - - - - - - - - - diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 0e9af41a..0faf09e7 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -1,12 +1,9 @@ import React from "react"; -import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Link } from 'react-router-dom'; -import "./Home.css"; +import "../../custom.css"; import {useTranslation} from "react-i18next"; -import "./Home.css"; - function Home() { diff --git a/webapp/src/components/Instructions.css b/webapp/src/components/Instructions.css deleted file mode 100644 index e381600b..00000000 --- a/webapp/src/components/Instructions.css +++ /dev/null @@ -1,21 +0,0 @@ - -main{ - background-color: white; -} - -section { - text-align: justify; - background-color: white; -} - - -article ul p{ - text-align: center; - background-color: lightblue; - font-size: large; -} - -article ul li{ - text-align: justify; - background-color: white; -} \ No newline at end of file diff --git a/webapp/src/components/Instructions.js b/webapp/src/components/Instructions.js index 5f2e93c4..a881b6ed 100644 --- a/webapp/src/components/Instructions.js +++ b/webapp/src/components/Instructions.js @@ -1,5 +1,5 @@ import React from 'react'; -import '../components/Instructions.css'; +import '../custom.css'; import {useTranslation} from "react-i18next"; diff --git a/webapp/src/components/fragments/NavBar.css b/webapp/src/components/fragments/NavBar.css deleted file mode 100644 index 4ec0f2c2..00000000 --- a/webapp/src/components/fragments/NavBar.css +++ /dev/null @@ -1,41 +0,0 @@ -.navbar-container { - display: flex; - justify-content: space-between; - align-items: center; - background-color: blue; - width: 100%; - padding: 10px; - box-sizing: border-box; - } - - main { - width: 100%; - } - - .navbar-container img { - width: 40px; - height: 40px; - margin-right: 10px; - } - - .navbar-text { - color: white; - } - - - .help-button { - border: none; - background: none; - - } - - .help-button img { - width: 40px; - height: 40px; - } - - - - - - \ No newline at end of file diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index 53235491..d65ef527 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -2,7 +2,7 @@ import React from 'react'; import Typography from "@mui/material/Typography"; import { Link } from 'react-router-dom'; -import "./NavBar.css"; +import "../../custom.css"; import {useTranslation} from "react-i18next"; function Navbar() { @@ -15,9 +15,12 @@ function Navbar() { {t("navBar.title")} - - - +
+ + + +
+
); } diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index 2fa87faa..5911c7f5 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -1,6 +1,6 @@ import React from "react"; import { FaUser, FaLock } from "react-icons/fa"; -import "./Login.css"; +import "../../custom.css"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; diff --git a/webapp/src/components/loginAndRegistration/Login.css b/webapp/src/components/loginAndRegistration/Login.css deleted file mode 100644 index c65fa58b..00000000 --- a/webapp/src/components/loginAndRegistration/Login.css +++ /dev/null @@ -1,106 +0,0 @@ - -.wrapper{ - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - background-color: lightblue; -} - -.wrapper2{ - width: 420px; - background-color: blue; - color: white; - border-style: 10px; - padding: 30px 40px; - border-radius: 15%; -} - -.wrapper2 h1{ - font-size: 36px; - text-align: center; -} - -.wrapper2 .input-box{ - position: relative; - width: 100%; - height: 50px; - margin: 30px 0; -} - -.input-box input{ - width: 100%; - height: 100%; - background: lightblue; - border: none; - outline: none; - border: 2px solid gray; - border-radius: 40px; - font-size: 14.5px; - color: black; -} - -.input-box input::placeholder{ - background-color: lightblue; -} - -.input-box .icon{ - position: absolute; - right: 20px; - top: 50%; - transform: translateY(-50%); - font-size: 16px; -} - -.wrapper2 .remember-forgot{ - display: flex; - justify-content: space-between; - font-size: 14.5px; - margin: -15px 0 15px; -} - -.remember-forgot label input{ - accent-color: white; - margin-right: 4px; -} - -.remember-forgot a { - color: white; - text-decoration: none; -} - -.remember-forgot a:hover{ - text-decoration: underline; -} - -.wrapper2 button{ - width: 100%; - height: 45px; - background: white; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: black; - font-weight: 700; -} - -.button-register { - color: aliceblue; - } - - .button-login { - color: aliceblue; - } - -.register-link p a { - color: white; - text-decoration: none; - font-weight: 600; -} - -.register-link p a:hover{ - text-decoration: underline; -} \ No newline at end of file diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index 0e9c8c9d..167b5ca8 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -3,6 +3,7 @@ import { FaUser, FaLock } from "react-icons/fa"; import { Link } from "react-router-dom"; import Button from "@mui/material/Button"; import { useTranslation } from "react-i18next"; +import "../../custom.css"; const Login = () => { const { t } = useTranslation("global"); diff --git a/webapp/src/components/questionView/Question.js b/webapp/src/components/questionView/Question.js index a572d7e1..41346f6a 100644 --- a/webapp/src/components/questionView/Question.js +++ b/webapp/src/components/questionView/Question.js @@ -1,3 +1,5 @@ +import "../../custom.css"; + class Question{ constructor(json){ this.question = ""; diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index 42049447..391047f6 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -1,4 +1,5 @@ import Question from './Question'; +import "../../custom.css"; class QuestionGenerator{ constructor(){ diff --git a/webapp/src/components/questionView/QuestionView.css b/webapp/src/components/questionView/QuestionView.css deleted file mode 100644 index 035cd898..00000000 --- a/webapp/src/components/questionView/QuestionView.css +++ /dev/null @@ -1,29 +0,0 @@ -.answerButton { - width: 100%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; -} - -.answerPanel { - display: grid; - grid-template-columns: repeat(2, 1fr); /* 2 columns */ - grid-template-rows: repeat(2, 1fr); /* 2 rows */ - gap: 10px; /* Adjust the gap between grid items */ -} - -/* Adjust width of child elements */ -.answerPanel div > * { - width: 100%; /* Adjust as needed */ - margin:1em; -} -p{ - text-align: center; -} \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index e116f32b..2686ae44 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -1,7 +1,6 @@ -import Question from './Question'; import QuestionGenerator from './QuestionGenerator'; import { useEffect, useState } from 'react'; -import './QuestionView.css'; +import "../../custom.css"; function QuestionView(){ @@ -30,7 +29,7 @@ function QuestionView(){ useEffect(() => {generateQuestions(numQuestion)}, []); return ( -
+
{/*Nav*/} {numQuestion >= 0 ? : diff --git a/webapp/src/custom.css b/webapp/src/custom.css new file mode 100644 index 00000000..39ce5c1b --- /dev/null +++ b/webapp/src/custom.css @@ -0,0 +1,339 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; + } + .App { + text-align: center; + } + + .App-logo { + height: 40vmin; + pointer-events: none; + } + + @media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } + } + + .App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; + } + + .App-link { + color: #61dafb; + } + + @keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } + .navbar-container { + display: flex; + justify-content: space-between; + align-items: center; + background-color: blue; + width: 100%; + padding: 10px; + box-sizing: border-box; + } + + main { + width: 100%; + } + + .navbar-container img { + display: flex; + justify-content: space-between; + align-items: center; + width: 40px; + height: 40px; + margin-right: 10px; + } + + .navbar-text { + color: white; + } + + + .help-button { + border: none; + background: none; + + } + + .en-button, .es-button{ + margin-right: 10px; + background: rgb(171, 171, 221); + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; + } + + .right-nav{ + display: flex; + } + + + + .help-button img { + width: 40px; + height: 40px; + } + + + .menuButton { + width: 200px; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor: pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; + } + + .create-game{ + width: 200px; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor: pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; + } + + + + + .divMenu { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + background-color: lightblue; + + } + + .wrapper { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + } + + .wrapper button{ + width: 100%; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; + } + + .wrapper link{ + font-size: 14.5px; + text-align: center; + margin: 20px 0 15px; + } + + +.wrapper{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background-color: lightblue; +} + +.wrapper2{ + width: 420px; + background-color: blue; + color: white; + border-style: 10px; + padding: 30px 40px; + border-radius: 15%; +} + +.wrapper2 h1{ + font-size: 36px; + text-align: center; +} + +.wrapper2 .input-box{ + position: relative; + width: 100%; + height: 50px; + margin: 30px 0; +} + +.input-box input{ + width: 100%; + height: 100%; + background: lightblue; + border: none; + outline: none; + border: 2px solid gray; + border-radius: 40px; + font-size: 14.5px; + color: black; +} + +.input-box input::placeholder{ + background-color: lightblue; +} + +.input-box .icon{ + position: absolute; + right: 20px; + top: 50%; + transform: translateY(-50%); + font-size: 16px; +} + +.wrapper2 .remember-forgot{ + display: flex; + justify-content: space-between; + font-size: 14.5px; + margin: -15px 0 15px; +} + +.remember-forgot label input{ + accent-color: white; + margin-right: 4px; +} + +.remember-forgot a { + color: white; + text-decoration: none; +} + +.remember-forgot a:hover{ + text-decoration: underline; +} + +.wrapper2 button{ + width: 100%; + height: 45px; + background: white; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: black; + font-weight: 700; +} + +.button-register { + color: aliceblue; + } + + .button-login { + color: aliceblue; + } + +.register-link p a { + color: white; + text-decoration: none; + font-weight: 600; +} + +.register-link p a:hover{ + text-decoration: underline; +} + +.answerButton { + width: 100%; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; +} + +.answerPanel { + display: grid; + grid-template-columns: repeat(2, 1fr); /* 2 columns */ + grid-template-rows: repeat(2, 1fr); /* 2 rows */ + gap: 10px; /* Adjust the gap between grid items */ + + +} + +/* Adjust width of child elements */ +.answerPanel div > * { + width: 100%; /* Adjust as needed */ + margin:1em; +} +p{ + text-align: center; +} + + +.question-view-container, .answerPanel { + background-color: lightblue; + padding: 20px; +} + + + + + + + + + + + + + \ No newline at end of file diff --git a/webapp/src/index.css b/webapp/src/index.css deleted file mode 100644 index ec2585e8..00000000 --- a/webapp/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/webapp/src/index.js b/webapp/src/index.js index cc263c85..f5d8ebec 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import './index.css'; +import './custom.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import {I18nextProvider} from "react-i18next"; diff --git a/webapp/src/locales/en/messages_en.properties b/webapp/src/locales/en/messages_en.properties deleted file mode 100644 index 103b5e56..00000000 --- a/webapp/src/locales/en/messages_en.properties +++ /dev/null @@ -1,19 +0,0 @@ -# messages_en.properties -navbar.title = Know and Win! -button.language = Español -instructionsTitle=WIQ Instructions -objective=Objective: -objectiveDescription=The objective of the game is to answer as many questions correctly as possible. -howToPlay=How to Play: -howToPlayDescription1=The game consists of a series of questions. -howToPlayDescription2=Read each question carefully. -howToPlayDescription3=Choose the correct answer from the options provided. -howToPlayDescription4=Click or tap on your selected answer to submit it. -scoring=Scoring: -scoringDescription1=Each correct answer earns you x points. -scoringDescription2=Incorrect answers do not deduct points. -timeLimit=Time Limit: -timeLimitDescription=Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score. -haveFun=Have Fun!: -haveFunDescription=Enjoy the game and test your knowledge. Good luck! - diff --git a/webapp/src/locales/es/messages_es.properties b/webapp/src/locales/es/messages_es.properties deleted file mode 100644 index a9ab7b5c..00000000 --- a/webapp/src/locales/es/messages_es.properties +++ /dev/null @@ -1,19 +0,0 @@ -# messages_es.properties -navbar.title = Saber y ganar -button.language = English -instructionsTitle=Instrucciones de WIQ -objective=Objetivo: -objectiveDescription=El objetivo del juego es responder tantas preguntas correctamente como sea posible. -howToPlay=Cómo Jugar: -howToPlayDescription1=El juego consiste en una serie de preguntas. -howToPlayDescription2=Lee cada pregunta cuidadosamente. -howToPlayDescription3=Elige la respuesta correcta de las opciones proporcionadas. -howToPlayDescription4=Haz clic o toca tu respuesta seleccionada para enviarla. -scoring=Puntuación: -scoringDescription1=Cada respuesta correcta te otorga x puntos. -scoringDescription2=Las respuestas incorrectas no restan puntos. -timeLimit=Límite de Tiempo: -timeLimitDescription=Algunos modos de juego pueden tener un límite de tiempo para responder cada pregunta. Sé rápido y preciso para maximizar tu puntuación. -haveFun=¡Diviértete!: -haveFunDescription=¡Disfruta del juego y pon a prueba tus conocimientos. ¡Buena suerte! - From d5f330c27adc837c3bacc47550ebd4746952d4bf Mon Sep 17 00:00:00 2001 From: uo289267 Date: Thu, 7 Mar 2024 22:00:49 +0100 Subject: [PATCH 13/16] Added a counter for the questions and internacionalized manu and question views --- package-lock.json | 13 +++++++ package.json | 1 + webapp/src/components/GameMenu/GameMenu.css | 11 ++++++ webapp/src/components/GameMenu/GameMenu.js | 19 +++++----- .../components/questionView/QuestionView.js | 36 +++++++++++++------ webapp/src/locales/en/messages_en.properties | 1 - webapp/src/translations/en/global.json | 10 ++++++ webapp/src/translations/es/global.json | 9 +++++ 8 files changed, 81 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 290c65f6..737d6d39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "@material-ui/icons": "^4.11.3", "asciidoctor-emoji": "^0.5.0", "i18n": "^0.15.1", + "react-countdown": "^2.3.5", "react-router-dom": "^6.22.1" } }, @@ -663,6 +664,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-countdown": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/react-countdown/-/react-countdown-2.3.5.tgz", + "integrity": "sha512-K26ENYEesMfPxhRRtm1r+Pf70SErrvW3g4CArLi/x6MPFjgfDFYePT4UghEj8p2nI0cqVV7/JjDgjyr//U60Og==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">= 15", + "react-dom": ">= 15" + } + }, "node_modules/react-dom": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", diff --git a/package.json b/package.json index a508ec7e..37679c9a 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "@material-ui/icons": "^4.11.3", "asciidoctor-emoji": "^0.5.0", "i18n": "^0.15.1", + "react-countdown": "^2.3.5", "react-router-dom": "^6.22.1" } } diff --git a/webapp/src/components/GameMenu/GameMenu.css b/webapp/src/components/GameMenu/GameMenu.css index db52042c..f56fd2d4 100644 --- a/webapp/src/components/GameMenu/GameMenu.css +++ b/webapp/src/components/GameMenu/GameMenu.css @@ -11,8 +11,19 @@ color: white; font-weight: 700; margin: 0.5em; + text-align: center; } +.countdown { + font-weight: 500; + margin: 3em; +} + +.topPanel{ + display: flex; + flex-direction: row; + align-items: center; +} .divMenu { display: flex; flex-direction: column; diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index c5b1169d..25f43792 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -1,29 +1,32 @@ import './GameMenu.css'; import { Link } from "react-router-dom"; -import QuestionView from '../questionView/QuestionView'; +import {useTranslation} from "react-i18next"; + export default function GameMenu() { + const[t, i18n] = useTranslation("global"); + return (
-

Game Menu

- - +

{t("gameMenu.title")}

+ +
); } - function ButtonHistoricalData() { + function ButtonHistoricalData({ t }) { function handleClick() { //ir a la vista de historical data alert("Historical Data"); } - return ; + return ; } - function ButtonNewGame() { + function ButtonNewGame({t}) { return ( <> - +

{t("gameMenu.new_game_button")}

); diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index e116f32b..cd69d9ba 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -2,12 +2,15 @@ import Question from './Question'; import QuestionGenerator from './QuestionGenerator'; import { useEffect, useState } from 'react'; import './QuestionView.css'; - +import React from "react"; +import Countdown from "react-countdown"; +import {useTranslation} from "react-i18next"; function QuestionView(){ const questionGenerator = new QuestionGenerator(); const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); + const[t, i18n] = useTranslation("global"); const generateQuestions = async (numQuestion) => { if (numQuestion < 0) { @@ -33,23 +36,36 @@ function QuestionView(){
{/*Nav*/} {numQuestion >= 0 ? - : + :

Please Wait a bit...

} - -
); } -function QuestionComponent({questions, numQuestion, handleClick}){ +function QuestionComponent({questions, numQuestion, handleClick, t}){ + const renderer = ({seconds, completed }) => { + if (completed) { + + return {t("questionView.end_countdown")}; // Rendered when countdown completes + } else { + return {seconds} {t("questionView.seconds")}; // Render countdown + } + }; + return ( <> +

{questions[numQuestion].getQuestion()}

-
- {questions[numQuestion].getAnswers().map((item, index) => ( - - ))} -

Question counter: {numQuestion}

+
+
+
+
+ {questions[numQuestion].getAnswers().map((item, index) => ( + + ))} + +
+

{t("questionView.question_counter")} {numQuestion}

); } diff --git a/webapp/src/locales/en/messages_en.properties b/webapp/src/locales/en/messages_en.properties index 103b5e56..970112c4 100644 --- a/webapp/src/locales/en/messages_en.properties +++ b/webapp/src/locales/en/messages_en.properties @@ -16,4 +16,3 @@ timeLimit=Time Limit: timeLimitDescription=Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score. haveFun=Have Fun!: haveFunDescription=Enjoy the game and test your knowledge. Good luck! - diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 30b70e9b..b7f7248d 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -41,6 +41,16 @@ "repeat_password_placeholder": "Repeat password", "register_button": "Register", "login_link": "Do you have an account? Login here." + }, + "gameMenu":{ + "history_button":"View Historical Data", + "new_game_button":"Create New Game", + "title":"Game Menu" + }, + "questionView":{ + "seconds":"seconds", + "question_counter":"Question counter :", + "end_countdown":"Time's up!" } } diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index d43e113f..3277d13a 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -45,6 +45,15 @@ "repeat_password_placeholder": "Repetir contraseña", "register_button": "Registrarse", "login_link": "¿Ya tienes una cuenta? Inicia sesión aquí." + }, + "gameMenu":{ + "history_button":"Ver Historial", + "new_game_button":"Crear nuevo juego", + "title":"Menú del Juego" + },"questionView":{ + "seconds":"segundos", + "question_counter":"Número de pregunta : ", + "end_countdown":"¡Se acabó el tiempo!" } From 2c7c7c8aaaf35b850735e9d377f70ac5837e0746 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Thu, 7 Mar 2024 23:31:56 +0100 Subject: [PATCH 14/16] Improving --- webapp/package-lock.json | 13 +++++ webapp/package.json | 1 + webapp/src/components/GameMenu/GameMenu.js | 15 +++--- webapp/src/custom.css | 57 ++++++++++++++++------ 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 72a49817..ad42295e 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -17,6 +17,7 @@ "axios": "^1.6.5", "i18n": "^0.15.1", "react": "^18.2.0", + "react-countdown": "^2.3.5", "react-dom": "^18.2.0", "react-i18next": "^14.0.5", "react-icons": "^5.0.1", @@ -22005,6 +22006,18 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/react-countdown": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/react-countdown/-/react-countdown-2.3.5.tgz", + "integrity": "sha512-K26ENYEesMfPxhRRtm1r+Pf70SErrvW3g4CArLi/x6MPFjgfDFYePT4UghEj8p2nI0cqVV7/JjDgjyr//U60Og==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">= 15", + "react-dom": ">= 15" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", diff --git a/webapp/package.json b/webapp/package.json index 85a27803..f31b2a0c 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -12,6 +12,7 @@ "axios": "^1.6.5", "i18n": "^0.15.1", "react": "^18.2.0", + "react-countdown": "^2.3.5", "react-dom": "^18.2.0", "react-i18next": "^14.0.5", "react-icons": "^5.0.1", diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index ed5a392c..a84fe5ea 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -22,13 +22,10 @@ export default function GameMenu() { return ; } - function ButtonNewGame({t}) { + function ButtonNewGame({ t }) { return ( - <> - -

{t("gameMenu.new_game_button")}

- - - ); - } - \ No newline at end of file + +

{t("gameMenu.new_game_button")}

+ + ); + } \ No newline at end of file diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 39ce5c1b..cc3106ae 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -110,21 +110,40 @@ body { .menuButton { - width: 200px; - height: 45px; + width: 40%; + height: 45px; background: darkblue; border: none; outline: none; border-radius: 40px; box-shadow: 0 0 10px black; - cursor: pointer; + cursor:pointer; font-size: 16px; color: white; font-weight: 700; margin: 0.5em; + text-align: center; + } + + .countdown { + font-weight: 500; + margin: 3em; + } + + .topPanel{ + display: flex; + flex-direction: row; + align-items: center; + } + .divMenu { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; } - .create-game{ + .menuButton{ width: 200px; height: 45px; background: darkblue; @@ -137,20 +156,30 @@ body { color: white; font-weight: 700; margin: 0.5em; + text-decoration: none; } - + + .linkButton { + display: flex; + justify-content: center; + align-items: center; + width: 200px; + height: 45px; + background: darkblue; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor: pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; + text-decoration: none; +} - - .divMenu { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; - background-color: lightblue; - } .wrapper { display: flex; From 088764b3b33570bd4bd7f514d3c5238029f9bf82 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sat, 9 Mar 2024 11:14:06 +0100 Subject: [PATCH 15/16] Elimination of properties file --- webapp/src/locales/en/messages_en.properties | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 webapp/src/locales/en/messages_en.properties diff --git a/webapp/src/locales/en/messages_en.properties b/webapp/src/locales/en/messages_en.properties deleted file mode 100644 index 970112c4..00000000 --- a/webapp/src/locales/en/messages_en.properties +++ /dev/null @@ -1,18 +0,0 @@ -# messages_en.properties -navbar.title = Know and Win! -button.language = Español -instructionsTitle=WIQ Instructions -objective=Objective: -objectiveDescription=The objective of the game is to answer as many questions correctly as possible. -howToPlay=How to Play: -howToPlayDescription1=The game consists of a series of questions. -howToPlayDescription2=Read each question carefully. -howToPlayDescription3=Choose the correct answer from the options provided. -howToPlayDescription4=Click or tap on your selected answer to submit it. -scoring=Scoring: -scoringDescription1=Each correct answer earns you x points. -scoringDescription2=Incorrect answers do not deduct points. -timeLimit=Time Limit: -timeLimitDescription=Some game modes may have a time limit for answering each question. Be quick and accurate to maximize your score. -haveFun=Have Fun!: -haveFunDescription=Enjoy the game and test your knowledge. Good luck! From 87e35515375ae4c64a90687de991e156bcd76fd6 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Sat, 9 Mar 2024 11:25:19 +0100 Subject: [PATCH 16/16] Improvements in the css --- webapp/src/components/GameMenu/GameMenu.css | 33 --------------------- webapp/src/components/Instructions.js | 12 ++++---- webapp/src/custom.css | 25 ++++++++++------ 3 files changed, 22 insertions(+), 48 deletions(-) delete mode 100644 webapp/src/components/GameMenu/GameMenu.css diff --git a/webapp/src/components/GameMenu/GameMenu.css b/webapp/src/components/GameMenu/GameMenu.css deleted file mode 100644 index f56fd2d4..00000000 --- a/webapp/src/components/GameMenu/GameMenu.css +++ /dev/null @@ -1,33 +0,0 @@ -.menuButton { - width: 40%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; - text-align: center; -} - -.countdown { - font-weight: 500; - margin: 3em; -} - -.topPanel{ - display: flex; - flex-direction: row; - align-items: center; -} -.divMenu { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; -} \ No newline at end of file diff --git a/webapp/src/components/Instructions.js b/webapp/src/components/Instructions.js index a881b6ed..7ffc2338 100644 --- a/webapp/src/components/Instructions.js +++ b/webapp/src/components/Instructions.js @@ -10,17 +10,17 @@ function Instructions() { return (
-

{t("instructions.title")}

+

{t("instructions.title")}

-

    {t("instructions.objective")}

    +

      {t("instructions.objective")}

    • {t("instructions.objective_p1")}
-

    {t("instructions.how_to_play")}

    +

      {t("instructions.how_to_play")}

    • {t("instructions.how_to_play_p1")}
    • @@ -36,7 +36,7 @@ function Instructions() {
-

    {t("instructions.scoring")}

  • +

      {t("instructions.scoring")}

    • {t("instructions.scoring_p1")}
    • {t("instructions.scoring_p2")} @@ -44,12 +44,12 @@ function Instructions() {
-

    {t("instructions.time_limit")}

  • +

      {t("instructions.time_limit")}

    • {t("instructions.time_limit_p1")}
-

    {t("instructions.have_fun")}

    +

      {t("instructions.have_fun")}

    • {t("instructions.have_fun_p1")}
    • diff --git a/webapp/src/custom.css b/webapp/src/custom.css index cc3106ae..4964935c 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -335,7 +335,6 @@ body { grid-template-columns: repeat(2, 1fr); /* 2 columns */ grid-template-rows: repeat(2, 1fr); /* 2 rows */ gap: 10px; /* Adjust the gap between grid items */ - } @@ -344,6 +343,7 @@ body { width: 100%; /* Adjust as needed */ margin:1em; } + p{ text-align: center; } @@ -354,15 +354,22 @@ p{ padding: 20px; } +.Instructions-container { + background-color: #eaf6ff; /* Cambia este valor al color de azul que prefieras */ + padding: 20px; /* Añade un poco de espacio alrededor del contenido */ +} +.instructions_title{ + background-color: darkblue; + color: white; +} +.ins_ul p{ + background-color: blue; + color: white; +} +.Instructions{ + background-color: lightblue; +} - - - - - - - - \ No newline at end of file