Commit 4277823e by Patryk Czarnik

Obsługa koszyka

parent 1afb874a
package sklep.basket;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import sklep.model.Product;
public class Basket {
private final Map<Integer, ProductInBasket> elementy = new HashMap<>();
public synchronized void addProduct(Product product, int quantity) {
if(elementy.containsKey(product.getId())) {
// jeśli w słowniku jest już taki element, to tylko zwiększamy ilość
elementy.get(product.getId()).increaseQuantity(quantity);
} else {
// jeśli jeszcze nie ma, to tworzymy
elementy.put(product.getId(),
new ProductInBasket(product.getId(), product.getProductName(), product.getPrice(), quantity));
}
}
public synchronized void addProduct(Product product) {
// "domyślną ilością, o którą zwiększamy, jest 1"
addProduct(product, 1);
}
public synchronized void removeProduct(int productId) {
elementy.remove(productId);
}
public synchronized Collection<ProductInBasket> getElements() {
return Collections.unmodifiableCollection(elementy.values());
}
public synchronized BigDecimal getTotalValue() {
return getElements().stream()
.map(ProductInBasket::getValue)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
@Override
public synchronized String toString() {
return "Koszyk o rozmiarze " + getElements().size()
+ " i wartości " + getTotalValue();
}
}
package sklep.basket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
@Configuration
public class BasketConfiguration {
// Adnotacja Configuration powoduje, że:
// - Spring tworzy obiekt tej klasy (BasketConfiguration)
// - dla każdej meody oznaczonej @Bean uruchamia tę metodę, a jej wynik rejestruje jako bean
// - gdy typ wynikowy "znaczy dla Springa coś specjalnego", to Spring weźmie to pod uwagę,
// właśnie w ten sposób często podaje się Springowi elementy konfiguracji
@Bean
HttpSessionListener createListener() {
return new HttpSessionListener() {
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession sesja = se.getSession();
// sesja.setMaxInactiveInterval(30); // pół minuty i sesja wygasa
// System.out.println("sessionCreated " + sesja.getId());
Basket basket = new Basket();
sesja.setAttribute("basket", basket);
}
};
}
}
package sklep.basket;
import java.math.BigDecimal;
import java.util.Objects;
public class ProductInBasket {
private final int productId;
private String productName;
private BigDecimal price;
private int quantity;
public ProductInBasket(int productId, String productName, BigDecimal price, int quantity) {
this.productId = productId;
this.productName = productName;
this.price = price;
this.quantity = quantity;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getProductId() {
return productId;
}
public String getProductName() {
return productName;
}
@Override
public String toString() {
return "ElementKoszyka [productId=" + productId + ", productName=" + productName + ", price=" + price
+ ", quantity=" + quantity + "]";
}
@Override
public int hashCode() {
return Objects.hash(price, productId, productName, quantity);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProductInBasket other = (ProductInBasket) obj;
return Objects.equals(price, other.price) && productId == other.productId
&& Objects.equals(productName, other.productName) && quantity == other.quantity;
}
public BigDecimal getValue() {
return price.multiply(BigDecimal.valueOf(quantity));
}
public void increaseQuantity(int change) {
quantity += change;
}
}
......@@ -5,6 +5,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import sklep.basket.Basket;
import sklep.model.Product;
import sklep.photo.PhotoUtil;
import sklep.repository.ProductRepository;
......@@ -70,6 +71,18 @@ public class ProductController {
return "wyszukiwarka2";
}
@GetMapping("/{id}/add-to-basket")
public String addToBasket(@PathVariable("id") Integer productId,
@SessionAttribute Basket basket) {
Optional<Product> product = productRepository.findById(productId);
if(product.isPresent()) {
basket.addProduct(product.get());
} else {
System.err.println("Nieznany produkt dodawany do koszyka: " + productId);
}
return "redirect:/products";
}
@GetMapping(path="/{id}/photo", produces="image/jpeg")
@ResponseBody
public byte[] getPhoto(@PathVariable int id) {
......
......@@ -16,6 +16,7 @@
<p>Cena: <span class="product-price">${product.price}</span></p>
<p>Stawka VAT: <span class="product-price">${product.vat * 100}%</span></p>
<p class="product-description">${product.description}</p>
<div class="action"><a href="/products/${product.id}/add-to-basket">Dodaj do koszyka</a></div>
</div>
<p><a href="/products">Przejdź do listy produktów</a></p>
......
......@@ -8,6 +8,17 @@
<link rel="stylesheet" type="text/css" href="/styl.css"/>
</head>
<body>
<c:if test="${not empty basket and not empty basket.elements}">
<div class="basket">
<h4>Koszyk</h4>
<ul>
<c:forEach var="p" items="${basket.elements}">
<li>${p.productName}: ${p.quantity} × ${p.price} = <b>${p.value}</b></li>
</c:forEach>
</ul>
<p>Wartość koszyka: ${basket.totalValue}</p>
</div>
</c:if>
<h1>Wszystkie produkty</h1>
......@@ -17,6 +28,7 @@
<p>Towar <a href="/products/${product.id}" class="product-name">${product.productName}</a></p>
<p>Cena: <span class="product-price">${product.price}</span></p>
<p class="product-description">${product.description}</p>
<div class="action"><a href="/products/${product.id}/add-to-basket">Dodaj do koszyka</a></div>
</div>
</c:forEach>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment