Skip to content
Snippets Groups Projects
Commit f695ff76 authored by Gabriel Copat's avatar Gabriel Copat
Browse files

New Login page. Started work on the controllers. Currently one can create...

New Login page. Started work on the controllers. Currently one can create account but theres no validation or password checking
parent c15217aa
No related branches found
No related tags found
1 merge request!37Resolve "As a repeat trail visitor , I want to be able to create an account so I can save and review my progress."
Showing
with 581 additions and 46 deletions
package Team5.SmartTowns.users;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class NewUser {
@NotEmpty(message = "You must type in a username.")
String name;
@NotEmpty(message = "You must type in a password.")
String password;
@NotEmpty(message = "You must type in an email.")
String email;
}
......@@ -4,13 +4,15 @@ package Team5.SmartTowns.users;
import Team5.SmartTowns.rewards.Pack;
import Team5.SmartTowns.rewards.RewardsRepository;
import Team5.SmartTowns.rewards.Sticker;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.List;
@Controller
......@@ -26,17 +28,32 @@ public class UserController {
@GetMapping("/login")
public ModelAndView getLoginPage() {
ModelAndView mav = new ModelAndView("users/login");
mav.addObject("user", new NewUser( "", "", ""));
return mav;
}
@PostMapping("/login/register")
public ModelAndView registerUser(String[] userInfo) {
/* TODO CHECK IS USER ALREADY EXISTS */
public ModelAndView registerUser(@Valid @ModelAttribute("user") NewUser user, BindingResult bindingResult, Model model) {
ModelAndView mav = new ModelAndView("users/login", model.asMap());
// TODO VALIDATE EMAIL INPUT
/* TODO CALL FUNCTION HERE TO CRATE USER IN THE DATABASE */
ModelAndView mav = new ModelAndView("users/login");
return mav;
if (bindingResult.hasErrors()) {
System.out.println("Errors");
}
System.out.println(user.getName());
System.out.println(user.getPassword());
if ( userRepository.doesUserExist(user.getEmail()) ) {
//TODO return modelandview for user already exists
System.out.println(user.getEmail() + " already exists");
System.out.print("LOG IN:");
System.out.println(userRepository.userLogIn(user.email, user.password));
return mav;
} else {
userRepository.addUser(user.name, user.email, user.password);
System.out.println(user.getEmail() + " created");
return mav;
}
}
/* USER MAPPING & FUNCTIONS */
......
......@@ -10,4 +10,5 @@ public interface UserRepository {
boolean unlockSticker(int userID, int packID, int stickerID);
boolean addUser(String username, String email, String password);
boolean doesUserExist(String email);
boolean userLogIn(String username, String password);
}
......@@ -12,6 +12,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
@Repository
public class UserRepositoryJDBC implements UserRepository{
......@@ -60,13 +61,20 @@ public class UserRepositoryJDBC implements UserRepository{
@Override
public boolean addUser(String username, String email, String password){
String query = "INSERT INTO users (name, email) VALUES (?,?)";
jdbc.update(query, username, email);
return false;
String query = "INSERT INTO users (name, email, password) VALUES (?, ?, ?)";
jdbc.update(query, username, email, password);
return true;
}
@Override
public boolean doesUserExist(String email){
String query = "SELECT COUNT(email) FROM users WHERE (email) = (?)";
return !(jdbc.queryForObject(query, Integer.class, email) == 0);
}
@Override
public boolean userLogIn(String email, String password){
String query = "SELECT (password) FROM users WHERE (email) = (?)";
String dbpassword = jdbc.queryForObject(query, String.class, email);
return Objects.equals(dbpassword, password);
}
}
DELETE FROM users;
INSERT INTO users (id, email, name) VALUE (1, 'admin@gmail.com', 'Admin');
INSERT INTO users (email, name) VALUE ('hannah@gmail.com', 'Hannah');
INSERT INTO users (email, name) VALUE ('nigel@gmail.com', 'Nigel');
INSERT INTO users (email, name) VALUE ('oscar@gmail.com', 'Nigel');
INSERT INTO users (id, email, name, password) VALUE (1, 'admin@gmail.com', 'Admin', 'admin');
INSERT INTO users (email, name, password) VALUE ('hannah@gmail.com', 'Hannah', 'root');
INSERT INTO users (email, name, password) VALUE ('nigel@gmail.com', 'Nigel', 'root');
INSERT INTO users (email, name, password) VALUE ('oscar@gmail.com', 'Oscar', 'root');
DELETE FROM trails;
INSERT INTO trails ( Name) VALUE ( 'Caerphilly Coffee Trail');
......
......@@ -33,6 +33,7 @@ CREATE TABLE IF NOT EXISTS users (
id bigint auto_increment primary key,
email varchar(128) NOT NULL ,
name varchar(30) NOT NULL,
password varchar(30) NOT NULL,
dragonProgress int,
dragonsLandmarkIDs longtext
);
......
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap');
:root {
--container-colour: #2a2a2a;
--details-colour: var(--primary-light);
--details-light: #512da8;
--font-buttons: 14px;
--font-size-1: 14px;
--font-size-2: 200px;
--font-size-3: 300px;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Montserrat', sans-serif;
color: white;
}
body{
align-items: center;
height: 100svh;
}
main {
height: 90%;
width: 90%;
display: flex;
align-items: center;
justify-content: center;
}
@keyframes move{
0%, 49.99%{
opacity: 0;
z-index: 1;
}
50%, 100%{
opacity: 1;
z-index: 5;
}
}
@media only screen
and (min-device-width: 650px) {
.container{
background-color: var(--container-colour);
border-radius: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);
position: relative;
overflow: hidden;
min-width: 768px;
max-width: 100%;
min-height: 480px;
}
.container p{
font-size: 14px;
line-height: 20px;
letter-spacing: 0.3px;
margin: 20px 0;
}
.container a{
font-size: var(--font-size-1);
text-decoration: none;
margin: 15px 0 10px;
}
.container button{
background-color: var(--details-colour)/*#512da8*/;
color: #fff;
font-size: var(--font-buttons);
padding: 10px 45px;
border: 1px solid transparent;
border-radius: 8px;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
margin-top: 10px;
cursor: pointer;
}
.container button.hidden{
background-color: transparent;
border-color: #fff;
}
.container form{
background-color: var(--container-colour);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
height: 100%;
}
.container input{
background-color: #eee;
border: none;
margin: 8px 0;
padding: 10px 15px;
font-size: 13px;
border-radius: 8px;
width: 100%;
outline: none;
}
.form-container{
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
}
.sign-in{
left: 0;
width: 50%;
z-index: 2;
}
.container.active .sign-in{
transform: translateX(100%);
}
.sign-up{
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
}
.container.active .sign-up{
transform: translateX(100%);
opacity: 1;
z-index: 5;
animation: move 0.6s;
}
.toggle-container{
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: all 0.6s ease-in-out;
border-radius: 150px 0 0 100px;
z-index: 1000;
}
.container.active .toggle-container{
transform: translateX(-100%); /*BG THING*/
border-radius: 0 150px 100px 0;
}
.toggle{
background-color: var(--details-colour);
height: 100%;
background: linear-gradient(to right, var(--details-light), var(--details-colour));
color: #fff;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: all 0.6s ease-in-out;
}
.container.active .toggle{
transform: translateX(50%);
}
.toggle-panel{
position: absolute;
width: 50%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 30px;
text-align: center;
top: 0;
transform: translateX(0);
transition: all 0.6s ease-in-out;
}
.toggle-left{
transform: translateX(-200%);
}
.container.active .toggle-left{
transform: translateX(0);
}
.toggle-right{
right: 0;
transform: translateX(0);
}
.container.active .toggle-right{
transform: translateX(200%);
}
.input {
color: black;
}
}
@media only screen
and (max-device-width: 640px) {
.container {
position: relative;
background-color: var(--container-colour);
border-radius: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);
overflow: hidden;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
.form-container {
height: 100%;
transition: all 0.6s ease-in-out;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.form-container form {
display: flex;
flex-direction: column;
align-items: center;
font-size: 3em;
margin-inline: 5%;
}
.form-container input {
flex: 1 1;
font-size: 1em;
color: black;
margin-block: 5%;
padding: 2%;
border-radius: 30px;
}
.form-container button {
flex: 1 1;
font-size: 1em;
}
.toggle-container {
position: absolute;
top: 0;
width: 100%;
height: 50%;
transition: all 0.6s ease-in-out;
overflow: hidden;
border-radius: 0 0 150px 150px;
z-index: 1000;
}
.container.active .toggle-container{
transform: translateY(100%); /*BG THING*/
border-radius: 150px 150px 0 0;
}
.toggle {
position: absolute;
width: 100%;
height: 200%;
display: flex;
flex-direction: column-reverse;
align-items: center;
justify-content: space-evenly;
background: linear-gradient(to bottom, var(--details-light), var(--details-colour));
/*background-color: red;*/
}
.toggle-panel {
flex: 1 1;
width: 100%;
}
.container .toggle-right {
transform: translateY(0);
opacity: 1;
}
.container .toggle-left {
transform: translateY(-100%);
opacity: 0;
}
.container.active .toggle-right{
transform: translateY(-100%);
opacity: 0;
}
.container.active .toggle-left{
transform: translateY(-100%);
opacity: 1;
}
.container .sign-up {
opacity: 0;
z-index: -1;
transform: translateY(100%);
}
.container .sign-in {
opacity: 1;
z-index: 5;
}
.container.active .sign-in{
transform: translateY(-100%);
opacity: 0;
z-index: -1;
}
.container.active .sign-up{
animation: move 0.6s;
opacity: 1;
z-index: 5;
transform: translateY(0);
}
.toggle-panel {
transition: all 0.6s ease-in-out;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: xxx-large;
}
.toggle-panel p {
margin-inline: 10%;
}
.container button{
background-color: var(--details-colour)/*#512da8*/;
color: #fff;
font-size: xxx-large;
padding: 40px 40px;
border: 5px solid transparent;
border-radius: 14px;
font-weight: 600;
letter-spacing: 1px;
text-transform: uppercase;
margin-top: 30px;
cursor: pointer;
}
.container button.hidden{
background-color: transparent;
border-color: #fff;
}
}
......@@ -62,6 +62,11 @@ and (max-device-width: 640px) {
width: 100vw;
height: 100svh;
}
html {
position: fixed;
width: 100vw;
height: 100svh;
}
}
/*PHONES LANDSCAPE*/
......
......@@ -198,8 +198,14 @@ main {
height: 17em;
margin: 1.5em;
}
/*}*/
/* LOGIN FORM PAGE */
/* MEDIA TYPE UPDATES*/
@media only screen
and (min-device-width: 320px)
and (max-device-width: 640px) {
......@@ -267,4 +273,21 @@ and (min-device-width: 1000px) {
.progressionContainer {
height: 20svh;
}
}
\ No newline at end of file
}
.container {
width: 500px;
margin-block: 5%;
background-color: var(--accent-colour);
border-radius: 10em;
display: flex;
flex-direction: column;
align-items: center;
& form {
margin-inline: auto;
margin-block: 5%;
}
}
.container-active {
background: black;
}
let username = document.forms["loginForm"]["username"];
/*let username = document.forms["loginForm"]["username"];
let password = document.forms["loginForm"]["password"];
let pattern = new RegExp("^[a-z0-9_-]{3,15}$");
......@@ -46,6 +46,39 @@ function validateForm(){
return false;
}
//TODO SERVER SIDE VALIDATION AND CHECK AGAINST USERS DB TABLE
}
}*/
/*
function createAccountPOST(){
let data = { username: username.value, password: password.value}
console.log(username.value);
console.log(password.value);
$.ajax
({
type: "POST",
url: "http://localhost:8080/login/register",
dataType: 'json',
data: JSON.stringify(data),
success: function (){
console.log('Success');
},
error: function (request, status, error) {
console.log("ERROR");
console.log(request);
console.log(status);
console.log(error);
}
});
return false;
}*/
const container = document.getElementById('container');
const registerBtn = document.getElementById('register');
const loginBtn = document.getElementById('login');
registerBtn.addEventListener('click', () => {
container.classList.add("active");
});
loginBtn.addEventListener('click', () => {
container.classList.remove("active");
});
\ No newline at end of file
......@@ -3,41 +3,64 @@
<head>
<meta charset="UTF-8">
<title>User Log In</title>
<link rel="stylesheet" th:href="@{/css/userProfile.css}">
<link rel="stylesheet" th:href="@{/css/style.css}">
<link rel="stylesheet" th:href="@{/css/login.css}">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<header>
<ul class="footerBar">
<li class="footerButton"><b>Home</b></li>
<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>Log In</b></li>
</ul>
</header>
<main class="solidBg">
<div class="loginWrapper">
<form action="" onsubmit="return validateForm()" method="post" name="loginForm">
<h2>Log In</h2>
<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>
<main>
<!--CODE FROM: https://www.youtube.com/watch?v=PlpM2LJWu-s&t=928s -->
<div class="container sign-in">
<div class="container" id="container">
<div class="form-container sign-up">
<form th:object="${user}" action="#" th:action="@{/login/register}" th:method="POST" onsubmit="">
<h1>Create Account</h1>
<label>
<input class="input" th:field="*{name}" type="text" placeholder="Name">
</label>
<label>
<input class="input" th:field="*{email}" type="email" placeholder="Email">
</label>
<label>
<input class="input" th:field="*{password}" type="password" placeholder="Password">
</label>
<button type="submit" >Sign Up</button>
</form>
</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>
<div class="form-container sign-in">
<form th:object="${user}" action="#" th:action="@{/login/register}" th:method="POST" onsubmit="">
<h1>Sign In</h1>
<label>
<input class="input" th:field="*{email}" type="email" placeholder="Email">
</label>
<label>
<input class="input" th:field="*{password}" type="password" placeholder="Password">
</label>
<a href="#" class="text">Forget Your Password?</a>
<button type="submit">Sign In</button>
</form>
</div>
<div class="toggle-container">
<div class="toggle">
<div class="toggle-panel toggle-left">
<h1>Welcome Back!</h1>
<p>Enter your personal details and start tracking your landmarks!</p>
<button class="hidden" id="login">Sign In</button>
</div>
<div class="toggle-panel toggle-right">
<h1>Hello, Welcome!</h1>
<p>Register with your personal details and start earning stickers!</p>
<button class="hidden" id="register">Sign Up</button>
</div>
</div>
</div>
</div>
</div>
</main>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<main>
<div class="container sign-in">
<form action="#" th:action="@{/login/register}" method="post" name="loginForm" th:object="${user}">
<h2>Log In</h2>
<div class="label">
<label for="username"><b>Username</b><br></label>
<div th:style="${#fields.hasErrors('name') ? 'opacity: 1;' : 'opacity: 0;'}" id="usernameInvalid" class="invalid-tooltip">Please fill out this field.</div>
</div>
<input type="text" name="username" id="username" th:field="*{name}" placeholder="Enter Username" title="Username Input">
<div class="label">
<label for="password"><b>Password</b><br></label>
<div th:style="${#fields.hasErrors('password') ? 'opacity: 1;' : 'opacity: 0;'}" id="passwordInvalid" class="invalid-tooltip">Please fill out this field.</div>
</div>
<input type="password" id="password" name="password" th:field="*{password}">
<div id="invalidLogin">Username and/or Password incorrect. Please try again.</div>
<button type="submit" ><b>Log In</b></button>
</form>
</div>
<div class="container sign-up"></div>
</main>
</body>
</html>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment