diff --git a/build.gradle b/build.gradle index 0bdcc02bb2a5367c58f9bb20ef3f61c21057242b..98ebc21ecb6ff501ad19fbb802c684c4ec3b3f93 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,10 @@ dependencies { tasks.named('bootBuildImage') { builder = 'paketobuildpacks/builder-jammy-base:latest' } +test { + useJUnitPlatform() +} tasks.named('test') { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/src/main/java/Team5/SmartTowns/users/UserController.java b/src/main/java/Team5/SmartTowns/users/UserController.java index 989d13b7161f783dc75bdcb9dbf379808b1584e4..a80f139bd0d2ee069f2116c463f3392e029793fe 100644 --- a/src/main/java/Team5/SmartTowns/users/UserController.java +++ b/src/main/java/Team5/SmartTowns/users/UserController.java @@ -8,6 +8,7 @@ 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.web.servlet.ModelAndView; import java.util.List; @@ -17,32 +18,36 @@ public class UserController { @Autowired private UserRepository userRepository; + @Autowired private RewardsRepository rewardsRepository; + /* LOGIN MAPPING & FUNCTIONS */ @GetMapping("/login") public ModelAndView getLoginPage() { ModelAndView mav = new ModelAndView("users/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); + @PostMapping("/login/register") + public ModelAndView registerUser(String[] userInfo) { + /* TODO CHECK IS USER ALREADY EXISTS */ + + /* TODO CALL FUNCTION HERE TO CRATE USER IN THE DATABASE */ + + ModelAndView mav = new ModelAndView("users/login"); return mav; } + /* USER MAPPING & FUNCTIONS */ @GetMapping("/user/{id}") public ModelAndView getUserPage(@PathVariable int id) { ModelAndView mav = new ModelAndView("users/userProfile"); List<Pack> allPacks = rewardsRepository.getAllPacks(); mav.addObject("user", userRepository.getUserById(id)); mav.addObject("packs", allPacks); - + userRepository.addUser("Maria", "MariaEmail", "MariaPassword"); + userRepository.doesUserExist("MariaEmail"); mav.addAllObjects(getPackInfo(id, 1).getModelMap()); return mav; @@ -86,4 +91,7 @@ public class UserController { return displayedStickers; } + + + } diff --git a/src/main/java/Team5/SmartTowns/users/UserRepository.java b/src/main/java/Team5/SmartTowns/users/UserRepository.java index f0f01269786128dd9afaa8d3becd5b3ada4944fa..9fdf4bac8acf480e42ffdecdf21787dd6e68c8cd 100644 --- a/src/main/java/Team5/SmartTowns/users/UserRepository.java +++ b/src/main/java/Team5/SmartTowns/users/UserRepository.java @@ -8,4 +8,6 @@ public interface UserRepository { List<Long> getUserStickersFromPack(int userID, int packID); User getUserById(int userID); boolean unlockSticker(int userID, int packID, int stickerID); + boolean addUser(String username, String email, String password); + boolean doesUserExist(String email); } diff --git a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java index 8b46fc3a568455e91c180b66fc91b65f20d20c81..94ed236172042ec4bdaaee9991cfe277efd391e8 100644 --- a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java +++ b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java @@ -3,8 +3,13 @@ package Team5.SmartTowns.users; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.object.SqlQuery; import org.springframework.stereotype.Repository; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.HashMap; import java.util.List; @@ -48,9 +53,20 @@ public class UserRepositoryJDBC implements UserRepository{ @Override public boolean unlockSticker(int userID, int packID, int stickerID){ - String sql = "INSERT INTO stickerprogress (userID, packID, stickerID) VALUES (" + - userID + ", " + packID + "," + stickerID + ")"; - jdbc.update(sql); + String sql = "INSERT INTO stickerprogress (userID, packID, stickerID) VALUES (?,?,?)"; + jdbc.update(sql, userID, packID, stickerID); return true; } + + @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; + } + public boolean doesUserExist(String email){ + String query = "SELECT COUNT(email) FROM users WHERE (email) = (?)"; + return !(jdbc.queryForObject(query, Integer.class, email) == 0); + } + } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index b5908000f5460b1c03f7531b5615a19f9c5e5d01..e696d3093eb1f3e59951992d1eeeccb724197ff2 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -26,7 +26,7 @@ drop table if exists stickerProgress; create table if not exists users ( id bigint auto_increment primary key, - email varchar(128), + email varchar(128) NOT NULL , name varchar(30), dragonProgress int, dragonsLandmarkIDs longtext diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index 08273bc1bba5a74c518361f71f7d88bb53774811..e39ea2ad0a52a0073a365c88eab6dde15fbde7be 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -1,210 +1,76 @@ * { - box-sizing: border-box; - padding: 0; - margin: 0; + margin: 0; + padding: 0; + box-sizing: border-box; } -#homeHead{ - color: inherit; - text-decoration: none; - padding: 0; - margin: 0;} +* { + /*COLOUR PALETTE*/ + @media (prefers-color-scheme: dark) { + --primary-darker: hsl(272, 100%, 10%); + --primary-dark: hsl(271, 100%, 20%); + --primary-colour: hsl(271, 100%, 30%); + --primary-light: hsl(271, 100%, 40%); + --primary-lighter: hsl(271, 100%, 50%); + + --secondary-colour: hsl(12, 81%, 46%); + --accent-colour: hsl(12, 82%, 32%); + --accent-border: hsl(12, 81%, 25%); + + --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; + + color: white; -.center { - text-align: center; -} -body { - background-color: rgb(41, 41, 41); - margin: 0%; -} -.headerBlock { - background-color: rgb(15, 15, 15); - padding-bottom: 20px; - box-shadow: 0 10px 20px black; - .headerTitle { - text-align: center; - padding: 10px 10px 0 10px; - margin: 0 50px 0 50px; - letter-spacing: 10px; - font-size: 50px; - font-style: italic; - color: blueviolet; - text-shadow: black 3px 3px 5px; - border-bottom: 3px blueviolet solid; - } - .headerBanner { - display: flex; - flex-direction: column; - justify-content: center; - overflow: hidden; - position: relative; - height: 200px; - border-top: grey solid 2px; - border-bottom: grey solid 2px; - - .bannerBack { - opacity: 0.6; - width: 100%; - left: 0; - top: 0; - position: absolute - } - .bigTitle { - color:white; - text-align: center; - position: relative; - font-size: 50px; - margin: 20px 20px 5px; - } - .smallTitle { - position: relative; - color:white; - text-align: center; - font-size: 20px; - margin: 5px 20px 20px; - } } -} + @media (prefers-color-scheme: light) { + --primary-darker: hsl(272, 100%, 10%); + --primary-dark: hsl(271, 100%, 20%); + --primary-colour: hsl(271, 100%, 30%); + --primary-light: hsl(271, 100%, 40%); + --primary-lighter: hsl(271, 100%, 50%); + --secondary-colour: hsl(12, 81%, 46%); + --accent-colour: hsl(12, 82%, 32%); + --accent-border: hsl(12, 81%, 25%); + + --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; + + color: white; -.mainTrails{ - overflow: hidden; - position: relative; - height: 200px; - border-top: grey solid 2px; - border-bottom: grey solid 2px; -} -.trailList { - .ulHeader { - margin: 30px; - display: flex; - list-style: none; - justify-content: center; - padding: 0px; - border-bottom: solid black 5px; - - .liHeader { - - flex: 1 1 0px; - padding-left: 10px; - padding-right: 10px; - color: white; - text-align: center; - } - .liHeader:hover { - color: blueviolet; - border-bottom: solid blueviolet 2px; - } - .selected { - flex: 1 1 0px; - padding-left: 10px; - padding-right: 10px; - color: rgb(154, 69, 234); - border-bottom: solid blueviolet 2px; - text-align: center; - } } - } -.mainBlock { + +body { + background: linear-gradient(to bottom right, + var(--primary-darker), + var(--primary-dark), + var(--primary-darker)); + display: flex; - min-width: 300px; - flex-wrap: wrap; - margin-top: 20px; - margin-bottom: 100px; + flex-direction: column; + justify-content: center; + align-content: center; } -.mainBlock .trailStats{ - background-color: rgb(206, 153, 253); - flex: 0 0 0px; - min-width: 400px; - height: 600px; - margin: auto; - margin-bottom: 20px; - box-shadow: 0px 0px 20px rgb(20, 20, 20); - border-radius: 30px; - .stats { - display: block; - width: 200px; - margin: auto; - } - .textStats { - display: block; - text-align: left; - margin: 20px; - } -} -.mainBlock .trailInfo{ - background-color: rgb(206, 153, 253); - flex: 0 0 0px; - min-width: 400px; - height: 600px; - margin: auto; - margin-bottom: 20px; - box-shadow: 0px 10px 10px rgb(20, 20, 20); - border-radius: 30px; - .trailInfoTxt { - margin: 15px; + +/*PHONES PORTRAIT*/ +@media only screen +and (min-device-width: 320px) +and (max-device-width: 640px) { + body { + position: fixed; + width: 100vw; + height: 100svh; } } -.titleH1 { - padding: 0px; - margin: 10px 30px 20px 30px; - text-align: center; - font-size: 40px; - font-style: italic; - border-bottom: solid black 1px; -} -.mainBlock p { - font-size: 25px; - text-align: left; - padding: 1px; -} -main .badgesBlock{ - bottom: 0%; - background-color: rgb(222, 75, 255); - flex: 0 0 0px; - min-width: 500px; - min-height: 100px; - margin: auto; - margin-bottom: 10px; - box-shadow: 0px 10px 10px rgb(20, 20, 20); - border-radius: 30px; -} -.badgesList { - display: flex; -} -.badgeImg { - flex: 0 1 0px; - width: 60px; - margin: auto; - margin-bottom: 20px; - -} -footer { - z-index: 99; - bottom: 0%; - left: 0%; - position: fixed; - width: 100%; - min-width: 300px; -} -footer .footerBar { - display: flex; - list-style: none; - padding: 0; - margin: 0; - -} -footer .footerButton { - padding: 20px; - text-align: center; - flex: 1 1 0px; - color:crimson; - background-color: white; - +/*PHONES LANDSCAPE*/ +@media only screen +and (min-device-width: 640px) +and (max-device-width: 1000px) { + + } -footer .footerButton:hover { - background-color: black; -} \ No newline at end of file + +/*LARGER SCREENS*/ +@media only screen and (min-device-width: 1000px) {} \ No newline at end of file diff --git a/src/main/resources/static/css/userProfile.css b/src/main/resources/static/css/userProfile.css deleted file mode 100644 index 878ab054fc53828cb76726775109ca7d3f4bcc80..0000000000000000000000000000000000000000 --- a/src/main/resources/static/css/userProfile.css +++ /dev/null @@ -1,408 +0,0 @@ -/* 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*/ -* { - margin: 0; - padding: 0; - - & h1, & h2 { - letter-spacing: 0.25vw; - line-height: 1.3; - text-align: center; - color: white; - text-justify: inter-word; - } - & label { - color: white; - } - -} -@media only screen and (max-device-width: 500px) { - /*ADJUSTING FOR SMALLER SCREENS*/ - * { - & h1, & h2 { text-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1svh;} - & p { line-height: 1.1; color: white;} - } -} -html{ - height: 100%; - @media only screen and (min-device-width: 1500px) { - height: auto; - } -} -body { - background: linear-gradient(135deg, #f7e8fd, #9914d1); - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-evenly; - @media only screen and (min-device-width: 1500px) { - height: auto; - } -} -main { - background: linear-gradient(to bottom, #1e1e1e 10%, darkgoldenrod 50%, #1e1e1e 90%); - border-radius: 1vw; - margin-inline: 5%; - /*margin-block: 5%;*/ - width: auto; - padding-block: 2svh; - margin-top: 6em; - padding-inline: 1vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em); - transition: all linear 2s; - overflow-y: scroll; - height: 90%; - @media only screen and (min-device-width: 1500px) { - padding-inline: 20%; - overflow: visible; - } -} -.rewards { - position: relative; -} -.userInfo { - display: flex; - flex-direction: column; - /*padding: min(2vw, 4em);*/ - text-align: center; - - & #userPicture { - width: min(30vw, 30em); - margin-inline: auto; - border-radius: 100%; - border: solid #a2a2a2 4px; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em); - } - - & h1 { - font-size: max(5vw, 2em); - margin: 1svh 25%; - color:white; - border-bottom: #36454F solid 2px; - border-radius: 5vw; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw; - } -} -#packsBar::-webkit-scrollbar { - display: none; - -ms-scrollbar-darkshadow-color: transparent; -} -#packsBar { - position: static; - display: grid; - grid-template-areas: - "header" - "packs"; - overflow-x: scroll; - overflow-y: hidden; - color: white; - padding-bottom: 2%; - @media only screen and (min-device-width: 501px) { - height: 24vw; - } - & h2 { - position: absolute; - grid-area: header; - margin-inline: 5vw; - padding-inline: 2vw; - margin-block: -1svh; - box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw; - border-bottom: #36454F solid 2px; - font-size: 4vw; - width: 7em; - height: 1.2em; - - } - & #allPacksContainer { - margin-top: 3svh; - grid-area: packs; - height: 12svh; - width: 100%; - display: flex; - justify-content: space-between; - @media only screen and (min-device-width: 501px) { - height: 20vw; - margin-top: 6vw; - } - } - & .packContainer{ - position: relative; - height: 12svh; - width: 20vw; - display: flex; - flex-direction: column; - text-align: center; - justify-content: center; - overflow: visible; - } - - & .packImg { - position: relative; - margin-inline: 3vw; - height: 8svh; - /*width: 25%;*/ - z-index: 50; - @media only screen and (min-device-width: 501px) { - height: 15vw; - } - transition: 0.3s ease-out 100ms; - } - & .packImg:hover { - /*box-shadow: 0 0 20px 10px #bbbb00;*/ - transform: scale(1.5,1.5); - - } - & .packName { - height: 4svh; - display: flex; - justify-content: center; - font-size: 2em; - overflow: hidden; - align-items: flex-end; - - } -} - -#stickersBox { - padding-top: 5%; - display: flex; - flex-direction: column; - /* border-bottom-left-radius: 2vw; */ - /* border-bottom-right-radius: 2vw; */ - /*background: linear-gradient(to bottom, darkgoldenrod, transparent 90%);*/ - margin-top: -1%; - height: 500px; - & h2 { - font-size: 4em; - text-align: center; - box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw; - border-bottom: #36454F solid 2px; - margin-block: 1svh; - margin-inline: 25%; - } - & .stickersContainer { - margin-block: 1svh; - display: flex; - flex-wrap: wrap; - justify-content: space-around; - width: 100%; - - & .stickerImg { - width: 20vw; - margin-block: 1em; - - } - } -} -.locked { - filter: grayscale(100%); -} - -.dragonProgression { - position: relative; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - height: 16svh; - box-sizing: content-box; - /*background: linear-gradient(to bottom, transparent -50%, darkgoldenrod 50%);*/ - width: 100%; - /*padding-top: 1svh;*/ - - @media only screen and (min-device-width: 501px) { - height: 28vw; - margin-bottom: 0; - padding-bottom: 5svh; - } - & 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: 15%; - margin-bottom: 1%; - } - & .dragonContainer { - position: relative; - margin: auto; - } - & .dragonImg { - height: 10svh; - width: 16svh; - @media only screen and (min-device-width: 501px) { - height: 22vw; - width: 30vw; - } - - } - & .dragonFill { - position: absolute; - overflow: hidden; - width: 40%; - } - & .dragonOut { - /*position: absolute;*/ - overflow: hidden; - } -} -header { - z-index: 99; - top: 0.5svh; - left: 0; - position: fixed; - width: 100vw; - justify-content: center; - display: flex; -} -header .footerBar { - display: flex; - list-style: none; - border-radius: 1vw; - overflow: hidden; - justify-content: space-evenly; - background-color: rgba(0, 0, 0, 0.7); -} -header .footerButton { - padding: 1vw; - text-align: center; - /*flex: 1 1;*/ - color:crimson; - background-color: rgba(31, 31, 31, 0.7); - font-size: 2.5em; - width: 15vw; -} -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; -} - -.rewards { - transition: 1s ease-in-out 1ms; -} \ No newline at end of file diff --git a/src/main/resources/static/css/userProfile2.css b/src/main/resources/static/css/userProfile2.css index 0728cbc6e973473051420fd817d243d5d484c489..adab43219b85ba98f0db7367490dd683a58bd9cc 100644 --- a/src/main/resources/static/css/userProfile2.css +++ b/src/main/resources/static/css/userProfile2.css @@ -2,46 +2,7 @@ @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap'); -* { - margin: 0; - padding: 0; - box-sizing: border-box; - /*COLOUR PALETTE*/ - @media (prefers-color-scheme: dark) { - --primary-darker: hsl(272, 100%, 10%); - --primary-dark: hsl(271, 100%, 20%); - --primary-colour: hsl(271, 100%, 30%); - --primary-light: hsl(271, 100%, 40%); - --primary-lighter: hsl(271, 100%, 50%); - - --secondary-colour: hsl(12, 81%, 46%); - --accent-colour: hsl(12, 82%, 32%); - --accent-border: hsl(12, 81%, 25%); - - --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; - - color: white; - - } - @media (prefers-color-scheme: light) { - --primary-darker: hsl(272, 100%, 10%); - --primary-dark: hsl(271, 100%, 20%); - --primary-colour: hsl(271, 100%, 30%); - --primary-light: hsl(271, 100%, 40%); - --primary-lighter: hsl(271, 100%, 50%); - - --secondary-colour: hsl(12, 81%, 46%); - --accent-colour: hsl(12, 82%, 32%); - --accent-border: hsl(12, 81%, 25%); - - --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em; - - color: white; - - - } -} diff --git a/src/main/resources/templates/users/userProfile.html b/src/main/resources/templates/users/userProfile.html index 3e865175760bc4b0aa11c9b54aade5d312ac55b5..94f46709d0cee67223a65098a8fc077544ce0ca7 100644 --- a/src/main/resources/templates/users/userProfile.html +++ b/src/main/resources/templates/users/userProfile.html @@ -3,6 +3,7 @@ <head> <meta charset="UTF-8"> <title th:text="'VZLA Profile Page of ' + ${user.getName()}"></title> + <link rel="stylesheet" th:href="@{/css/style.css}"> <link rel="stylesheet" th:href="@{/css/userProfile2.css}"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- <link rel="stylesheet" th:href="@{/css/templatingstyle.css}">-->