diff --git a/build.gradle b/build.gradle
index 8d359787ce8628dbb4933c80c53d4a6d91fad470..0bdcc02bb2a5367c58f9bb20ef3f61c21057242b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -26,7 +26,8 @@ dependencies {
 	implementation 'org.springframework.boot:spring-boot-starter-web'
 	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
 	implementation 'org.mariadb.jdbc:mariadb-java-client:2.1.2'
-	compileOnly 'org.projectlombok:lombok'
+    testImplementation 'junit:junit:4.13.1'
+    compileOnly 'org.projectlombok:lombok'
     testImplementation 'org.projectlombok:lombok:1.18.28'
     compileOnly 'org.projectlombok:lombok'
 	developmentOnly 'org.springframework.boot:spring-boot-devtools'
diff --git a/src/main/java/Team5/SmartTowns/Data/DatabaseController.java b/src/main/java/Team5/SmartTowns/Data/DatabaseController.java
index 0eed9aca6601fa11eab58684cbf54bae225d5a35..0d38e955dd0a2e38e9585e5560d1cd4b6df83033 100644
--- a/src/main/java/Team5/SmartTowns/Data/DatabaseController.java
+++ b/src/main/java/Team5/SmartTowns/Data/DatabaseController.java
@@ -1,5 +1,7 @@
 package Team5.SmartTowns.Data;
 
+import Team5.SmartTowns.users.User;
+import Team5.SmartTowns.users.UserRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -9,20 +11,13 @@ import java.util.*;
 @Controller
 public class DatabaseController {
 
-    @Autowired
-    private UserRepository userRepository;
+
     @Autowired
     private locationRepository locationRepository;
     @Autowired
     private trailsRepository trailsRepository;
 
-    @GetMapping("/userList")
-    public ModelAndView userList() {
-        ModelAndView mav = new ModelAndView("towns/userData");
-        List<user> users = userRepository.getAllUsers();
-        mav.addObject("users", users);
-        return mav;
-    }
+
     @GetMapping("/trailList")
     public ModelAndView trailList() {
         ModelAndView mav1 = new ModelAndView("towns/trailsData");
diff --git a/src/main/java/Team5/SmartTowns/Data/UserRepository.java b/src/main/java/Team5/SmartTowns/Data/UserRepository.java
deleted file mode 100644
index 172591d6500927a341d6534dca6c34728965db06..0000000000000000000000000000000000000000
--- a/src/main/java/Team5/SmartTowns/Data/UserRepository.java
+++ /dev/null
@@ -1,8 +0,0 @@
-//Holds users data repository
-package Team5.SmartTowns.Data;
-
-import java.util.List;
-
-public interface UserRepository {
-    List<user> getAllUsers();
-}
diff --git a/src/main/java/Team5/SmartTowns/Data/UserRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/Data/UserRepositoryJDBC.java
deleted file mode 100644
index 63e0bad0a8a3abf5f09c435a749066f51f7100fc..0000000000000000000000000000000000000000
--- a/src/main/java/Team5/SmartTowns/Data/UserRepositoryJDBC.java
+++ /dev/null
@@ -1,36 +0,0 @@
-//Implements the users repository using JDBC
-package Team5.SmartTowns.Data;
-
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public class UserRepositoryJDBC implements UserRepository{
-
-    private JdbcTemplate jdbc;
-    private RowMapper<user> userMapper;
-
-    public UserRepositoryJDBC(JdbcTemplate aJdbc){
-        this.jdbc = aJdbc;
-        setuserMapper();
-    }
-
-
-    private void setuserMapper(){
-        userMapper = (rs, i) -> new user(
-                rs.getInt("userID"),
-                rs.getString("name")
-        );
-    }
-
-
-
-    @Override
-    public List<user> getAllUsers(){
-        String sql= "SELECT * FROM users";
-        return jdbc.query(sql, userMapper);
-    }
-}
diff --git a/src/main/java/Team5/SmartTowns/Data/user.java b/src/main/java/Team5/SmartTowns/Data/user.java
deleted file mode 100644
index a40350ebc13621da4fb8a89f4e58d2ccb5be2568..0000000000000000000000000000000000000000
--- a/src/main/java/Team5/SmartTowns/Data/user.java
+++ /dev/null
@@ -1,12 +0,0 @@
-//Holds variable data for the users table
-package Team5.SmartTowns.Data;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-@Data
-@AllArgsConstructor
-public class user {
-    private int userId;
-    private String name;
-}
diff --git a/src/main/java/Team5/SmartTowns/rewards/BadgesRepository.java b/src/main/java/Team5/SmartTowns/rewards/BadgesRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..56b1019cbe016a7c687b5ac83973679e8f498eef
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/rewards/BadgesRepository.java
@@ -0,0 +1,9 @@
+//Holds locations data repository
+package Team5.SmartTowns.rewards;
+
+import java.util.List;
+
+public interface BadgesRepository {
+    List<Badge> getAllBadges();
+}
+
diff --git a/src/main/java/Team5/SmartTowns/rewards/BadgesRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/rewards/BadgesRepositoryJDBC.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c22061e894a633bf9c047f69f575daf9366b493
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/rewards/BadgesRepositoryJDBC.java
@@ -0,0 +1,33 @@
+//Implements the locations repository using JDBC
+package Team5.SmartTowns.rewards;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public class BadgesRepositoryJDBC implements BadgesRepository {
+    private JdbcTemplate jdbc;
+    private RowMapper<Badge> badgeMapper;
+
+    public BadgesRepositoryJDBC(JdbcTemplate aJdbc) {
+        this.jdbc = aJdbc;
+        setBadgeMapper();
+    }
+    private void setBadgeMapper(){
+        badgeMapper = (rs, i) -> new Badge(
+                rs.getInt("badgeID"),
+                rs.getString("name"),
+                rs.getString("description"),
+                rs.getInt("difficulty")
+        );
+    }
+
+    @Override
+    public List<Badge> getAllBadges(){
+        String sql= "SELECT * FROM badges";
+        return jdbc.query(sql, badgeMapper);
+    }
+}
diff --git a/src/main/java/Team5/SmartTowns/rewards/Sticker.java b/src/main/java/Team5/SmartTowns/rewards/Sticker.java
index 274091bdacbaf6199349956be041eb09e34074ff..4fa498c61e7d5748e7d6dcfc26c7c6442dfd8cc4 100644
--- a/src/main/java/Team5/SmartTowns/rewards/Sticker.java
+++ b/src/main/java/Team5/SmartTowns/rewards/Sticker.java
@@ -15,6 +15,7 @@ public class Sticker {
     String description;
     String imgPath;
     int rarity; //1-5
+    boolean hasSticker;
 
     public Sticker(int id, String name, String description, int rarity) {
         this.id = id;
@@ -33,6 +34,16 @@ public class Sticker {
         return imgFile.exists() ? imgPath : notFoundPath;
     }
 
+    public boolean hasSticker(){
+        return hasSticker;
+    }
+    public void setVisibility(boolean hasSticker){
+        this.hasSticker = hasSticker;
+    }
+    public String getVisibility(){
+        return hasSticker? "" : "grayedOut";
+    }
+
 
     @Override
     public boolean equals(Object o) {
diff --git a/src/main/java/Team5/SmartTowns/rewards/StickersRepository.java b/src/main/java/Team5/SmartTowns/rewards/StickersRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..869c2d07353a7aa090fb7fee79b2d44feacd9b12
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/rewards/StickersRepository.java
@@ -0,0 +1,9 @@
+//Holds locations data repository
+package Team5.SmartTowns.rewards;
+
+import java.util.List;
+
+public interface StickersRepository {
+    List<Sticker> getAllStickers();
+}
+
diff --git a/src/main/java/Team5/SmartTowns/rewards/StickersRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/rewards/StickersRepositoryJDBC.java
new file mode 100644
index 0000000000000000000000000000000000000000..64df71bc3da3eff327377798185111aee3be7867
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/rewards/StickersRepositoryJDBC.java
@@ -0,0 +1,33 @@
+//Implements the locations repository using JDBC
+package Team5.SmartTowns.rewards;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public class StickersRepositoryJDBC implements StickersRepository {
+    private JdbcTemplate jdbc;
+    private RowMapper<Sticker> stickerMapper;
+
+    public StickersRepositoryJDBC(JdbcTemplate aJdbc) {
+        this.jdbc = aJdbc;
+        setStickerMapper();
+    }
+    private void setStickerMapper(){
+        stickerMapper = (rs, i) -> new Sticker(
+                rs.getInt("stickerID"),
+                rs.getString("name"),
+                rs.getString("description"),
+                rs.getInt("rarity")
+        );
+    }
+
+    @Override
+    public List<Sticker> getAllStickers(){
+        String sql= "SELECT * FROM stickers";
+        return jdbc.query(sql, stickerMapper);
+    }
+}
diff --git a/src/main/java/Team5/SmartTowns/users/User.java b/src/main/java/Team5/SmartTowns/users/User.java
index 667222393c481b9e2f573ca1773700a93cf7667d..84887664fbee090abb68281f28b5f2b0832af9ae 100644
--- a/src/main/java/Team5/SmartTowns/users/User.java
+++ b/src/main/java/Team5/SmartTowns/users/User.java
@@ -15,17 +15,20 @@ public class User {
     String email; //Validation would be done by email, since they will have that
     String name;
     String imgPath;
+    int dragonProgress;
 
     Map<Badge, Integer> badgeProgress = new HashMap<>(); // Demonstrates the progress towards a specific badge (0-100)
     Map<Sticker, Boolean> hasStickers = new HashMap<>(); // True if User has sticker (key)
 
-    public User(int id, String email, String name) {
+    public User(int id, String email, String name, int dragonProgress) {
         this.id = id;
         this.email = email;
         this.name = name;
+        this.dragonProgress = dragonProgress;
         imgPath = findImagePath();
     }
 
+
     private String findImagePath(){
         /* Finds the image in the Path folder, if image is not found assigns default image */
         String imgPath = "images/users/" + id + ".jpg";
diff --git a/src/main/java/Team5/SmartTowns/users/UserController.java b/src/main/java/Team5/SmartTowns/users/UserController.java
index 0df6457070de7a7db2ff33576c569e20120be554..d635c8a401d85ef6d930142882d69b5528f38fd7 100644
--- a/src/main/java/Team5/SmartTowns/users/UserController.java
+++ b/src/main/java/Team5/SmartTowns/users/UserController.java
@@ -1,57 +1,62 @@
 package Team5.SmartTowns.users;
 
+
 import Team5.SmartTowns.rewards.Badge;
+import Team5.SmartTowns.rewards.BadgesRepository;
 import Team5.SmartTowns.rewards.Sticker;
+import Team5.SmartTowns.rewards.StickersRepository;
+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.servlet.ModelAndView;
 
 import java.util.List;
+import java.util.Map;
 
 @Controller
 public class UserController {
 
-    /* TEMPORARY USER LIST --- TODO REPLACE IT WITH DATABASE LIST*/
-    static List<User> users = List.of(
-            new User(1, "johndoe@gmail.com", "Claire Redfield"),
-            new User(2, "johndoe@gmail.com", "Albert Wesker"),
-            new User(3, "johndoe@gmail.com", "Leon Kennedy"),
-            new User(4, "johndoe@gmail.com", "Jill Valentine")
-    );
-    static List<Badge> badges = List.of(
-            new Badge(1, "Badge1", "Bage One is This", 1),
-            new Badge(2, "Badge1", "Bage One is This", 4),
-            new Badge(3, "Badge1", "Bage One is This", 4),
-            new Badge(4, "Badge1", "Bage One is This", 5),
-            new Badge(5, "Badge1", "Bage One is This", 5),
-            new Badge(46, "Badge1", "Bage One is This", 5),
-            new Badge(7, "Badge1", "Bage One is This", 2)
-    );
-
-    static List<Sticker> stickers = List.of(
-            new Sticker(1, "Sticker", "Sticker", 1),
-            new Sticker(2, "Sticker", "Sticker", 4),
-            new Sticker(3, "Sticker", "Sticker One is This", 4),
-            new Sticker(4, "Sticker", "Sticker One is This", 5),
-            new Sticker(5, "Sticker", "Sticker One is This", 5),
-            new Sticker(46, "Sticker", "Sticker One is This", 5),
-            new Sticker(7, "Sticker", "Sticker One is This", 2)
-    );
+    @Autowired
+    private UserRepository userRepository;
+    @Autowired
+    private BadgesRepository badgesRepository;
+    @Autowired
+    private StickersRepository stickersRepository;
+
+    @GetMapping("/login")
+    public ModelAndView getLoginPage() {
+        ModelAndView mav = new ModelAndView("rewards/login");
+//        List<User> users = userRepository.getAllUsers();
+//        mav.addObject("users", users);
+        return mav;
+    }
+
+    @GetMapping("/userList")
+    public ModelAndView userList() {
+        ModelAndView mav = new ModelAndView("towns/userData");
+        List<User> users = userRepository.getAllUsers();
+        mav.addObject("users", users);
+        return mav;
+    }
 
     @GetMapping("/user/{id}")
     public ModelAndView getUserPage(@PathVariable int id) {
         ModelAndView mav = new ModelAndView("rewards/userProfile");
-        users.stream()
-                .filter(user -> user.getId() == id)
-                .findFirst() //Convoluted way of finding the matching user to the id, probably easier to do a hashmap
-                .ifPresent(result -> mav.addObject("user", result));
+        List<Badge> badges = badgesRepository.getAllBadges(); /*DEPRECATED FOR THE MOMENT*/
         mav.addObject("badges", badges);
-        mav.addObject("stickers", stickers);
+        List<Sticker> allStickers = stickersRepository.getAllStickers();
+        List<User> users = userRepository.getAllUsers();
+        Map<Long, Boolean> userStickers = userRepository.getStickers(id);
+
+        for (Long stickerID : userStickers.keySet()) { //Finds and updates visibility of stickers based on what the user has
+            allStickers.stream()
+                    .filter(sticker -> sticker.getId()==stickerID)
+                    .findFirst().ifPresent(sticker -> sticker.setVisibility(userStickers.get(stickerID)));
+        }
+
+        mav.addObject("user", userRepository.getUser(id));
+        mav.addObject("stickers", allStickers);
         return mav;
     }
-//    @GetMapping("/userProfile")
-//    public ModelAndView getUserPage(ModelAndView mav) {
-//        return mav;
-//    }
 }
diff --git a/src/main/java/Team5/SmartTowns/users/UserRepository.java b/src/main/java/Team5/SmartTowns/users/UserRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f4e828f17c231179df1a9fcd6a87cc5c8cf75b6
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/users/UserRepository.java
@@ -0,0 +1,12 @@
+//Holds users data repository
+package Team5.SmartTowns.users;
+
+import java.util.List;
+import java.util.Map;
+
+public interface UserRepository {
+    List<User> getAllUsers();
+//    Map<Long, Integer> getBadgeProgress(int id);
+    Map<Long, Boolean> getStickers(int id);
+    User getUser(int id);
+}
diff --git a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b24461d06d300172d904272edf0cc20c51b99f0
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java
@@ -0,0 +1,69 @@
+//Implements the users repository using JDBC
+package Team5.SmartTowns.users;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class UserRepositoryJDBC implements UserRepository{
+
+    private JdbcTemplate jdbc;
+    private RowMapper<User> userMapper;
+
+    public UserRepositoryJDBC(JdbcTemplate aJdbc){
+        this.jdbc = aJdbc;
+        setUserMapper();
+    }
+
+
+    private void setUserMapper(){
+        userMapper = (rs, i) -> new User(
+                rs.getInt("userID"),
+                rs.getString("email"),
+                rs.getString("name"),
+                rs.getInt("dragonProgress")
+        );
+    }
+
+    @Override
+    public List<User> getAllUsers(){
+        String sql= "SELECT * FROM users";
+        return jdbc.query(sql, userMapper);
+    }
+
+    @Override
+    public User getUser(int id){
+        String sql= "SELECT * FROM users WHERE userID="+id;
+        List<User> result = jdbc.query(sql, userMapper);
+        return result.get(0);
+    }
+
+    @Override
+    public Map<Long, Boolean> getStickers(int id){
+        String sql = "SELECT stickerID, hasSticker FROM stickerprogress WHERE userID=" + id;
+        List<Map<String, Object>> query = jdbc.queryForList(sql);
+        Map<Long, Boolean> progress = new HashMap<>();
+        for (Map<String, Object> result : query) {
+            progress.put((Long)result.get("stickerID"), (boolean)result.get("hasSticker"));
+        }
+        return progress;
+    }
+
+
+//    @Override
+//    public Map<Long, Integer> getBadgeProgress(int id){
+//        String sql = "SELECT badgeID, progress FROM badgeprogress WHERE userID=" + id;
+//        List<Map<String, Object>> query = jdbc.queryForList(sql);
+//        Map<Long, Integer> progress = new HashMap<>();
+//        for (Map<String, Object> result : query) {
+//            progress.put((Long)result.get("badgeID"), (int)result.get("progress"));
+//        }
+//        return progress;
+//    }
+}
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
index 13137e1537cdf71c3ea608325401c3e70c58cfa4..e40208ba343bab8aeb675e792a3566fd0e573028 100644
--- a/src/main/resources/data.sql
+++ b/src/main/resources/data.sql
@@ -1,6 +1,6 @@
 delete from users;
-insert into users (userID, Name) value ('1', 'Hannah');
-insert into users (userID, Name) value ('2', 'Nigel');
+insert into users (email, name, dragonProgress) value ('hannah@gmail.com', 'Hannah', '90');
+insert into users (userID, email, name, dragonProgress) value ('2', 'nigel@gmail.com', 'Nigel', '40');
 
 delete from trails;
 insert into trails ( Name) value ( 'Caerphilly Coffee Trail');
@@ -30,5 +30,28 @@ insert into locations ( locationName , locationEmail,locationDescription,locatio
 insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201);
 
 
-insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID) value ( 'The Esplanade','','Location description here','Penarth',0301);
-insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301);
+insert into locations (locationID, locationName , locationEmail,locationDescription,locationPlace, locationTrailID) value (19, 'The Esplanade','','Location description here','Penarth',0301);
+insert into locations (locationID, locationName , locationEmail,locationDescription,locationPlace, locationTrailID) value (20, 'The Old Swimming Baths','','Location description here','Penarth',0301);
+delete from badges;
+insert into badges (name, description, difficulty) value ('TownConnoisseur', 'You know the town very well!', '2');
+insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+insert into badges (name, description, difficulty) value ('TownMaster', 'You visited the town 7 days in a row!', '1');
+insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+insert into badges (name, description, difficulty) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+
+delete from stickers;
+insert into stickers (name, description, rarity) value ('TownConnoisseur', 'You know the town very well!', '2');
+insert into stickers (name, description, rarity) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+insert into stickers (name, description, rarity) value ('TownMaster', 'You visited the town 7 days in a row!', '1');
+insert into stickers (name, description, rarity) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+insert into stickers (name, description, rarity) value ('TownRegular', 'You visited the town 3 days in a row!', '1');
+
+delete from badgeprogress;
+insert into badgeprogress (userID, badgeID, progress) value ('1', '1', '40');
+insert into badgeprogress (userID, badgeID, progress) value ('1', '2', '70');
+insert into badgeprogress (userID, badgeID, progress) value ('2', '2', '70');
+
+delete from stickerprogress;
+insert into stickerprogress (userID, stickerID, hasSticker) value ('1', '1', true);
+insert into stickerprogress (userID, stickerID, hasSticker) value ('1', '3', true);
+insert into stickerprogress (userID, stickerID, hasSticker) value ('2', '2', true);
\ No newline at end of file
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index abb296cb3ddc14856259de8efe5819cabb19f505..92b8d4e0377d6ceeb58aef53b35e946670b6bc62 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -4,6 +4,7 @@ create table if not exists trails
     trailID bigint auto_increment primary key,
     name varchar(128)
 )   engine=InnoDB;
+
 drop table if exists locations;
 
 create table if not exists locations
@@ -15,9 +16,45 @@ create table if not exists locations
     locationPlace varchar(255),
     locationTrailID varchar(128)
 )   engine=InnoDB;
+
 drop table if exists users;
 create table if not exists users
 (
     userID bigint auto_increment primary key,
-    name varchar(128)
+    email varchar(128),
+    name varchar(128),
+    dragonProgress int
+) engine=InnoDB;
+
+drop table if exists badges;
+create table if not exists badges
+(
+    badgeID bigint auto_increment primary key,
+    name varchar(128),
+    description varchar(128),
+    difficulty bigint
+) engine=InnoDB;
+
+drop table if exists stickers;
+create table if not exists stickers
+(
+    stickerID bigint auto_increment primary key,
+    name varchar(128),
+    description varchar(128),
+    rarity bigint
+) engine=InnoDB;
+
+drop table if exists badgeProgress;
+create table if not exists badgeProgress
+(
+    userID bigint,
+    badgeID bigint,
+    progress int /*0-100*/
+) engine=InnoDB;
+
+create table if not exists stickerProgress
+(
+    userID bigint,
+    stickerID bigint,
+    hasSticker boolean /*Has sticker or not*/
 ) engine=InnoDB;
\ No newline at end of file
diff --git a/src/main/resources/static/css/userProfile.css b/src/main/resources/static/css/userProfile.css
index d59daa0689371b0adb2a204035b6a42d89dadab3..8ceb77b4e82d8c44f9aefdcf9c1f54493771e668 100644
--- a/src/main/resources/static/css/userProfile.css
+++ b/src/main/resources/static/css/userProfile.css
@@ -1,4 +1,17 @@
 /* AUTHOR: Gabriel Copat*/
+@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
+
+/*COLOUR PALETTE*/
+* {
+    --main-colour: #e47201;
+    --secondary-colour: #e47201;
+    --accent-colour: #e47201;
+    --accent-border: #b25901;
+
+    --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
+}
+
 
 /*FONTS, TYPOGRAPHY & BACKGROUNDS*/
 * {
@@ -12,6 +25,10 @@
         color: white;
         text-justify: inter-word;
     }
+    & label {
+        color: white;
+    }
+
 }
 @media only screen and (max-device-width: 500px) {
     /*ADJUSTING FOR SMALLER SCREENS*/
@@ -22,8 +39,11 @@
 }
 
 body {
-    background: linear-gradient(135deg, #9f74be, #3e126b);
+    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%);
@@ -35,9 +55,9 @@ main {
     margin-top: 6em;
     padding-inline: 1vw;
     box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
-}
 
 
+}
 .userInfo {
     display: flex;
     flex-direction: column;
@@ -170,10 +190,12 @@ main {
     }
     & h1 {
         font-size: 3em;
+        font-family: 'MedievalSharp', cursive;
+        letter-spacing: 1vw;
         box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw;
         border-bottom: #36454F solid 2px;
         border-top: #36454F solid 2px;
-        margin-inline: 25%;
+        margin-inline: 15%;
         margin-bottom: 1%;
     }
     & .dragonContainer {
@@ -227,4 +249,115 @@ header .footerButton {
 }
 header .footerButton:hover {
     background-color: #36454F;
+}
+
+.grayedOut {
+    filter: grayscale(1);
+}
+
+.solidBg {
+    background: #1e1e1e;
+    display: flex;
+}
+.loginWrapper {
+    margin-inline: auto;
+    margin-block: 5svh;
+    display: flex;
+    text-align: center;
+    justify-content: center;
+    background: rgba(196, 92, 239, 0.75);
+    padding: 2em;
+    flex: 0 0;
+    border-radius: 1vw;
+    box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
+    & h2 {
+        margin-left: 0;
+        margin-right: auto;
+        margin-bottom: 0.5em;
+    }
+    & form{
+        margin-block: auto;
+        font-size: 3em;
+        display: flex;
+        flex-direction: column;
+    }
+    & label {
+        position: relative;
+        margin-top: 1em;
+        /*width: fit-content;*/
+        font-size: 0.8em;
+        & b {
+            float: left;
+        }
+        & a {
+            position: absolute;
+            font-size: 0.4em;
+            right: 0.2em;
+            bottom: 0.2em;
+            height: fit-content;
+        }
+
+    }
+    & input {
+        font-size: 0.6em;
+        height: 1.5em;
+        width: 40vw;
+        border-radius: 0.2em;
+        padding-inline: 0.4em;
+        border: transparent solid 0.1em;
+        margin-bottom: 1em;
+    }
+    & button {
+        font-size: 1em;
+        height: 2em;
+        width: 4em;
+        box-shadow: var(--accent-shadow);
+        margin:auto;
+        margin-top: 1em;
+        background-color: var(--accent-colour);
+        border: 0.1em solid var(--accent-border);
+        border-radius: 1em;
+        color: white;
+
+    }
+    & button: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 0000000000000000000000000000000000000000..929b8b61e7a6f0f71a97937b2bdf2fcd83a5ce4f
--- /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
new file mode 100644
index 0000000000000000000000000000000000000000..9c7aea8b67c0d18e2910b8c067ea576899fa6340
--- /dev/null
+++ b/src/main/resources/templates/rewards/login.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>User Log In</title>
+    <link rel="stylesheet" th:href="@{/css/userProfile.css}">
+
+</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>
+            </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>
+
+</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 bd502cfc61f804533f7195de53ef812187d3f0ec..a193bf7614603637614dd0cfdc0974fdd8c44767 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,9 +37,9 @@
             </div>
         </article>
         <article class="dragonProgression">
-            <h1>The Dragon Trail</h1>
+            <h1>The Dragon's Tale</h1>
             <div class="dragonContainer">
-                <div class="dragonFill">
+                <div class="dragonFill" th:style="'width:'+ ${user.getDragonProgress()} + '%;'">
                     <img th:src="@{/images/rewards/dragonFilled.png}"
                          alt="Filled Dragon" id="FilledDragon" class="dragonImg">
                 </div>
@@ -48,12 +48,12 @@
                          alt="Outline Dragon" id="OutlineDragon" class="dragonImg">
                 </div>
             </div>
-            <h2>40%</h2>
+            <h2 th:text="${user.getDragonProgress()} + '%'"></h2>
         </article>
         <article id="stickersBox"> <!--Need a controller to show earned stickers -->
             <h2> STICKERS! </h2>
             <div class="stickersContainer">
-                <img class="stickerImg"  th:each="sticker : ${stickers}" th:src="@{'../' + ${sticker.getImgPath()}}"
+                <img th:class="'stickerImg ' + ${sticker.getVisibility()}"  th:each="sticker : ${stickers}" th:src="@{'../' + ${sticker.getImgPath()}}"
                      th:id="'img' + ${sticker.getId()}" th:alt="${sticker.getName()}" >
             </div>
         </article>
@@ -67,10 +67,7 @@
 </footer>
 
 
-
+<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