feat: devweb - Make translations on profile page and error management

This commit is contained in:
kmitresse
2024-06-11 15:33:11 +02:00
parent 885ea243c1
commit 1fe2487563
28 changed files with 435 additions and 181 deletions
@@ -77,6 +77,11 @@ public class ForgottenPasswordBean implements Serializable {
return this;
}
/**
*
* @param translator le traducteur
* @return this
*/
public ForgottenPasswordBean setTranslator(Translator translator) {
this.translator = translator;
return this;
@@ -14,6 +14,7 @@ import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
public class LoginBean implements Serializable {
@@ -23,6 +24,7 @@ public class LoginBean implements Serializable {
private String password;
private User user;
private HttpResponse error;
private Translator translator;
public LoginBean() {
}
@@ -46,11 +48,11 @@ public class LoginBean implements Serializable {
}
}
} catch (DAOException e) {
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR,"Une erreur est survenue (DB_CONNECTION_ERROR:001)");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR,translator.translate("internal_error_1"));
return false;
}
error = new HttpResponse(HttpResponseCode.NOT_FOUND,"Le nom d'utilisateur ou le mot de passe est incorrect.");
error = new HttpResponse(HttpResponseCode.NOT_FOUND, translator.translate("login_error"));
return false;
}
@@ -74,6 +76,16 @@ public class LoginBean implements Serializable {
return this;
}
/**
*
* @param translator le traducteur
* @return l'entité
*/
public LoginBean setTranslator(Translator translator) {
this.translator = translator;
return this;
}
/**
*
* @return l'utilisateur connecté
@@ -15,6 +15,7 @@ import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Game;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
public class NewGameBean implements Serializable {
@@ -26,6 +27,7 @@ public class NewGameBean implements Serializable {
private String timer;
private String nbValues;
private String nbColors;
private Translator translator;
private Game game;
@@ -59,10 +61,10 @@ public class NewGameBean implements Serializable {
entityManager.getTransaction().commit();
return true;
} catch (NumberFormatException e) {
error = new HttpResponse(HttpResponseCode.BAD_REQUEST, "Les valeurs entrées ne sont pas valides");
error = new HttpResponse(HttpResponseCode.BAD_REQUEST, translator.translate("newGame_invalid_param_values"));
} catch (DAOException e) {
entityManager.getTransaction().rollback();
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, "Erreur lors de la création de la partie");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, translator.translate("newGame_error_creation"));
}
return false;
}
@@ -117,6 +119,15 @@ public class NewGameBean implements Serializable {
return this;
}
/**
*
* @param translator le traducteur
* @return l'entité
*/
public NewGameBean setTranslator(Translator translator) {
this.translator = translator;
return this;
}
/**
*
* @return la partie créée
@@ -11,6 +11,7 @@ import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Player;
import uppa.project.web.translation.Translator;
public class PlayerBean {
private Player player;
@@ -19,6 +20,7 @@ public class PlayerBean {
this.player = player;
}
/**
* Gestion des joueurs de la parties
*
@@ -13,6 +13,7 @@ import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
public class ProfileBean {
private String username;
@@ -23,6 +24,7 @@ public class ProfileBean {
private String gender;
private User user;
private HttpResponse error;
private Translator translator;
public ProfileBean() {}
@@ -40,25 +42,25 @@ public class ProfileBean {
// Vérification de l'existence de l'utilisateur
user = (userDAO.findByField("username",username).length == 0 ? null : userDAO.findByField("username",username)[0]);
if (user == null) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Utilisateur non trouvé");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("profile_error_username_unknown"));
entityManager.getTransaction().rollback();
return false;
}
// Vérification de l'unicité de l'adresse e-mail
User[] users = userDAO.findByField("email", email);
if (!oldEmail.equals(email) && users.length > 0) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Cet email est déjà utilisé");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("profile_error_email"));
entityManager.getTransaction().rollback();
return false;
}
// Verification de l'ancien mot de passe
if(!oldPassword.isEmpty() && !user.verifyPassword(oldPassword)) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Ancien mot de passe incorrect");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("profile_error_old_password"));
entityManager.getTransaction().rollback();
return false;
}
} catch (DAOException e) {
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, "Une erreur est survenue (DB_CONNECTION_ERROR:002)");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, translator.translate("internal_error_2"));
entityManager.getTransaction().rollback();
return false;
}
@@ -73,7 +75,7 @@ public class ProfileBean {
entityManager.getTransaction().commit();
return true;
} catch (DAOException e) {
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, "Une erreur est survenue (DB_CONNECTION_ERROR:002)");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, translator.translate("internal_error_2"));
entityManager.getTransaction().rollback();
return false;
}
@@ -139,6 +141,16 @@ public class ProfileBean {
return this;
}
/**
*
* @param translator le traducteur
* @return l'entité
*/
public ProfileBean setTranslator(Translator translator) {
this.translator = translator;
return this;
}
/**
*
* @return l'erreur
@@ -13,6 +13,7 @@ import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
public class RegisterBean implements Serializable {
@@ -26,6 +27,7 @@ public class RegisterBean implements Serializable {
private String gender;
private HttpResponse error;
private Translator translator;
public RegisterBean() {
}
@@ -46,18 +48,18 @@ public class RegisterBean implements Serializable {
// Vérification de l'unicité du nom d'utilisateur
User[] users = userDAO.findByField("username", username);
if (users.length > 0) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Ce nom d'utilisateur est déjà pris");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("register_error_username"));
return false;
}
// Vérification de l'unicité de l'adresse e-mail
users = userDAO.findByField("email", email);
if (users.length > 0) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Cet email est déjà utilisé");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("register_error_email"));
return false;
}
} catch (DAOException e) {
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, "Une erreur est survenue (DB_CONNECTION_ERROR:001)");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, translator.translate("internal_error_1"));
return false;
}
@@ -69,7 +71,7 @@ public class RegisterBean implements Serializable {
try {
user.setGender(User.Gender.valueOf(gender));
} catch (IllegalArgumentException e) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "Le genre n'est pas valide");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("register_error_gender"));
return false;
}
@@ -80,7 +82,7 @@ public class RegisterBean implements Serializable {
Date date = Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
user.setBirth(date);
} catch (Exception e) {
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "La date de naissance n'est pas valide");
error = new HttpResponse(HttpResponseCode.UNAUTHORIZED, translator.translate("register_error_birthdate"));
return false;
}
@@ -93,7 +95,7 @@ public class RegisterBean implements Serializable {
entityManager.getTransaction().commit();
return true;
} catch (DAOException e) {
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, "Une erreur est survenue (DB_CONNECTION_ERROR:002)");
error = new HttpResponse(HttpResponseCode.INTERNAL_SERVER_ERROR, translator.translate("internal_error_2"));
entityManager.getTransaction().rollback();
}
return false;
@@ -149,6 +151,16 @@ public class RegisterBean implements Serializable {
return this;
}
/**
*
* @param translator le traducteur
* @return l'entité
*/
public RegisterBean setTranslator(Translator translator) {
this.translator = translator;
return this;
}
/**
*
* @return l'erreur
@@ -9,6 +9,7 @@ import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import uppa.project.web.translation.Translator;
public class ResetPasswordBean implements Serializable {
@@ -18,6 +19,7 @@ public class ResetPasswordBean implements Serializable {
private String token;
private String password;
private String errorMessage;
private Translator translator;
public ResetPasswordBean() {
}
@@ -85,6 +87,16 @@ public class ResetPasswordBean implements Serializable {
return this;
}
/**
*
* @param translator le traducteur
* @return this
*/
public ResetPasswordBean setTranslator(Translator translator) {
this.translator = translator;
return this;
}
/**
*
* @return le message d'erreur
@@ -18,10 +18,8 @@ import java.io.PrintWriter;
import uppa.project.bean.ForgottenPasswordBean;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_User;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
@@ -58,6 +56,7 @@ public class ForgottenPasswordServlet extends HttpServlet {
* @throws IOException si une erreur d'entrée/sortie survient
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
Translator translator = (Translator) request.getSession().getAttribute("translator");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
@@ -73,7 +72,7 @@ public class ForgottenPasswordServlet extends HttpServlet {
if (forgottenPasswordBean.validate(uri)) {
httpResponse = new HttpResponse(HttpResponseCode.OK, "Mail sent");
} else {
httpResponse = new HttpResponse(HttpResponseCode.NOT_FOUND, "L'email renseigné est inconnu de nos services.");
httpResponse = new HttpResponse(HttpResponseCode.NOT_FOUND, translator.translate("forgotten_error_email"));
}
out.println(gson.toJson(httpResponse));
@@ -16,6 +16,7 @@ import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Game;
import uppa.project.web.translation.Translator;
@WebServlet(name = "gameServlet", value = "/game")
public class GameServlet extends HttpServlet {
@@ -32,6 +33,10 @@ public class GameServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
try {
DAO<Game> gameDAO = new Game_JPA_DAO_Factory().getDAOGame();
Game game = gameDAO.findById(Integer.parseInt(request.getParameter("id")));
@@ -11,6 +11,7 @@ import uppa.project.database.dao.DAO;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.web.translation.Translator;
@WebServlet(name = "game-statistics", value = "/game-statistics")
public class GameStatisticsServlet extends HttpServlet {
@@ -27,6 +28,10 @@ public class GameStatisticsServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
Game game;
try {
DAO<Game> gameDAO = new Game_JPA_DAO_Factory().getDAOGame();
@@ -12,6 +12,7 @@ import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import uppa.project.web.translation.Translator;
@WebServlet(name = "indexServlet", value = "/index")
public class IndexServlet extends HttpServlet {
@@ -28,6 +29,10 @@ public class IndexServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
request.setAttribute("current", "index");
request.getRequestDispatcher("/WEB-INF/pages/index.jsp").forward(request, response);
}
@@ -19,6 +19,7 @@ import java.util.Set;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import uppa.project.web.translation.Translator;
@WebServlet(name = "lobbyServlet", value = "/lobby")
public class LobbyServlet extends HttpServlet {
@@ -35,6 +36,10 @@ public class LobbyServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
request.getRequestDispatcher("/WEB-INF/pages/lobby.jsp").forward(request, response);
}
@@ -50,6 +50,7 @@ public class LoginServlet extends HttpServlet {
* @throws IOException si une erreur d'entrée/sortie survient
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
Translator translator = (Translator) request.getSession().getAttribute("translator");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
@@ -57,6 +58,7 @@ public class LoginServlet extends HttpServlet {
LoginBean loginBean = new LoginBean()
.setUsername(request.getParameter("username"))
.setPassword(request.getParameter("password"))
.setTranslator(translator)
;
Gson gson = new Gson();
@@ -18,6 +18,7 @@ import uppa.project.bean.NewGameBean;
import uppa.project.database.pojo.Game;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
@WebServlet(name = "newGameServlet", value = "/new")
public class NewGameServlet extends HttpServlet {
@@ -34,6 +35,10 @@ public class NewGameServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
request.getRequestDispatcher("/WEB-INF/pages/new-game.jsp").forward(request, response);
}
@@ -44,7 +49,7 @@ public class NewGameServlet extends HttpServlet {
* @param response la réponse
* @throws IOException si une erreur d'entrée/sortie survient
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
Gson gson = new Gson();
response.setContentType("application/json");
@@ -22,6 +22,7 @@ import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
import uppa.project.web.translation.Translator;
@WebServlet(name = "profileServlet", value = "/profile")
public class ProfileServlet extends HttpServlet {
@@ -38,13 +39,15 @@ public class ProfileServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
User usersession = (User) request.getSession().getAttribute("user");
DAO<User> userDAO;
try {
userDAO = new Game_JPA_DAO_Factory().getDAOUser();
User user = userDAO.findById(usersession.getId().intValue());
for(Player p : user.getPlayedGames()){
}
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/pages/profile.jsp").forward(request, response);
} catch (DAOException e) {
@@ -6,6 +6,7 @@ import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import uppa.project.web.translation.Translator;
@WebServlet(name = "rulesServlet", value = "/rules")
public class RulesServlet extends HttpServlet {
@@ -21,6 +22,10 @@ public class RulesServlet extends HttpServlet {
* @throws ServletException si une erreur de servlet survient
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("translator") == null) {
request.getSession().setAttribute("language", "FR");
request.getSession().setAttribute("translator", Translator.generateTranslator(request.getSession(), request.getServletContext()));
}
request.getRequestDispatcher("/WEB-INF/pages/rules.jsp").forward(request, response);
}
public void destroy() {
@@ -13,7 +13,7 @@ public class Translator {
private final String language;
private JsonParser parser;
private final JsonParser parser;
private JsonObject translations;
@@ -2,7 +2,6 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<% Translator translator = (Translator) request.getSession().getAttribute("translator"); %>
<layout:error message="${translator.translate('invalid_token')}">
@@ -1,10 +1,12 @@
<%@ page import="uppa.project.web.translation.Translator" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<% Translator translator = (Translator) request.getSession().getAttribute("translator"); %>
<layout:base title="Profil">
<layout:base title="${translator.translate('profile_title')}">
<jsp:attribute name="head">
<link rel="stylesheet" href="${pageContext.request.contextPath}/static/css/form.css"/>
<script defer type="module" src="${pageContext.request.contextPath}/static/js/form/profile.js"></script>
@@ -13,7 +15,7 @@
<component:hero>
<div class="columns is-centered">
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<component:card title="Profil">
<component:card title="${translator.translate('profile_title')}">
<fieldset>
<form:profile/>
</fieldset>
@@ -22,7 +24,7 @@
</div>
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<component:card title="Statistiques">
<component:card title="${translator.translate('statistics_title')}">
<component:statistics/>
</component:card>
</div>
@@ -1,3 +1,5 @@
<%@ tag import="uppa.project.web.translation.Translator" %>
<% Translator translator = (Translator) request.getSession().getAttribute("translator"); %>
<%@ tag import="uppa.project.database.pojo.Player" %>
<%@ tag import="uppa.project.database.pojo.Game" %>
<%@ tag import="java.util.ArrayList" %>
@@ -1,41 +1,44 @@
<%@ tag import="uppa.project.database.pojo.Player" %>
<%@ tag import="uppa.project.web.translation.Translator" %>
<%@tag description="component/statistics" pageEncoding="UTF-8" %>
<% Translator translator = (Translator) request.getSession().getAttribute("translator"); %>
<jsp:useBean id="user" class="uppa.project.database.pojo.User" scope="session"/>
<h4 class="title is-4">Statistiques globales</h4>
<h4 class="title is-4">${translator.translate("global_statistics")}</h4>
<div class="level">
<div class="level-item has-text-centered">
<div>
<p class="heading">Parties</p>
<p class="heading">${translator.translate("global_statistics_game")}</p>
<p class="title">${user.nbPlayedGame}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Victoires</p>
<p class="heading">${translator.translate("global_statistics_win")}</p>
<p class="title">${user.nbWin}</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Clics corrects</p>
<p class="heading">${translator.translate("global_statistics_corrects_clics")}</p>
<p class="title">${user.rightClickPercentRate}%</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Clics rapides</p>
<p class="heading">${translator.translate("global_statistics_rapid_clics")}</p>
<p class="title">${user.rapidClickPercentRate}%</p>
</div>
</div>
</div>
<h4 class="title is-4">Parties jouées </h4>
<h4 class="title is-4">${translator.translate("statistics_games_played")} </h4>
<table class="table is-fullwidth">
<thead>
<tr>
<th>Date</th>
<th>Score</th>
<th>Vainqueur</th>
<th>${translator.translate("statistics_game_date")}</th>
<th>${translator.translate("statistics_game_score")}</th>
<th>${translator.translate("statistics_game_winner")}</th>
<th></th>
</tr>
</thead>
@@ -47,7 +50,7 @@
<td><%= player.getGame().getCreatedAt().toLocaleString() %></td>
<td><%= player.getScore() %></td>
<td><%= player.getGame().getWinner().getUser().getUsername() %></td>
<td><a href="${pageContext.request.contextPath}/game-statistics?id=<%= player.getGame().getId() %>">Voir</a></td>
<td><a href="${pageContext.request.contextPath}/game-statistics?id=<%= player.getGame().getId() %>">${translator.translate("statistics_game_show")}</a></td>
</tr>
<% } %>
</tbody>
@@ -1,17 +1,19 @@
<%@ tag import="uppa.project.database.pojo.User" %>
<%@tag description="form/profile" pageEncoding="UTF-8" %>
<%@ tag import="uppa.project.web.translation.Translator" %>
<% Translator translator = (Translator) request.getSession().getAttribute("translator"); %>
<form id="profile-form" action="${pageContext.request.contextPath}/profile" method="post">
<jsp:useBean id="user" class="uppa.project.database.pojo.User" scope="session"/>
<div class="field">
<label class="label" for="username">Nom d'utilisateur</label>
<label class="label" for="username">${translator.translate('user_username')}</label>
<div class="control has-icons-left">
<input id="username" name="username" value="${user.username}" type="text" class="input is-fullwidth" disabled/>
<span class="icon is-left"><i class="fas fa-user"></i></span>
</div>
</div>
<div class="field">
<label class="label" for="email">Email</label>
<label class="label" for="email">${translator.translate('user_username')}</label>
<div class="control has-icons-left">
<input id="old-email" name="oldEmail" type="hidden" value="${user.email}" class="input is-fullwidth" required>
<input id="email" name="email" type="email" value="${user.email}" class="input is-fullwidth" required>
@@ -19,56 +21,56 @@
</div>
</div>
<div class="field">
<label class="label">Mot de passe</label>
<a id="change-password" href="#">Changer le mot de passe</a>
<label class="label">${translator.translate('user_password')}</label>
<a id="change-password" href="#">${translator.translate('user_update_password')}</a>
</div>
<div id="old-password-field" class="field" style="display: none">
<div class="control has-icons-left">
<input id="old-password" name="oldPassword" placeholder="Ancien mot de passe" type="password" class="input is-fullwidth">
<input id="old-password" name="oldPassword" placeholder="${translator.translate('user_old_password')}" type="password" class="input is-fullwidth">
<span class="icon is-left"><i class="fas fa-lock"></i></span>
</div>
</div>
<div id="password-field" class="field" style="display: none">
<div class="control has-icons-left">
<input id="password" name="password" placeholder="Nouveau mot de passe" type="password" class="input is-fullwidth">
<input id="password" name="password" placeholder="${translator.translate('user_new_password')}" type="password" class="input is-fullwidth">
<span class="icon is-left"><i class="fas fa-lock"></i></span>
</div>
</div>
<div id="repeat-password-field" class="field" style="display: none">
<div class="control has-icons-left">
<input id="repeat-password" name="repeat-password" placeholder="Confirmer le mot de passe" type="password" class="input is-fullwidth">
<input id="repeat-password" name="repeat-password" placeholder="${translator.translate('user_confirm_password')}" type="password" class="input is-fullwidth">
<span class="icon is-left"><i class="fas fa-lock"></i></span>
</div>
</div>
<div class="field">
<label class="label">Date de naissance</label>
<label class="label">${translator.translate('user_birthdate')}</label>
<input class="input" type="text" value="${user.birth.toLocaleString()}" disabled>
</div>
<div class="field">
<label class="label" for="gender">Genre</label>
<label class="label" for="gender">${translator.translate('user_gender')}</label>
<div class="control has-icons-left">
<div class="select is-fullwidth">
<input id="old-gender" name="oldGender" type="hidden" value="${user.gender.name()}" class="input is-fullwidth" required>
<select name="gender" id="gender" required>
<% if (user.getGender() == null) { %>
<option selected value="">- Choisissez une option -</option>
<option selected value="">-- ${translator.translate('user_gender_select_option')} --</option>
<% } else { %>
<option value="">- Choisissez une option -</option>
<option value="">-- ${translator.translate('user_gender_select_option')} --</option>
<% } %>
<% if (user.getGender().equals(User.Gender.MALE)) {%>
<option selected value="MALE">Homme</option>
<option selected value="MALE">${translator.translate('user_gender_male')}</option>
<% } else { %>
<option value="MALE">Homme</option>
<option value="MALE">${translator.translate('user_gender_male')}</option>
<% } %>
<% if (user.getGender().equals(User.Gender.FEMALE)) {%>
<option selected value="FEMALE">Femme</option>
<option selected value="FEMALE">${translator.translate('user_gender_female')}</option>
<% } else { %>
<option value="FEMALE">Femme</option>
<option value="FEMALE">${translator.translate('user_gender_female')}</option>
<% } %>
<% if (user.getGender().equals(User.Gender.OTHER)) {%>
<option selected value="OTHER">Autre</option>
<option selected value="OTHER">${translator.translate('user_gender_other')}</option>
<% } else { %>
<option value="OTHER">Autre</option>
<option value="OTHER">${translator.translate('user_gender_other')}</option>
<% } %>
</select>
</div>
@@ -82,9 +84,9 @@
<span class="icon">
<i class="fa-solid fa-arrow-left"></i>
</span>
<span>Retour</span>
<span>${translator.translate('back')}</span>
</a>
<input type="submit" id="modify" class="button is-primary is-light" value="Modifier">
<input type="submit" id="modify" class="button is-primary is-light" value="${translator.translate('profile_edit')}">
</div>
</div>
</form>
@@ -35,6 +35,18 @@
"EN": "Email",
"FR": "Email"
},
"user_old_password" : {
"EN": "Old password",
"FR": "Ancien mot de passe"
},
"user_new_password" : {
"EN": "New password",
"FR": "Nouveau mot de passe"
},
"user_update_password" : {
"EN": "Modify password",
"FR": "Changer à jour le mot de passe"
},
"user_confirm_password" : {
"EN": "Confirm Password",
"FR": "Confirmer le mot de passe"
@@ -95,112 +107,196 @@
"EN": "Register",
"FR": "S'inscrire"
},
"register_submit" : {
"EN": "Register",
"FR": "S'inscrire"
},
"register_already_registered" : {
"EN": "Already registered?",
"FR": "Déjà inscrit?"
},
"register_login" : {
"EN": "Login now!",
"FR": "Se connecter"
},
"register_error_username" : {
"EN": "Username already taken",
"FR": "Nom d'utilisateur déjà pris"
},
"register_error_email" : {
"EN": "Email already taken",
"FR": "Email déjà utilisé"
},
"register_error_password" : {
"EN": "Passwords do not match",
"FR": "Les mots de passe ne correspondent pas"
},
"forgotten_title" : {
"EN": "Forgotten password ?",
"FR": "Mot de passe oublié ?"
},
"forgotten_submit" : {
"EN": "Send email",
"FR": "Envoyer l'email"
},
"forgotten_error" : {
"EN": "The email entered is not associated with any account",
"FR": "L'email renseigné n'est associé à aucun compte"
},
"forgotten_success" : {
"EN": "Email sent successfully",
"FR": "Email envoyé avec succès"
},
"forgotten_email_description" : {
"EN": "Enter the email address associated with your account to receive a password reset link.",
"FR": "Entrez l'adresse email associée à votre compte pour recevoir un lien de réinitialisation de mot de passe."
},
"forgotten_email_object" : {
"EN": "Reset password",
"FR": "Réinitialiser le mot de passe"
},
"forgotten_email_content" : {
"EN": "Hello,\n\nYou have requested a password reset.\nTo do this, please click on the following link: {0}/reset-password?token={1}\n\nThis link is valid for 10 minutes.\nIf you are not the origin of this request, please ignore this email.\n\nSincerely,\nThe CardRush team\n\n\n\nThis message is generated automatically, please do not reply to it.\nCardRush is the property of CardRush Corporation, 2024. All rights reserved.\nCardRush Corporation, 2024, 1 rue de la programmation web, 64000 Pau, France\nFictitious company created as part of a university project. Project authors: MITRESSÉ Kevin & VABRE Lucàs",
"FR": "Bonjour,\n\nVous avez demandé la réinitialisation de votre mot de passe.\nPour cela, veuillez cliquer sur le lien suivant :{0}/reset-password?token={1}\n\nCe lien est valable 10 minutes.\nSi vous n'êtes pas à l'origine de cette demande, ne prenez pas compte de ce mail.\n\nCordialement,\nL'équipe CardRush\n\n\n\nCe message est généré automatiquement, merci de ne pas y répondre.\nCardRush est la propriété de CardRush Corporation, 2024. Tous droits réservés.\\nCardRush Corporation, 2024, 1 rue de la programmation web, 64000 Pau, France\nSociété fictive créée dans le cadre d'un projet universitaire. Auteurs du projet: MITRESSÉ Kevin & VABRE Lucàs"
},
"reset_title" : {
"EN": "Reset password",
"FR": "Réinitialisation du mot de passe"
},
"reset_submit" : {
"EN": "Reset",
"FR": "Réinitialiser"
},
"invalid_token" : {
"EN": "Invalid token",
"FR": "Token invalide"
},
"expired_token" : {
"EN": "Expired token",
"FR": "Token expiré"
},
"error_token_go_to_connection_page" :{
"EN": "Return to the login page",
"FR": "Retour à la page de connexion"
},
"error" : {
"EN": "Error",
"FR": "Erreur"
"register_submit" : {
"EN": "Register",
"FR": "S'inscrire"
},
"register_already_registered" : {
"EN": "Already registered?",
"FR": "Déjà inscrit?"
},
"register_login" : {
"EN": "Login now!",
"FR": "Se connecter"
},
"register_error_username" : {
"EN": "Username already taken",
"FR": "Nom d'utilisateur déjà pris"
},
"register_error_email" : {
"EN": "Email already taken",
"FR": "Email déjà utilisé"
},
"register_error_password" : {
"EN": "Passwords do not match",
"FR": "Les mots de passe ne correspondent pas"
},
"register_error_gender" : {
"EN": "Gender is not valid",
"FR": "Le genre n'est pas valide"
},
"register_error_birthdate" : {
"EN": "Birthdate is not valid",
"FR": "La date de naissance n'est pas valide"
},
"forgotten_title" : {
"EN": "Forgotten password ?",
"FR": "Mot de passe oublié ?"
},
"forgotten_submit" : {
"EN": "Send email",
"FR": "Envoyer l'email"
},
"forgotten_error_email" : {
"EN": "The email entered is not associated with any account",
"FR": "L'email renseigné n'est associé à aucun compte"
},
"forgotten_success" : {
"EN": "Email sent successfully",
"FR": "Email envoyé avec succès"
},
"forgotten_email_description" : {
"EN": "Enter the email address associated with your account to receive a password reset link.",
"FR": "Entrez l'adresse email associée à votre compte pour recevoir un lien de réinitialisation de mot de passe."
},
"forgotten_email_object" : {
"EN": "Reset password",
"FR": "Réinitialiser le mot de passe"
},
"forgotten_email_content" : {
"EN": "Hello,\n\nYou have requested a password reset.\nTo do this, please click on the following link: {0}/reset-password?token={1}\n\nThis link is valid for 10 minutes.\nIf you are not the origin of this request, please ignore this email.\n\nSincerely,\nThe CardRush team\n\n\n\nThis message is generated automatically, please do not reply to it.\nCardRush is the property of CardRush Corporation, 2024. All rights reserved.\nCardRush Corporation, 2024, 1 rue de la programmation web, 64000 Pau, France\nFictitious company created as part of a university project. Project authors: MITRESSÉ Kevin & VABRE Lucàs",
"FR": "Bonjour,\n\nVous avez demandé la réinitialisation de votre mot de passe.\nPour cela, veuillez cliquer sur le lien suivant :{0}/reset-password?token={1}\n\nCe lien est valable 10 minutes.\nSi vous n'êtes pas à l'origine de cette demande, ne prenez pas compte de ce mail.\n\nCordialement,\nL'équipe CardRush\n\n\n\nCe message est généré automatiquement, merci de ne pas y répondre.\nCardRush est la propriété de CardRush Corporation, 2024. Tous droits réservés.\\nCardRush Corporation, 2024, 1 rue de la programmation web, 64000 Pau, France\nSociété fictive créée dans le cadre d'un projet universitaire. Auteurs du projet: MITRESSÉ Kevin & VABRE Lucàs"
},
"reset_title" : {
"EN": "Reset password",
"FR": "Réinitialisation du mot de passe"
},
"reset_submit" : {
"EN": "Reset",
"FR": "Réinitialiser"
},
"invalid_token" : {
"EN": "Invalid token",
"FR": "Token invalide"
},
"expired_token" : {
"EN": "Expired token",
"FR": "Token expiré"
},
"error_token_go_to_connection_page" :{
"EN": "Return to the login page",
"FR": "Retour à la page de connexion"
},
"error" : {
"EN": "Error",
"FR": "Erreur"
},
"reset_success" : {
"EN": "Password reset successfully",
"FR": "Mot de passe réinitialisé avec succès"
},
"reset_password" : {
"EN": "New password",
"FR": "Nouveau mot de passe"
},
"reset_confirm_password" : {
"EN": "Confirm new password",
"FR": "Confirmer le nouveau mot de passe"
},
"reset_password_description" : {
"EN": "Enter your new password",
"FR": "Entrez votre nouveau mot de passe"
},
"reset_error_password" : {
"EN": "Passwords do not match",
"FR": "Les mots de passe ne correspondent pas"
},
"profile_title" : {
"EN": "Profile",
"FR": "Profil"
},
"profile_edit" : {
"EN": "Edit",
"FR": "Modifier"
},
"profile_error_username_unknown" : {
"EN": "Unknown username",
"FR": "Nom d'utilisateur inconnu"
},
"profile_error_email" : {
"EN": "Email already taken",
"FR": "Email déjà utilisé"
},
"profile_error_old_password" : {
"EN": "Incorrect old password",
"FR": "Ancien mot de passe incorrect"
},
"statistics_title" : {
"EN": "Statistics",
"FR": "Statistiques"
},
"reset_success" : {
"EN": "Password reset successfully",
"FR": "Mot de passe réinitialisé avec succès"
},
"reset_password" : {
"EN": "New password",
"FR": "Nouveau mot de passe"
},
"reset_confirm_password" : {
"EN": "Confirm new password",
"FR": "Confirmer le nouveau mot de passe"
},
"reset_password_description" : {
"EN": "Enter your new password",
"FR": "Entrez votre nouveau mot de passe"
},
"reset_error_password" : {
"EN": "Passwords do not match",
"FR": "Les mots de passe ne correspondent pas"
},
"profile_title" : {
"EN": "Profile",
"FR": "Profil"
},
"profile_edit" : {
"EN": "Edit",
"FR": "Modifier"
}
"global_statistics" : {
"EN": "Global statistics",
"FR": "Statistiques globales"
},
"global_statistics_game" : {
"EN": "Games",
"FR": "Parties"
},
"global_statistics_win" : {
"EN": "Wins",
"FR": "Victoires"
},
"global_statistics_corrects_clics": {
"EN": "Corrects clics",
"FR": "Clics corrects"
},
"global_statistics_rapid_clics": {
"EN": "Rapid clics",
"FR": "Clics rapides"
},
"statistics_games_played" : {
"EN": "Games played",
"FR": "Parties jouées"
},
"statistics_game_date" : {
"EN": "Date",
"FR": "Date"
},
"statistics_game_score" : {
"EN": "Score",
"FR": "Score"
},
"statistics_game_winner" : {
"EN": "Winner",
"FR": "Vainqueur"
},
"statistics_game_show" : {
"EN": "Show",
"FR": "Voir"
},
"internal_error_1" : {
"EN": "An error occurred (DB_CONNECTION_ERROR:001)",
"FR": "Une erreur est survenue (DB_CONNECTION_ERROR:001)"
},
"internal_error_2" : {
"EN": "An error occurred (DB_CONNECTION_ERROR:002)",
"FR": "Une erreur est survenue (DB_CONNECTION_ERROR:002)"
},
"newGame_invalid_param_values" : {
"EN": "The values entered are not valid",
"FR": "Les valeurs entrées ne sont pas valides"
},
"newGame_error_creation" : {
"EN": "An error occurred during the creation of the game",
"FR": "Une erreur est survenue lors de la création de la partie"
},
"back" : {
"EN": "Back",
"FR": "Retour"
}
}
@@ -1,13 +1,13 @@
import {onError} from "../notification/error.js";
import {onSuccess} from "../notification/success.js";
import {Success} from "../notification/success.js";
const languageSelector = document.getElementById('language-select');
const profileForm = document.querySelector("form#profile-form");
const username = profileForm.querySelector("input[name='username']");
const changePassword = profileForm.querySelector("a#change-password");
const passwordFields = profileForm.querySelectorAll("div#old-password-field, div#password-field, div#repeat-password-field");
const inputs = profileForm.querySelectorAll("input[type='text'], input[type='email'], input[type='password']");
// Afficher les champs de mot de passe si le lien est cliqué
changePassword.addEventListener("click", (e) => {
e.preventDefault();
@@ -26,6 +26,10 @@ function onSubmit(event) {
const repassword = profileForm.querySelector("input[name='repeat-password']");
// Check if the password and the confirmation password are the same
if (oldPassword.value !== "" && password.value !== repassword.value) {
if (languageSelector.value === "EN") {
onError(new Error("Passwords do not match"), [oldPassword, password, repassword]);
return;
}
onError(new Error("Les mots de passe ne correspondent pas"), [oldPassword, password, repassword]);
return;
}
@@ -33,8 +37,6 @@ function onSubmit(event) {
const {action, method} = profileForm;
const url = new URL(action);
const contextPath = url.href.substring(0, url.href.lastIndexOf("/") + 1);
const formData = new FormData(profileForm);
for (const [key, value] of formData.entries()) {
url.searchParams.append(key, value);
@@ -1,4 +1,5 @@
import {onError} from "../notification/error.js";
const languageSelector = document.getElementById('language-select');
const registerForm = document.querySelector("form#register-form");
@@ -14,7 +15,11 @@ function onSubmit(event) {
// Check if the password and the confirmation password are the same
if (password.value !== repassword.value) {
onError( new Error("Les mots de passe ne correspondent pas"),[password, repassword]);
if (languageSelector.value === "EN") {
onError(new Error("Passwords do not match"), [oldPassword, password, repassword]);
return;
}
onError(new Error("Les mots de passe ne correspondent pas"), [oldPassword, password, repassword]);
return;
}
@@ -1,4 +1,5 @@
import {onError} from "../notification/error.js";
const languageSelector = document.getElementById('language-select');
const resetPasswordForm = document.querySelector("form#reset-password-form");
const submitButton = document.querySelector("input[type=submit]");
@@ -15,7 +16,11 @@ function onSubmit(event) {
// Check if the password and the confirmation password are the same
if (passwordInput.value !== repasswordInput.value) {
onError(new Error("Les mots de passe ne correspondent pas"), inputs);
if (languageSelector.value === "EN") {
onError(new Error("Passwords do not match"), [oldPassword, password, repassword]);
return;
}
onError(new Error("Les mots de passe ne correspondent pas"), [oldPassword, password, repassword]);
return;
}
@@ -1,5 +1,7 @@
export function onError(error, inputs) {
// Animations des champs
const languageSelector = document.getElementById('language-select');
inputs.forEach(input => {
input.classList.add("is-danger");
input.style.animation = "shake 0.5s ease-in-out"
@@ -11,7 +13,11 @@ export function onError(error, inputs) {
const notificationTitle = document.createElement("p");
notificationTitle.classList.add("title", "is-6");
notificationTitle.innerHTML = "Erreur";
if (languageSelector.value === "EN") {
notificationTitle.innerHTML = "Error";
} else {
notificationTitle.innerHTML = "Erreur";
}
const notificationIcon = document.createElement("span");
notificationIcon.classList.add("icon");
@@ -32,4 +38,4 @@ export function onError(error, inputs) {
inputs.forEach(input => input.classList.remove("is-danger"));
}, 5010);
inputs.forEach(input => input.addEventListener("animationend", () => input.style.animation = ""));
};
}
@@ -1,4 +1,9 @@
export class Success {
static successLabels = {
EN: "Success",
FR: "Succès",
}
static successKeys = {
FORGOTTEN_PASSWORD: "forgotten-password",
RESET_PASSWORD: "reset-password",
@@ -7,13 +12,22 @@ export class Success {
}
static successValues = {
FORGOTTEN_PASSWORD: "Un email vous a été envoyé pour réinitialiser votre mot de passe",
RESET_PASSWORD: "Mot de passe récupéré avec succès",
UPDATE_PROFILE: "Profil modifié avec succès",
CREATE_ACCOUNT: "Compte créé avec succès",
EN: {
FORGOTTEN_PASSWORD: "An email has been sent to you to reset your password",
RESET_PASSWORD: "Password successfully recovered",
UPDATE_PROFILE: "Profile successfully modified",
CREATE_ACCOUNT: "Account successfully created",
},
FR: {
FORGOTTEN_PASSWORD: "Un email vous a été envoyé pour réinitialiser votre mot de passe",
RESET_PASSWORD: "Mot de passe récupéré avec succès",
UPDATE_PROFILE: "Profil modifié avec succès",
CREATE_ACCOUNT: "Compte créé avec succès",
}
}
}
export function onSuccess(message) {
export function onSuccess(title, message) {
console.log("Succès:", "Modifications effectuées avec succès")
// Notification
@@ -40,18 +54,36 @@ export function onSuccess(message) {
setTimeout(() => notification.remove(), 5010);
}
export function verifSuccess(){
export function verifSuccess() {
const languageSelector = document.getElementById('language-select');
const url = new URL(window.location.href);
if (url.searchParams.get("success")!=undefined && url.searchParams.get("success") === Success.successKeys.FORGOTTEN_PASSWORD) {
onSuccess(Success.successValues.FORGOTTEN_PASSWORD)
if (url.searchParams.get("success") !== undefined && url.searchParams.get("success") === Success.successKeys.FORGOTTEN_PASSWORD) {
if (languageSelector.value === "EN") {
onSuccess(Success.successLabels.EN, Success.successValues.EN.FORGOTTEN_PASSWORD)
} else {
onSuccess(Success.successLabels.FR, Success.successValues.FR.FORGOTTEN_PASSWORD)
}
}
if (url.searchParams.get("success")!=undefined && url.searchParams.get("success") === Success.successKeys.RESET_PASSWORD) {
onSuccess(Success.successValues.RESET_PASSWORD)
}
if (url.searchParams.get("success")!=undefined && url.searchParams.get("success") === Success.successKeys.CREATE_ACCOUNT) {
onSuccess(Success.successValues.CREATE_ACCOUNT)
}
if (url.searchParams.get("success")!=undefined && url.searchParams.get("success") === Success.successKeys.UPDATE_PROFILE) {
onSuccess(Success.successValues.UPDATE_PROFILE)
if (url.searchParams.get("success") !== undefined && url.searchParams.get("success") === Success.successKeys.RESET_PASSWORD) {
if (languageSelector.value === "EN") {
onSuccess(Success.successLabels.EN, Success.successValues.EN.RESET_PASSWORD)
} else {
onSuccess(Success.successLabels.FR, Success.successValues.FR.RESET_PASSWORD)
}
if (url.searchParams.get("success") !== undefined && url.searchParams.get("success") === Success.successKeys.CREATE_ACCOUNT) {
if (languageSelector.value === "EN") {
onSuccess(Success.successLabels.EN, Success.successValues.EN.CREATE_ACCOUNT)
} else {
onSuccess(Success.successLabels.FR, Success.successValues.FR.CREATE_ACCOUNT)
}
}
if (url.searchParams.get("success") !== undefined && url.searchParams.get("success") === Success.successKeys.UPDATE_PROFILE) {
if (languageSelector.value === "EN") {
onSuccess(Success.successLabels.EN, Success.successValues.EN.UPDATE_PROFILE)
} else {
onSuccess(Success.successLabels.FR, Success.successValues.FR.UPDATE_PROFILE)
}
}
}
}