From c450950cb008ddc2ff4376f5d1792228804760b1 Mon Sep 17 00:00:00 2001
From: Gabriel Copat <copatg@cardiff.ac.uk>
Date: Sun, 3 Dec 2023 16:26:05 +0000
Subject: [PATCH] Added client-side validation for log-in

---
 src/main/resources/static/css/userProfile.css | 55 ++++++++++++++++---
 src/main/resources/static/scripts/login.js    | 49 +++++++++++++++++
 .../resources/templates/rewards/login.html    | 22 ++++++--
 .../templates/rewards/userProfile.html        | 10 +---
 4 files changed, 117 insertions(+), 19 deletions(-)
 create mode 100644 src/main/resources/static/scripts/login.js

diff --git a/src/main/resources/static/css/userProfile.css b/src/main/resources/static/css/userProfile.css
index 7047dc43..3cc42919 100644
--- a/src/main/resources/static/css/userProfile.css
+++ b/src/main/resources/static/css/userProfile.css
@@ -39,8 +39,11 @@
 }
 
 body {
-    background: linear-gradient(135deg, #d295e9, #53166a);
+    background: linear-gradient(135deg, #f7e8fd, #9914d1);
     height: 100svh;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-evenly;
 }
 main {
     background: linear-gradient(to bottom, #1e1e1e 10%, darkgoldenrod 50%, #1e1e1e 90%);
@@ -52,6 +55,8 @@ main {
     margin-top: 6em;
     padding-inline: 1vw;
     box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
+
+
 }
 .userInfo {
     display: flex;
@@ -259,17 +264,16 @@ header .footerButton:hover {
     margin-block: 5svh;
     display: flex;
     text-align: center;
-    justify-content: left;
-    background: #c45cef;
+    justify-content: center;
+    background: rgba(196, 92, 239, 0.75);
     padding: 2em;
-
-    width: auto;
-    height: auto;
+    flex: 0 0;
     border-radius: 1vw;
     box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
     & h2 {
-        margin-left: 1vw;
+        margin-left: 0;
         margin-right: auto;
+        margin-bottom: 0.5em;
     }
     & form{
         margin-block: auto;
@@ -300,6 +304,8 @@ header .footerButton:hover {
         width: 40vw;
         border-radius: 0.2em;
         padding-inline: 0.4em;
+        border: transparent solid 0.1em;
+        margin-bottom: 1em;
     }
     & button {
         font-size: 1em;
@@ -318,4 +324,39 @@ header .footerButton:hover {
         background-color: var(--accent-border);
         border: 0.1em solid var(--accent-colour);
     }
+}
+.label {
+    position: relative;
+}
+.invalid-tooltip {
+    color: red;
+    width: fit-content;
+    opacity: 0;
+    font-size: 0.6em;
+    text-shadow: red 0 0.2em 1em;
+    transition: 0.3s ease-in-out 1ms;
+    padding:0.1em;
+    position: absolute;
+    right: 0.2em;
+    bottom: 0.2em;
+    height: fit-content;
+}
+.invalid-field {
+    box-shadow: red 0 0 1em;
+    transition: 0.3s ease-in-out 1ms;
+}
+.valid-field {
+    box-shadow: #40ff00 0 0 1em;
+    border: #40ff00 solid 0.1em;
+    transition: 0.3s ease-in-out 1ms;
+}
+
+#invalidLogin {
+    color: red;
+    text-shadow: black 0 0.1em 0.2em;
+    width: auto;
+    height: auto;
+    font-size: 0.6em;
+    opacity: 0;
+    transition: 0.5s ease-in-out 1ms;
 }
\ No newline at end of file
diff --git a/src/main/resources/static/scripts/login.js b/src/main/resources/static/scripts/login.js
new file mode 100644
index 00000000..929b8b61
--- /dev/null
+++ b/src/main/resources/static/scripts/login.js
@@ -0,0 +1,49 @@
+let username = document.forms["loginForm"]["username"];
+let password = document.forms["loginForm"]["password"];
+let pattern = new RegExp("^[a-z0-9_-]{3,15}$");
+
+username.addEventListener("input", validateUsername)
+password.addEventListener("input", validatePassword)
+
+function validateUsername() {
+    if (!(username.value === "") && pattern.test(username.value)){
+        username.classList.remove("invalid-field");
+        username.classList.add("valid-field");
+        document.getElementById(username.name+"Invalid").style.opacity = 0;
+        username.style.borderColor = "green";
+        return true;
+    } else if( ! (username.classList.contains("invalid-field") ) ){
+        username.classList.add("invalid-field");
+        username.classList.remove("valid-field");
+        document.getElementById(username.name+"Invalid").style.opacity = 1;
+        username.style.borderColor = "red";
+    }
+    return false;
+}
+function validatePassword(){
+    if (password.value === "") {
+        password.classList.add("invalid-field");
+        password.classList.remove("valid-field");
+        document.getElementById(password.name+"Invalid").style.opacity = 1;
+        password.style.borderColor = "red";
+        return false;
+    } else if( ! (password.classList.contains("valid-field") ) ) {
+        password.classList.remove("invalid-field");
+        password.classList.add("valid-field");
+        document.getElementById(password.name+"Invalid").style.opacity = 0;
+        password.style.borderColor = "green";
+    }
+    return true;
+}
+
+function validateForm(){
+    if (validateUsername() & validatePassword()) { //Using just & so it checks both, even if the first is false (it applies the style)
+        console.log("VALID");
+        return false;
+    } else {
+        console.log("Invalid");
+        document.getElementById("invalidLogin").style.opacity = 1;
+        return false;
+    }
+    //TODO SERVER SIDE VALIDATION AND CHECK AGAINST USERS DB TABLE
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/rewards/login.html b/src/main/resources/templates/rewards/login.html
index ed1791fd..9c7aea8b 100644
--- a/src/main/resources/templates/rewards/login.html
+++ b/src/main/resources/templates/rewards/login.html
@@ -4,6 +4,7 @@
     <meta charset="UTF-8">
     <title>User Log In</title>
     <link rel="stylesheet" th:href="@{/css/userProfile.css}">
+
 </head>
 <body>
 
@@ -18,12 +19,20 @@
 </header>
 <main  class="solidBg">
     <div class="loginWrapper">
-        <form action="/login" method="post">
+        <form action="" onsubmit="return validateForm()" method="post" name="loginForm">
             <h2>Log In</h2>
-            <label for="username"><b>Username</b><br></label>
-                <input type="text" name="username" id="username" placeholder="Enter Username">
-            <label for="password"><b>Password</b><a>Forgot Password</a><br></label>
-                <input type="password" id="password" name="password">
+            <div class="label">
+                <label for="username"><b>Username</b><br></label>
+                <div id="usernameInvalid" class="invalid-tooltip">Please fill out this field.</div>
+            </div>
+            <input type="text" name="username" id="username" placeholder="Enter Username" title="Username Input">
+
+            <div class="label">
+                <label for="password"><b>Password</b><br></label>
+                <div id="passwordInvalid" class="invalid-tooltip">Please fill out this field.</div>
+            </div>
+            <input type="password" id="password" name="password">
+            <div id="invalidLogin">Username and/or Password incorrect. Please try again.</div>
             <button type="submit"><b>Log In</b></button>
         </form>
 
@@ -32,5 +41,8 @@
 </main>
 
 
+
+<script type="text/javascript" th:src="@{scripts/login.js}"></script>
+
 </body>
 </html>
\ No newline at end of file
diff --git a/src/main/resources/templates/rewards/userProfile.html b/src/main/resources/templates/rewards/userProfile.html
index cecdb406..dbf4b0e0 100644
--- a/src/main/resources/templates/rewards/userProfile.html
+++ b/src/main/resources/templates/rewards/userProfile.html
@@ -14,7 +14,7 @@
         <li class="footerButton"><b>About</b></li>
         <li class="footerButton"><b>Map</b></li>
         <li class="footerButton"><b>Facilities</b></li>
-        <li class="footerButton"><b>Search</b></li>
+        <li class="footerButton"><b>Log In</b></li>
     </ul>
 </header>
 
@@ -37,7 +37,7 @@
 <!--            </div>-->
 <!--        </article>-->
         <article class="dragonProgression">
-            <h1>The Dragon Trail</h1>
+            <h1>The Dragon's Tale</h1>
             <div class="dragonContainer">
                 <div class="dragonFill" th:style="'width:'+ ${user.getDragonProgress()} + '%;'">
                     <img th:src="@{/images/rewards/dragonFilled.png}"
@@ -70,8 +70,4 @@
 <script>
 </script>
 </body>
-</html>
-
-<!--TODO finished doing the tooltips, need to add some more changes to them for sure
-    TODO afterwards probably need to implement thymeleaf so it shows badges based on the list
-    TODO implement some placeholder pictures as well for the badges and for the stickers -->
\ No newline at end of file
+</html>
\ No newline at end of file
-- 
GitLab