Angular - cart-page component

Θα δημιουργήσουμε το Angular cart-page component, το οποίο θα αντιπροσωπεύει το καλάθι του χρήστη

Εάν ο χρήστης είναι συνδεδεμένος τότε, το καλάθι του θα αποθηκεύεται στη βάση δεδομένων. Αλλιώς αν είναι ανώνυμος, τότε θα αποθηκεύεται στο browser του στο localStorage.

Spring Boot

Δημιουργούμε τον πίνακα Cart στη βάση

Cart

Δημιουργούμε το σύνθετο πρωτεύον κλειδί CartPrimaryKey και το entity Cart στο springeshop.model

                
                        @Embeddable
                        public class CartPrimaryKey implements Serializable{

                           private int userId;
                           private int productId;

                           public CartPrimaryKey() {}

                           //Getters - Setters ...

                           @Override
                           public boolean equals(Object o) {
                             if (this == o) return true;
                             if (!(o instanceof CartPrimaryKey)) return false;
                             CartPrimaryKey that = (CartPrimaryKey) o;
                             return Objects.equals(getUserId(), that.getUserId()) && Objects.equals(getProductId(), that.getProductId());
                           }

                           @Override
                           public int hashCode() {
                             return Objects.hash(getUserId(), getProductId());  
                           }

                        } 
                
            
                
                        @Entity
                        @Table(name = "cart")
                        public class Cart{

                           @EmbeddedId
                           private CartPrimaryKey id;

                           @OneToOne(fetch = FetchType.LAZY)
                           @MapsId("userId")
                           private User user;

                           @OneToOne(fetch = FetchType.LAZY)
                           @MapsId("productId")
                           private Product  product;

                           @Column(name = "quantity")
                           @NotNull(message = "Please provide quantity")
                           private int  quantity;

                           @Column(name = "expiration")
                           private Timestamp  expiration;


                           public Cart() {}

                           //Getters - Setters ...

                        } 
                
            

Δημιουργούμε το CartProduct στο springeshop.model

                
                        public class CartProduct{

                           private int userId;
                           private int productId;
                           private String name;
                           private String brand ;
                           private String imageUrl;
                           private double price;
                           private int quantity;

                           public CartProduct() {}

                           //Getters - Setters ...

                        } 
                
            

Δημιουργούμε ένα repository CartRepository.

                
                        package springeshop.repositories;

                        @Repository
                        public interface CartRepository  extends JpaRepository<Cart, Integer>  {

                          @Query("select cartProduct from Cart cartProduct where cartProduct.user.id = :userid")
                          List<Cart> findUserCartProducts(@Param("userid") int userid);

                          @Query(value = "delete from Cart cartProduct where cartProduct.user.id = :userid")
                          @Modifying
                          void deleteUserCart(@Param("userid") int userid);

                          @Query(value = "select cartProduct from Cart cartProduct where cartProduct.user.id = :userid and cartProduct.product.id = :productid")
                          Cart findUserCartProductRow(@Param("userid") int userid, @Param("productid") int productid);

                          @Query(value = "delete from Cart cartProduct where cartProduct.user.id = :userid and cartProduct.product.id = :productid")
                          @Modifying
                          void deleteUserCartProductRow(@Param("userid") int userid, @Param("productid") int productid);

                          @Query(value = "insert into cart (user_id, product_id, quantity, expiration) values ( :userid, :productid, :quantity, :expiration )",nativeQuery = true))
                          void addProductToCart(@Param("userid") int userid, @Param("productid") int productid, @Param("quantity") int quantity, @Param("expiration") Timestamp expiration);

                          @Query("update Cart cartProduct set cartProduct.quantity = :quantity where cartProduct.user.id = :userid and cartProduct.product.id = :productid")
                          @Modifying
                          void updateCartProduct (@Param("userid") int userid, @Param("productid") int productid, @Param("quantity") int quantity);

                        } 
                
            

Δημιουργούμε το CartService και CartServiceImpl στο springeshop.service .

                
                        package springeshop.service;

                        public interface CartService{

                          List<Cart> findUserCartProducts(int userid);
                          boolean deleteUserCartAndIsSuccess(int userid);
                          Cart findUserCartRow(int userid, int productid);
                          boolean deleteUserCartRowAndIsSuccess(int userid, int productid);
                          boolean addProductToCartAndIsSuccess(Cart cartProduct);
                          boolean updateCartProductAndIsSuccess(int userid, int productid, int quantity);
                          boolean doesUserCartRowExist(int userid, int productid);
                        } 
                
            
                
                            package springeshop.service;

                            @Service("cartService")
                            @Transactional
                            public class CartServiceImpl implements CartService{

                              @Autowired
                              private  CartRepository cartRepository;

                              @Override
                              public List<Cart> findUserCartProducts(int userid) {
                                return userRepository.findByUsername(userName);
                              }

                              @Override
                              public deleteUserCartAndIsSuccess(int userid) {
                                 boolean isSuccess = false;

                                try {
                                  cartRepository.deleteUserCart(userid);
                                  isSuccess = true;
                                } catch (DataAccessException exception) {
                                  System.out.println(exception);
                                  isSuccess = false;
                                } 

                                return isSuccess;
                              }

                              @Override
                              public Cart findUserCartRow(int userid, int productid) {
                                return cartRepository.findUserCartProductRow(userid, productid);
                              }

                              @Override boolean deleteUserCartRowAndIsSuccess(int userid, int productid) {
                                 boolean isSuccess = false;

                                try {
                                  cartRepository.deleteUserCartProductRow(userid, productid);
                                  isSuccess = true;
                                } catch (DataAccessException exception) {
                                  System.out.println(exception);
                                  isSuccess = false;
                                } 

                                return isSuccess;
                              }

                              @Override boolean addProductToCartAndIsSuccess(Cart cartProduct) {
                                 boolean isSuccess = false;

                                try {
                                  cartRepository.save(cartProduct);
                                  isSuccess = true;
                                } catch (DataAccessException exception) {
                                  System.out.println(exception);
                                  isSuccess = false;
                                } 

                                return isSuccess;
                              }

                              @Override boolean updateCartProductAndIsSuccess(int userid, int productid, int quantity) {
                                 boolean isSuccess = false;

                                try {
                                  cartRepository.updateCartProduct(userid, productid, quantity);
                                  isSuccess = true;
                                } catch (DataAccessException exception) {
                                  System.out.println(exception);
                                  isSuccess = false;
                                } 

                                return isSuccess;
                              }

                              @Override
                              public User findById(int id) {
                                return userRepository.findById(id);
                              }
                        }
                
            

Δημιουργούμε τoν CartApiController στο πακέτο springeshop.controller

                
                            package springeshop.controller;

                            @RestController
                            @RequestMapping("/api")
                            public class CartApiController{
                        
                               @Autowired
                               private  CartService cartService;
    
                               @Autowired
                               private  UserService userService;

                               @Autowired
                               private  ProductService productService;
    
                               @Autowired
                               private  ProductImageService productImageService;

                                ...
                
            

Προσθέτουμε τη μέθοδο createCartProduct() στον CartApiController, με την οποία προσθέτουμε προϊόντα στο πίνακα Carts. O client στέλνει το ένα CartProduct, που περιέχει το id του χρήστη και του προϊόντος και άλλα στοιχεία του και τα προσθέτουμε στον πίνακα.

                
                           @RequestMapping(value = "/carts", method = RequestMethod.POST)
                           public ResponseEntity<?> createCartProduct(@RequestBody() CartProduct cartProduct{

                             User user = userService.findById(cartProduct.getUserid());
                             Product product = productService.findById(cartProduct.getProductid());

                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("Unable to create. User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             if(product == null){
                               return new ResponseEntity<>(new ErrorMessage("Unable to create. Product does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             if(cartProduct.getQuantity() < 0){
                               return new ResponseEntity<>(new ErrorMessage("Unable to create. Quantity does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             CartPrimaryKey cartProductCompositeId = new CartPrimaryKey(cartProduct.getUserid(), cartProduct.getProductid());
                             Cart cartRow =  new Cart();	
                             User user = userService.findById(cartProduct.getUserid());
                             Timestamp expiration = new Timestamp(System.currentTimeMillis());
                             cartRow.setId(cartProductCompositeId);
                             cartRow.setUser(user);
                             cartRow.setProduct(product);
                             cartRow.setQuantity(cartProduct.getQuantity());
                             cartRow.setExpiration(expiration);

                             if(cartProduct.getQuantity() < 0){
                               CartProduct cartProductCreated = new CartProduct();
                               cartProductCreated.setUserid(cartRow.getId().getUserId());
                               cartProductCreated.setProductid(cartRow.getId().getProductId());
                               cartProductCreated.setName(cartRow.getProduct().getName());
                               cartProductCreated.setBrand(cartRow.getProduct().getBrand().getName());
                               cartProductCreated.setQuantity(cartRow.getQuantity());
                               cartProductCreated.setPrice(cartRow.getProduct().getPrice());
                               return new ResponseEntity<>(cartProductCreated, HttpStatus.CREATED);
                             }

                             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
                           }               
                
            

Προσθέτουμε τη μέθοδο getUserCartProducts(), η οποία δέχεται το id του χρήστη και επιστρέφει τα προϊόντα του καλαθιού του.

                
                           @RequestMapping(value = "/carts/{userid}", method = RequestMethod.GET)
                           public ResponseEntity<?> getUserCartProducts(@PathVariable(value = "userid", required = true)) int userid{

                             User user = userService.findById(cartProduct.getUserid());

                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             List<Cart> products = cartService.findUserCartProducts(userid);
                             List<CartProduct> cartProducts = new ArrayList<>();

                             if(products == null){
                               return new ResponseEntity<>(HttpStatus.NO_CONTENT);
                             }

                             for(Cart cart : products){
                               CartProduct prod = new CartProduct();
                               prod.setUserid(cart.getId().getUserId());
                               prod.setProductid(cart.getId().getProductId());
                               prod.setName(cart.getProduct().getName());
                               prod.setBrand(cart.getProduct().getBrand().getName());
                               prod.setQuantity(cart.getQuantity());
                               prod.setPrice(cart.getProduct().getPrice());

                               ProductImage productImage = productImageService.findByProductId(prod.getProductid());
                               prod.setImageUrl(productImage.getVerySmallImageurl());
                               cartProducts.add(prod);
                             }

                             return new ResponseEntity<List<CartProduct>>(cartProducts, HttpStatus.OK);
                           }               
                
            

Προσθέτουμε τη μέθοδο getUserCartProduct(), η οποία δέχεται το id του χρήστη και προϊόντος, επιστρέφει το προϊόν αυτό.

                
                           @RequestMapping(value = "/carts/{userid}/products/{productid}", method = RequestMethod.GET)
                           public ResponseEntity<?> getUserCartProduct(@PathVariable(value = "userid", required = true)) String userid,
                                  @PathVariable(value = "productid", required = true)) String productid){

                             int usrId = Integer.parseInt(userid);
                             int prodId = Integer.parseInt(productid);

                             User user = userService.findById(usrId);
                    
                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             if(!cartService.doesUserCartRowExist(usrId, prodId)){
                               return new ResponseEntity<>(new ErrorMessage("Product does not exist" , HttpStatus.NOT_FOUND);
                             }

                             Cart cartRow = cartService.findUserCartRow(usrId, prodId);

                             CartProduct cartProduct = new CartProduct();
                             cartProduct.setUserid(cart.getId().getUserId());
                             cartProduct.setProductid(cart.getId().getProductId());
                             cartProduct.setName(cart.getProduct().getName());
                             cartProduct.setBrand(cart.getProduct().getBrand().getName());
                             cartProduct.setQuantity(cart.getQuantity());
                             cartProduct.setPrice(cart.getProduct().getPrice());

                             return new ResponseEntity<CartProduct>(cartProduct, HttpStatus.OK);
                           }               
                
            

Προσθέτουμε τη μέθοδο deleteUserCartProduct(), η οποία δέχεται το id του χρήστη και προϊόντος, διαγράφει το προϊόν από το καλάθι.

                
                           @RequestMapping(value = "/carts/{userid}/products/{productid}", method = RequestMethod.DELETE)
                           public ResponseEntity<?> deleteUserCartProduct(@PathVariable(value = "userid", required = true)) String userid,
                                  @PathVariable(value = "productid", required = true)) String productid){

                             int usrId = Integer.parseInt(userid);
                             int prodId = Integer.parseInt(productid);

                             User user = userService.findById(usrId);
                    
                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             if(!cartService.doesUserCartRowExist(usrId, prodId)){
                               return new ResponseEntity<>(new ErrorMessage("Product does not exist" , HttpStatus.NOT_FOUND);
                             }

                              if(cartService.deleteUserCartRowAndIsSuccess(usrId, prodId)){
                               return new ResponseEntity<>(HttpStatus.OK);
                             }

                             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
                           }               
                
            

Προσθέτουμε τη μέθοδο updateCartProduct(), η οποία δέχεται το id του χρήστη και προϊόντος και ενημερώνουμε την ποσότητα του προϊόντος.

                
                           @RequestMapping(value = "/carts/{userid}/products/{productid}", method = RequestMethod.PATCH)
                           public ResponseEntity<?> updateCartProduct(@PathVariable(value = "userid", required = true)) String userid,
                                  @PathVariable(value = "productid", required = true)) String productid){

                             int usrId = Integer.parseInt(userid);
                             int prodId = Integer.parseInt(productid);

                             User user = userService.findById(usrId);
                             Product product = productService.findById(prodId);
                    
                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                              if(product == null){
                               return new ResponseEntity<>(new ErrorMessage("Product does not exist" , HttpStatus.BAD_REQUEST);
                             }


                             if(cartProduct.getQuantity() <> 0){
                               return new ResponseEntity<>(new ErrorMessage("Quantity cannot be negative" , HttpStatus.BAD_REQUEST);
                             }

                             int oldQuantity = cartService.findUserCartRow(usrId, prodId).getQuantity();
                             if(oldQuantity != cartProduct.getQuantity()){
                               if(cartService.updateCartProductAndIsSuccess(usrId, prodId, cartProduct.getQuantity())){
                                 return new ResponseEntity<>(HttpStatus.OK);	
                               }else{
                                 return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);	
                               }
                    }
                             }

                             return new ResponseEntity<>(HttpStatus.INTERNAL_OK);
                           }               
                
            

Προσθέτουμε τη μέθοδο deleteUserCart(), η οποία δέχεται το id του χρήστη και διαγράφει το καλάθι του.

                
                           @RequestMapping(value = "/carts/{userid}/products/{productid}", method = RequestMethod.DELETE)
                           public ResponseEntity<?> deleteUserCart(@PathVariable(value = "userid", required = true)) String userid){

                             int usrId = Integer.parseInt(userid);
                             User user = userService.findById(usrId);
                    
                             if(user == null){
                               return new ResponseEntity<>(new ErrorMessage("User does not exist" , HttpStatus.BAD_REQUEST);
                             }

                             if(cartService.findUserCartProducts(usrId).isEmpty()){
                               return new ResponseEntity<>(new ErrorMessage("Cart is empty" , HttpStatus.BAD_REQUEST);
                             }

                              if(cartService.deleteUserCartAndIsSuccess(usrId)){
                               return new ResponseEntity<>(HttpStatus.OK);
                             }

                             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
                           }               
                
            
Angular

Δημιουργούμε το component cart-page και το service cart.

                
                        ng generate component cart-page
                
            
                
                        ng generate service cart
                
            

Δημιουργούμε ένα μοντέλο CartProduct

Cart Product

cart.service.ts

Όταν ο χρήστης είναι συνδεδεμένος, το καλάθι αποθηκεύται στη βάση.

Cart Service

Όταν ο χρήστης δεν είναι συνδεδεμένος, το καλάθι αποθηκεύεται στο localStorage ως String

Cart Appearance Cart Service

Προσθέτουμε τη μέθοδο addProductsToCart() στο ProductPageComponent, ώστε προσθέτει ο χρήστης προιόντα στο καλάθι

Product Page

cart-page.component.ts

Cart Page Ts

cart-page.component.html

Cart Page Html

cart-page.component.css

Cart Page Css

Εμφάνιση σελίδας

Cart Page Appearnce