diff --git a/src/main/java/com/pixels/adapters/UserAdapter.java b/src/main/java/com/pixels/adapters/UserAdapter.java index 7e35914..3745dbf 100644 --- a/src/main/java/com/pixels/adapters/UserAdapter.java +++ b/src/main/java/com/pixels/adapters/UserAdapter.java @@ -22,7 +22,6 @@ public class UserAdapter implements JsonSerializer { JsonObject json = new JsonObject(); json.addProperty("user", src.getUsername()); - json.addProperty("email", src.getEmail()); json.addProperty("balance", src.getBalance()); List list = new ArrayList<>(); diff --git a/src/main/java/com/pixels/beans/User.java b/src/main/java/com/pixels/beans/User.java index 8d1681a..51eff60 100644 --- a/src/main/java/com/pixels/beans/User.java +++ b/src/main/java/com/pixels/beans/User.java @@ -25,12 +25,6 @@ public class User implements Serializable { @NotBlank private String username; - // addresse mail de l'utilisateur - @NonNull - @NotBlank - @Column(unique = true) - private String email; - // mot de passe hashé en sha256 @NonNull @NotBlank @@ -44,11 +38,11 @@ public class User implements Serializable { @NotNull private Integer balance = 0; + @Column(unique = true) private transient String sessionID; - public User(String username, String email, String password) { + public User(String username, String password) { this.username = username; - this.email = email; this.password = Hash.sha256(password); } diff --git a/src/main/java/com/pixels/services/PixelService.java b/src/main/java/com/pixels/services/PixelService.java index 5af7c61..630cf0d 100644 --- a/src/main/java/com/pixels/services/PixelService.java +++ b/src/main/java/com/pixels/services/PixelService.java @@ -33,7 +33,7 @@ public class PixelService { @PersistenceContext private EntityManager em; - Gson gson = new GsonBuilder() + private final Gson gson = new GsonBuilder() .registerTypeAdapter(Pixel.class, new PixelAdapter()) .registerTypeAdapter(User.class, new UserAdapter()) .create(); @@ -83,21 +83,30 @@ public class PixelService { User user = User.fromSessionID(cookie.getValue(), em); if (user.getBalance() >= pixel.getPrice() && pixel_json.getPrice() > pixel.getPrice()) { + // on récupère l'ancien owner + User old_owner = pixel.getOwner(); + // on update le pixel pixel.setOwner(user); pixel.setColor(pixel_json.getColor()); pixel.setDescription(pixel_json.getDescription()); pixel.setPrice(pixel_json.getPrice()); - // on débite le user - user.setBalance(user.getBalance() - pixel_json.getPrice()); + //Si le user possède le pixel on le débite pas + if (old_owner.getUsername().equals(user.getUsername())){ + // on débite le user + user.setBalance(user.getBalance() - pixel_json.getPrice()); + + // on crédite l'ancien owner + old_owner.setBalance(old_owner.getBalance() + pixel_json.getPrice()); + } // on ajoute la transaction Date now = new Date(System.currentTimeMillis()); Transaction new_transaction = new Transaction(now, pixel); em.persist(new_transaction); - // on update le pixel dans la db + // on commit les modifs dans la db em.merge(pixel); em.merge(user); } diff --git a/src/main/java/com/pixels/services/UserService.java b/src/main/java/com/pixels/services/UserService.java index 1bd3293..9e4f3ad 100644 --- a/src/main/java/com/pixels/services/UserService.java +++ b/src/main/java/com/pixels/services/UserService.java @@ -14,6 +14,7 @@ import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.FormParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Cookie; import javax.ws.rs.core.MediaType; @@ -34,13 +35,24 @@ public class UserService { private final Logger LOGGER = Logger.getLogger("UserService"); - Gson gson = new GsonBuilder() + private final Gson gson = new GsonBuilder() .registerTypeAdapter(Pixel.class, new PixelAdapter()) .registerTypeAdapter(User.class, new UserAdapter()) .create(); @GET @Produces(MediaType.APPLICATION_JSON) + public String myself(@CookieParam("JSESSIONID") Cookie cookie) { + // on trouve l'utilisateur connecté via son sessionID + User user = User.fromSessionID(cookie.getValue(), em); + + // on renvoie les informations + return gson.toJson(user); + } + + @GET + @Path("list") + @Produces(MediaType.APPLICATION_JSON) public String list() { TypedQuery query = em.createNamedQuery("User.list", User.class); return gson.toJson(query.getResultList()); @@ -61,15 +73,17 @@ public class UserService { @POST @Path("signup") - @Consumes(MediaType.APPLICATION_JSON) - public void signup(@CookieParam("JSESSIONID") Cookie cookie, String json) { - User json_user = gson.fromJson(json, User.class); - User new_user = new User( - json_user.getUsername(), - json_user.getEmail(), - json_user.getPassword()); + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public void signup(@CookieParam("JSESSIONID") Cookie cookie, @FormParam("username") String username, @FormParam("password") String password) { + // on créé un utilisateur + User new_user = new User(username, password); + + // on associe aussi le sessionID de l'utilisateur new_user.setSessionID(cookie.getValue()); + + // on commit les modifs dans la db em.persist(new_user); + LOGGER.info("new user: " + new_user.getUsername()); } @@ -79,8 +93,9 @@ public class UserService { public void login(@CookieParam("JSESSIONID") Cookie cookie, String json) { User user; try { - // si on trouve l'utilsateur via son sessionID + // si on trouve l'utilisateur via son sessionID user = User.fromSessionID(cookie.getValue(), em); + LOGGER.info(user.getUsername() + " already logged in"); // TODO: renvoyer un json avec les creds } catch (NoResultException e) { @@ -92,8 +107,12 @@ public class UserService { // si les identifiants sont valides if (user.validPassword(json_user.getPassword())) { + // on enregistre son sessionID user.setSessionID(cookie.getValue()); + + // on commit les modifs dans la db em.merge(user); + LOGGER.info(user.getUsername() + " logged in"); } else { LOGGER.info("incorrect creds for " + user.getUsername()); @@ -105,8 +124,15 @@ public class UserService { @Path("logout") public void logout(@CookieParam("JSESSIONID") Cookie cookie) { try { + // on trouve l'utilisateur connecté via son sessionID User user = User.fromSessionID(cookie.getValue(), em); + + // on supprime le sessionID user.setSessionID(null); + + // on commit les modifs dans la db + em.merge(user); + LOGGER.info(user.getUsername() + " logged out"); } catch (NoResultException e) { LOGGER.info("user not logged in, cannot logout"); diff --git a/src/main/webapp/buy_pixel.js b/src/main/webapp/buy_pixel.js new file mode 100644 index 0000000..d0bce12 --- /dev/null +++ b/src/main/webapp/buy_pixel.js @@ -0,0 +1,61 @@ +var urlPixel = "http://localhost:8080/api/pixel"; + +// var pixelsJSON; + +// const updatePixelsJSON = async () => { +// var reponse = await fetch(urlPixel); +// pixelsJSON = await reponse.json(); +// } + +// Initialize pixel index +function initBuyPixel() { + var pixel_index = 0; + + var pixel = pixelsJSON[pixel_index]; + updatePixelBuyPreview(pixel); +} + +// Compute next pixel index +function nextBuyPixel() { + var pixel_index = document.getElementById("buy-pixel-index").value; + + var table = document.getElementById("pixelTable"); + var number_rows = table.rows.length; + + pixel_index++; + if (pixel_index > number_rows * number_rows - 1) { + pixel_index = 0; + } + + var pixel = pixelsJSON[pixel_index]; + updatePixelBuyPreview(pixel); +} + +// Compute previous pixel index +function previousUserPixel() { + var pixel_index = document.getElementById("buy-pixel-index"); + + var table = document.getElementById("pixelTable"); + var number_rows = table.rows.length; + + pixel_index--; + if (pixel_index < 0) { + pixel_index = number_rows * number_rows - 1; + } + + var pixel = pixelsJSON[pixel_index]; + updatePixelBuyPreview(pixel); +} + +function updatePixelBuyPreview(pixel) { + document.getElementById("buy-pixel-index").value = pixel.id - 1; + document.getElementById("buy-pixel-owner").innerHTML = pixel.owner_username; + document.getElementById("buy-pixel-description").innerHTML = pixel.description; + document.getElementById("buy-pixel-price").innerHTML = pixel.price; +} + +// updatePixelsJSON(); +initBuyPixel(); + +// setInterval(updatePixelsJSON, 10000); + diff --git a/src/main/webapp/buypixel.css b/src/main/webapp/buypixel.css new file mode 100644 index 0000000..1caf9b9 --- /dev/null +++ b/src/main/webapp/buypixel.css @@ -0,0 +1,89 @@ +.buypixel-container .text { + font-size: 35px; + font-weight: 600; + text-align: center; +} + +.buypixel-container .solde { + font-size: 35px; + font-weight: 600; + text-align: center; + color: #fff; + border-radius: 45px; + background: -webkit-linear-gradient(right, #56d8e4, #9f01ea); +} + +.buypixel-container form { + margin-top: -20px; +} + +.buypixel-container form .data { + height: 45px; + width: 100%; + margin: 40px 0; +} + +form .data label { + font-size: 18px; +} + +form .data input { + height: 100%; + width: 100%; + padding-left: 10px; + font-size: 17px; + border: 1px solid silver; +} + +form .data input:focus { + border-color: #3498db; + border-bottom-width: 2px; +} + +form .forgot-pass { + margin-top: -8px; +} + +form .forgot-pass a { + color: #3498db; + text-decoration: none; +} + +form .forgot-pass a:hover { + text-decoration: underline; +} + +form .btn { + margin: 30px 0; + height: 45px; + width: 100%; + position: relative; + overflow: hidden; + border-radius: 45px; +} + +form .btn:hover { + box-shadow: 0px 0px 5px 5px #3333; +} + +form .btn button { + height: 100%; + width: 100%; + background: none; + border: none; + color: #fff; + font-size: 18px; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 1px; + cursor: pointer; + background: -webkit-linear-gradient(right, #56d8e4, #9f01ea); +} + +form .signup-login-link { + text-align: center; +} + +#color { + min-height: 20px; +} diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index d5a4f12..f57e38b 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -35,7 +35,7 @@
Login
-
+
@@ -62,7 +62,7 @@
Signup
- +
diff --git a/src/main/webapp/index2.html b/src/main/webapp/index2.html index ef79773..40997c9 100644 --- a/src/main/webapp/index2.html +++ b/src/main/webapp/index2.html @@ -10,6 +10,7 @@ + @@ -54,6 +66,7 @@ + @@ -67,6 +80,7 @@
+
@@ -96,42 +110,76 @@
-
My pixels

+
+
+ (
)
-
- - -
- +
- +
- +
- +
+
+
+ +
+
+ +
+
+
+
+ +
+ Buy pixel +
+
+
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
@@ -165,6 +213,7 @@
+ diff --git a/src/main/webapp/modify_pixel.js b/src/main/webapp/modify_pixel.js index 910553b..cbb847f 100644 --- a/src/main/webapp/modify_pixel.js +++ b/src/main/webapp/modify_pixel.js @@ -1,7 +1,18 @@ -var url = "http://localhost:8080/api/pixel"; +var urlPixel = "http://localhost:8080/api/pixel"; +var urlUser = "http://localhost:8080/api/user"; -var reponse; var pixelsJSON; +var userJSON; + +const updatePixelsJSON = async () => { + var reponse = await fetch(urlPixel); + pixelsJSON = await reponse.json(); +} + +const updateUserJSON = async () => { + var reponse = await fetch(urlUser); + userJSON = await reponse.json(); +} function hexToRgb(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); @@ -13,68 +24,82 @@ function hexToRgb(hex) { } : null; } -function nextPixel() { - var index = document.getElementById("color").value - 1; +// Initialize pixel index +function initUserPixel() { + var user_pixel_index = 0; + var pixel_index = userJSON.pixels[user_pixel_index].id - 1; - var table = document.getElementById("pixelTable"); - var num_rows = table.rows.length; + document.getElementById("user-pixel-index").innerHTML = user_pixel_index; + document.getElementById("pixel-index").innerHTML = pixel_index; - index++; - if (index > num_rows * num_rows - 1) { - index = 0; - } - - document.getElementById("color").value = index + 1; - - updateInfo(); + updatePixelPreview(); } -function previousPixel() { - var index = document.getElementById("color").value - 1; +// Compute next pixel index +function nextUserPixel() { + var user_pixel_index = parseInt(document.getElementById("user-pixel-index").innerHTML); - var table = document.getElementById("pixelTable"); - var num_rows = table.rows.length; - - index--; - if (index < 0) { - index = num_rows * num_rows - 1; + user_pixel_index++; + if (user_pixel_index > userJSON.pixels.length - 1) { + user_pixel_index = 0; } - document.getElementById("color").value = index + 1; + var pixel_index = userJSON.pixels[user_pixel_index].id - 1; - updateInfo(); + document.getElementById("user-pixel-index").innerHTML = user_pixel_index; + document.getElementById("pixel-index").innerHTML = pixel_index; + + updatePixelPreview(); } -function updateInfo() { +// Compute previous pixel index +function previousUserPixel() { + var user_pixel_index = parseInt(document.getElementById("user-pixel-index").innerHTML); + + user_pixel_index--; + if (user_pixel_index < 0) { + user_pixel_index = userJSON.pixels.length - 1; + } + + var pixel_index = userJSON.pixels[user_pixel_index].id - 1; + + document.getElementById("user-pixel-index").innerHTML = user_pixel_index; + document.getElementById("pixel-index").innerHTML = pixel_index; + + updatePixelPreview(); +} + +function updatePixelPreview() { var colorDiv = document.getElementById("color"); - var index = colorDiv.value - 1; + var index = parseInt(document.getElementById("pixel-index").innerHTML); var pixel = pixelsJSON[index]; + // Update price var price = document.getElementById("price"); price.value = pixel.price; + // Update color var red = document.getElementById("red"); var green = document.getElementById("green"); var blue = document.getElementById("blue"); - console.log(pixel.color); var color = hexToRgb(pixel.color); - console.log(color); red.value = color.r; green.value = color.g; blue.value = color.b; - colorDiv.style.color = 'rgb(' + (255 - color.r) + ',' + (255 - color.g) + ',' + (255 - color.b) + ')'; - colorDiv.style.background = 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')'; + updateUserColorPreview(); + + // Update description var description = document.getElementById("description"); description.value = pixel.description; - updateColor(); } -function updateColor() { +// Update preview's color +function updateUserColorPreview() { var red = document.getElementById("red").value * 255 / 100; var green = document.getElementById("green").value * 255 / 100; var blue = document.getElementById("blue").value * 255 / 100; @@ -83,13 +108,11 @@ function updateColor() { color.style.background = "rgb(" + red + "," + green + "," + blue + ")"; } -const updatePixelsJSON = async () => { - reponse = await fetch(url); - pixelsJSON = await reponse.json(); -} - updatePixelsJSON(); -setInterval(updatePixelsJSON, 10000); +updateUserJSON(); + +initUserPixel(); + +setInterval(updatePixelsJSON, 10000); +setInterval(updateUserJSON, 10000); -updateColor(); -updateInfo(); diff --git a/src/main/webapp/mypixel.css b/src/main/webapp/mypixel.css index 3c9842c..c5c9100 100644 --- a/src/main/webapp/mypixel.css +++ b/src/main/webapp/mypixel.css @@ -84,6 +84,6 @@ form .signup-login-link { text-align: center; } -.color { +#color { min-height: 20px; } diff --git a/src/main/webapp/profil.css b/src/main/webapp/profil.css index d907e2a..601714a 100644 --- a/src/main/webapp/profil.css +++ b/src/main/webapp/profil.css @@ -102,6 +102,39 @@ color: #3498db; } +.buypixel-container { + --width: 410px; + display: none; + visibility: visible; + background: #fff; + width: var(--width); + margin: 30px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); + position: absolute; + left: calc(50% - var(--width) / 2); + top: 30%; + padding: 20px; + border-radius: 10px; + box-shadow: 0px 0px 5px #000; + +} + +#show-buypixel:checked~.buypixel-container { + display: block; +} + +.buypixel-container .close-btn { + position: absolute; + right: 20px; + top: 15px; + font-size: 18px; + cursor: pointer; +} + +.buypixel-container .close-btn:hover { + color: #3498db; +} + .settings-container { --width: 410px; @@ -139,10 +172,11 @@ .wallet-btn, .mypixel-btn, +.buypixel-btn, .settings-btn { background: #fff; margin: 10px 10px; padding: 10px 10px; color: #3498db; cursor: pointer; -} \ No newline at end of file +}