From c5866de78e2726d7ad16d909eaafa0c1ea217984 Mon Sep 17 00:00:00 2001 From: Luigi Date: Wed, 17 Jan 2024 21:17:23 +0100 Subject: [PATCH 1/3] userReport page and function --- .../controller/AddRemovePatientCondition.java | 2 +- src/main/java/model/DAO/DAOExercise.java | 49 ++++++++++ .../service/exercise/ExerciseManager.java | 6 ++ src/main/webapp/JSP/userReport.jsp | 92 +++++++++++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/JSP/userReport.jsp diff --git a/src/main/java/controller/AddRemovePatientCondition.java b/src/main/java/controller/AddRemovePatientCondition.java index 8e61ed4..f8675f9 100644 --- a/src/main/java/controller/AddRemovePatientCondition.java +++ b/src/main/java/controller/AddRemovePatientCondition.java @@ -11,7 +11,7 @@ @WebServlet("/AddRemovePatientCondition") public class AddRemovePatientCondition extends HttpServlet { - +//mammt protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { String referer = request.getHeader("Referer"); ConditionManager conditionService= new ConditionManager(); diff --git a/src/main/java/model/DAO/DAOExercise.java b/src/main/java/model/DAO/DAOExercise.java index 5a8aa54..2f9cf06 100644 --- a/src/main/java/model/DAO/DAOExercise.java +++ b/src/main/java/model/DAO/DAOExercise.java @@ -6,7 +6,9 @@ import java.sql.*; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * The DAOExercise class provides methods for retrieving Exercise information from a database. @@ -464,5 +466,52 @@ public boolean deleteMultipleExercise(int userId){ } } + public Map retrieveAllStatsPatientExerciseDone(int userID) { + String query = "SELECT " + + " eg.Type AS ExerciseType," + + " COUNT(*) AS TotalAssigned," + + " COUNT(e.ID_exercise) AS TotalCompleted," + + " (COUNT(e.ID_exercise) / COUNT(*)) * 100 AS CompletionPercentage " + + "FROM " + + " exercise_glossary eg " + + "LEFT JOIN " + + " exercise e ON eg.ID_exercise = e.ID_exercise " + + " AND e.Recommended <> 0 " + + "WHERE " + + " e.ID_user = ? " + + "GROUP BY " + + " eg.Type;"; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + Map result = new HashMap<>(); + + try { + connection = connection.isClosed() ? DAOConnection.getConnection() : connection; + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, userID); + + resultSet = preparedStatement.executeQuery(); + + while (resultSet.next()) { + String exerciseType = resultSet.getString("ExerciseType"); + int completionPercentage = Math.round((float)resultSet.getDouble("CompletionPercentage")); + + result.put(exerciseType,completionPercentage); + } + + } catch (SQLException e) { + e.printStackTrace(); + } finally { + try { + if (resultSet != null) resultSet.close(); + if (preparedStatement != null) preparedStatement.close(); + DAOConnection.releaseConnection(connection); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return result; + } } diff --git a/src/main/java/model/service/exercise/ExerciseManager.java b/src/main/java/model/service/exercise/ExerciseManager.java index 341cf00..363c94b 100644 --- a/src/main/java/model/service/exercise/ExerciseManager.java +++ b/src/main/java/model/service/exercise/ExerciseManager.java @@ -9,6 +9,7 @@ import java.sql.Blob; import java.sql.Date; import java.util.List; +import java.util.Map; public class ExerciseManager implements ExerciseManagerInterface { private final DAOExerciseGlossary daoEG = new DAOExerciseGlossary(); @@ -63,4 +64,9 @@ public boolean changeMultipleReccomandation(String action, int userId){ return daoE.deleteMultipleExercise(userId); } } + + public Map retrieveAllStats(int id) + { + return daoE.retrieveAllStatsPatientExerciseDone(id); + } } diff --git a/src/main/webapp/JSP/userReport.jsp b/src/main/webapp/JSP/userReport.jsp new file mode 100644 index 0000000..e5cd03c --- /dev/null +++ b/src/main/webapp/JSP/userReport.jsp @@ -0,0 +1,92 @@ +<%@ page import="model.service.exercise.ExerciseManager" %> +<%@ page import="model.entity.Exercise" %> +<%@ page import="java.util.List" %> +<%@ page import="model.entity.ExerciseGlossary" %> +<%@ page import="java.util.Map" %> + + +<% + Integer userIdp = (Integer) session.getAttribute("id"); + if(userIdp == null) { + response.sendRedirect("../errorPage/403.html"); + } + else { + int userId = (Integer) session.getAttribute("id"); +%> + + <%@page contentType="text/html;charset=UTF-8"%> + + + + + + + +
+
+
+ +

Report del vostro progresso

+
+
+ +
+
+
+ +
+ + <% + ExerciseManager exerciseManager = new ExerciseManager(); + Map dict = exerciseManager.retrieveAllStats((int)session.getAttribute("id")); + if(!dict.isEmpty()){ + int Counter = 0; + for(Map.Entry exercise : dict.entrySet()) { + + %> +
+

<%= exercise.getKey()%>

+ + + Layer 1 + + + <%=exercise.getValue()%>% + + +
+ + + <% + Counter++; + } + } + else { + %> + %> +
Esercizi non disponibili
+ <% + } + %> + +
+
+ + +
+
+
+ + +<% + } +%> \ No newline at end of file From c1c74313a0c7c3f4f21808d4cb4aa3a8aa43f77a Mon Sep 17 00:00:00 2001 From: Luigi Date: Wed, 17 Jan 2024 21:30:39 +0100 Subject: [PATCH 2/3] Aggiunta css di userReport --- src/main/webapp/CSS/userReport.css | 494 +++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 src/main/webapp/CSS/userReport.css diff --git a/src/main/webapp/CSS/userReport.css b/src/main/webapp/CSS/userReport.css new file mode 100644 index 0000000..e31680e --- /dev/null +++ b/src/main/webapp/CSS/userReport.css @@ -0,0 +1,494 @@ +*{ + padding: 0; + margin: 0; +} +body +{ + align-items: center; + width: 100%; +} + +form +{ + width: 100%; + display: flex; + justify-content: center; + flex-direction: column; + gap: 10px; + padding: 25px; + border-radius: 8px; +} +.up +{ + padding-top: 200px; + background-color: #199A8E; + height:20vh; + width: 100vw; +} + +.div_up +{ + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + width:80vw; +} +.div_up img +{ + padding-right: 10px; +} + +.div_up h2 +{ + font-size: 50px; + color: white; +} + +.eillustration-wrapper h2 +{ + font-size: 35px; + padding-left: 70px; +} +img +{ + width: 7vw; + height: 7vw; +} + +#paziente +{ + width: 10vw; + height: 10vw; + position: absolute; + top:26vh; + left: 46vw; + z-index: 2; + border-radius: 50%; + border: 4px solid white; +} +.down +{ + z-index: 1; + background-color: white; + display: flex; + flex-direction: column; + align-items: center; + padding-top: 25px; +} + +.input-field { + position: relative; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + padding: 25px; +} + +.input { + margin-top: 15px; + width: 75%; + outline: none; + border-radius: 8px; + height: 5vh; + border: 3px solid black; + background: transparent; + padding-left: 10px; + font-size: 35px; +} +.input:focus { + border: 1.5px solid #2d79f3; +} +.input-field .label { + position: absolute; + top: 5px; + left: 145px; + color: #ccc; + transition: all 0.3s ease; + pointer-events: none; + z-index: 2; + font-size: 35px; +} +.input-field .input:focus ~ .label, +.input-field .input:valid ~ .label { + top: 5px; + left: 145px; + font-size: 35px; + color: #2d79f3; + background-color: #ffffff; + padding-left: 5px; + padding-right: 5px; +} + +.save +{ + z-index: 2; + position: sticky; + bottom: 0; + padding: 10px; + background-color: white; + border-radius: 35px 35px 0 0; + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0px -10px 10px -10px #888; + height: 5vh; +} + +.submit-btn { + align-items: center; + justify-content: center; + gap: 8px; + padding: 10px; + position: relative; + background-color: #199a8e; + border-radius: 9999px; + font-family: Georgia, serif; + color: #ffffff; + font-size: 2.5em; + white-space: nowrap; + box-sizing: border-box; +} + +.submit-btn:hover { + box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #0000003a; +} + +.prova +{ + width: 75vw; + display: flex; + align-items: center; + justify-content: space-around; + box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1); + border-radius: 32px; + margin-bottom: 50px; +} + +.prova h2 +{ + font-size: 35px; +} + +.prova .eimg +{ + margin: 15px; +} + + + + + + + + + + +.container { + width: 100vw; + display: flex; + flex-direction: column; + align-items: center; +} + +.margin20 { + margin-bottom: 4em; +} + +.card { + width: 70vw; + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px; + position: relative; + flex: 0 0 auto; + background-color: #ffffff; + border-radius: 32px; + margin-right: 20px; /* Spazio tra i div */ + box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1); +} + +.divbar{ + background-color: #199a8e; + width: 100%; + border-collapse: collapse; + margin-top: 1.3em; + margin-bottom: 1.3em; + border-radius: 50px; + overflow-x: auto; + white-space: nowrap; + height: 1.3em; +} + +.cards { + margin-top: 20px; + margin-bottom: 20px; + display: flex; + overflow-x: auto; + white-space: nowrap; +} +.acards { + margin-top: 20px; + margin-bottom: 20px; + display: flex; + justify-content: center; + flex-wrap: wrap; + overflow-x: auto; + white-space: nowrap; +} + + +.card2 { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 16px; + padding: 20px; + position: relative; + flex: 0 0 auto; + background-color: #ffffff; + border-radius: 32px; + margin-right: 20px; /* Spazio tra i div */ +} + +.challenges .cards { + display: flex; + overflow-x: scroll; +} + +.challenges .acards { + display: flex; + overflow-x: scroll; +} + +.card .img { + position: absolute; + width: 105px; + height: 115px; + top: 4px; + left: 600px; +} + + + +.errorcard { + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px; + position: relative; + flex: 0 0 auto; + background-color: #ffffff; + border-radius: 32px; + margin-right: 20px; /* Spazio tra i div */ +} +.errorcard .img { + position: absolute; + width: 105px; + height: 115px; + top: 4px; + left: 600px; +} +.errorcard .chapter { + position: relative; + width: fit-content; + margin-top: -1px; + font-family: Georgia, serif; + font-size: 1.5em; + white-space: nowrap; +} + +.card .eimg { + position: absolute; + left: 600px; +} + +.eillustration-wrapper { + display: flex; + align-items: center; + justify-content: center; + padding: 8px; + position: relative; + flex: 0 0 auto; + border-radius: 900px; + margin-bottom:2em; +} + + + + + + +.frame-3 { + display: flex; + align-items: center; + gap: 16px; + position: relative; + align-self: stretch; + width: 100%; + flex: 0 0 auto; +} + +.frame-4 { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + gap: 8px; + position: relative; + flex: 1; + flex-grow: 1; +} + +.frame-5 { + display: flex; + flex-direction: column; + align-items: flex-start; + position: relative; + align-self: stretch; + width: 100%; + height: 150px; + flex: 0 0 auto; +} + +.frame-7 { + display: flex; + width: 208px; + align-items: flex-start; + justify-content: space-between; + position: relative; + flex: 0 0 auto; +} + +.illustration-wrapper { + display: flex; + align-items: center; + justify-content: center; + padding: 8px; + position: relative; + flex: 0 0 auto; + border-radius: 900px; +} + +.illustration { + position: relative; + width: 40px; + height: 40px; +} + +.img { + position: absolute; + width: 105px; + height: 115px; + top: 4px; + left: 260px; +} + +.chapter { + position: relative; + width: fit-content; + margin-top: -1px; + font-family: Georgia, serif; + font-size: 2em; + white-space: nowrap; +} + +.discovering-english { + position: relative; + align-self: stretch; + font-family: Georgia, serif; + color: #252526; + font-weight: 700; + font-size: 2em; +} + +.button-2 { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 10px; + position: relative; + background-color: #199a8e; + border-radius: 9999px; + + font-family: Georgia, serif; + color: #ffffff; + font-size: 2em; + white-space: nowrap; + + box-sizing: border-box; +} + + + + + + +.navigation-title { + display: flex; + height: 32px; + align-items: baseline; + justify-content: space-between; + padding: 4px 0px; + position: relative; +} + +.current-lesson { + position: relative; + width: fit-content; + margin-top: -1px; + font-family: Georgia, serif; + font-weight: 700; + color: #252526; + font-size: 2.5em; + text-align: center; + white-space: nowrap; +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; + position: relative; + background-color: #199a8e; + border-radius: 9999px; + border-width: 1px; + padding: 10px; + + font-family: Georgia, serif; + color: #ffffff; + font-size: 2em; + white-space: nowrap; +} + + + + + +.header { + font-family: Georgia, serif; + text-align: center; + color:#199a8e; + font-weight: 700; + font-size: 2.5em; +} + + + +.circle_animation { + stroke-dasharray: 440; /* this value is the pixel circumference of the circle */ + stroke-dashoffset: 440; +} + +.html .circle_animation { + animation: html 1s ease-out forwards; +} + +@keyframes html { + to { + stroke-dashoffset: 80; /* 50% would be 220 (half the initial value specified above) */ + } +} From db9aa0d8daf62022a1d53abb693bef30f8d42d18 Mon Sep 17 00:00:00 2001 From: Luigi Date: Wed, 17 Jan 2024 22:48:19 +0100 Subject: [PATCH 3/3] Perfezionamento userReport --- src/main/java/model/DAO/DAOExercise.java | 28 ++++++++----------- .../exercise/ExerciseManagerInterface.java | 8 ++++++ src/main/webapp/JSP/userReport.jsp | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/model/DAO/DAOExercise.java b/src/main/java/model/DAO/DAOExercise.java index 2f9cf06..63a5f3c 100644 --- a/src/main/java/model/DAO/DAOExercise.java +++ b/src/main/java/model/DAO/DAOExercise.java @@ -467,20 +467,14 @@ public boolean deleteMultipleExercise(int userId){ } public Map retrieveAllStatsPatientExerciseDone(int userID) { - String query = "SELECT " + - " eg.Type AS ExerciseType," + - " COUNT(*) AS TotalAssigned," + - " COUNT(e.ID_exercise) AS TotalCompleted," + - " (COUNT(e.ID_exercise) / COUNT(*)) * 100 AS CompletionPercentage " + - "FROM " + - " exercise_glossary eg " + - "LEFT JOIN " + - " exercise e ON eg.ID_exercise = e.ID_exercise " + - " AND e.Recommended <> 0 " + - "WHERE " + - " e.ID_user = ? " + - "GROUP BY " + - " eg.Type;"; + String query = "SELECT eg.Type, " + + "COUNT(CASE WHEN e.CompletionDate IS NOT NULL THEN e.ID_exercise END) as CompletedCount, " + + "COUNT(e.ID_exercise) as TotalAssignedCount, " + + "IFNULL(COUNT(CASE WHEN e.CompletionDate IS NOT NULL THEN e.ID_exercise END) / NULLIF(COUNT(e.ID_exercise), 0) * 100, 0) as CompletionPercentage " + + "FROM exercise_glossary eg " + + "LEFT JOIN exercise e ON eg.ID_exercise = e.ID_exercise AND e.ID_user = ? " + + "GROUP BY eg.Type; "; + PreparedStatement preparedStatement = null; ResultSet resultSet = null; Map result = new HashMap<>(); @@ -493,10 +487,10 @@ public Map retrieveAllStatsPatientExerciseDone(int userID) { resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { - String exerciseType = resultSet.getString("ExerciseType"); - int completionPercentage = Math.round((float)resultSet.getDouble("CompletionPercentage")); + String exerciseType = resultSet.getString("Type"); // Fix: Use "Type" instead of "ExerciseType" + int completionPercentage = Math.round((float) resultSet.getDouble("CompletionPercentage")); - result.put(exerciseType,completionPercentage); + result.put(exerciseType, completionPercentage); } } catch (SQLException e) { diff --git a/src/main/java/model/service/exercise/ExerciseManagerInterface.java b/src/main/java/model/service/exercise/ExerciseManagerInterface.java index 14622c9..6b6461f 100644 --- a/src/main/java/model/service/exercise/ExerciseManagerInterface.java +++ b/src/main/java/model/service/exercise/ExerciseManagerInterface.java @@ -7,6 +7,7 @@ import java.sql.Blob; import java.sql.Date; import java.util.List; +import java.util.Map; public interface ExerciseManagerInterface { @@ -66,4 +67,11 @@ public interface ExerciseManagerInterface { */ public List retrieveNotDoneExercises(int patientId); + /** + * Recupera i dati riguardanti gli esercizi proposti dal paziente all'utente. + * + * @param id L'ID del paziente. + * @return Una Map con chiave il tipo di esercizio e valore la percentaule di esercizi fatti rispetto a quelli non fatti. + */ + public Map retrieveAllStats(int id); } diff --git a/src/main/webapp/JSP/userReport.jsp b/src/main/webapp/JSP/userReport.jsp index e5cd03c..668ef07 100644 --- a/src/main/webapp/JSP/userReport.jsp +++ b/src/main/webapp/JSP/userReport.jsp @@ -71,7 +71,7 @@ else { %> %> -
Esercizi non disponibili
+
Non ti sono stati proposti esercizi
<% } %>