From 1b8d613df88e0eadcacb6aea5dba0fed9a7e8872 Mon Sep 17 00:00:00 2001 From: Henry Joerg Date: Fri, 5 Jan 2024 21:27:52 +0100 Subject: [PATCH] WIP --- .../shopibackend/controller/CartController.kt | 7 +- .../kotlin/ch/bbw/shopibackend/model/Cart.kt | 2 +- .../shopibackend/repository/CartRepository.kt | 20 +++++- .../bbw/shopibackend/service/CartService.kt | 15 ++-- .../db/migration/V3__create_cart_table.sql | 2 +- shopi-frontend/package.json | 1 - .../components/ShoppingCart/ShoppingCart.tsx | 72 ++++++++++++++++--- shopi-frontend/src/helpers/cartHelpers.ts | 15 ++++ 8 files changed, 111 insertions(+), 23 deletions(-) diff --git a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/controller/CartController.kt b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/controller/CartController.kt index 4ce4ca3..5fd9970 100644 --- a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/controller/CartController.kt +++ b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/controller/CartController.kt @@ -2,6 +2,7 @@ package ch.bbw.shopibackend.controller import ch.bbw.shopibackend.SimpleProduct import ch.bbw.shopibackend.model.Cart +import ch.bbw.shopibackend.model.CartItem import ch.bbw.shopibackend.service.CartService import org.springframework.web.bind.annotation.* @@ -21,8 +22,8 @@ class CartController( cartService.addItemToCart(product, bearerToken) } - @DeleteMapping - fun deleteProduct() { - + @PutMapping + fun changeAmount(@RequestHeader("Authorization") bearerToken: String, @RequestBody cartItem: CartItem): Cart? { + return cartService.changeAmount(cartItem.product, bearerToken, cartItem.amount) } } diff --git a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/model/Cart.kt b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/model/Cart.kt index a539132..d2587aa 100644 --- a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/model/Cart.kt +++ b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/model/Cart.kt @@ -3,7 +3,7 @@ package ch.bbw.shopibackend.model import ch.bbw.shopibackend.SimpleProduct data class Cart( - val items: List + val items: List ) data class CartItem( diff --git a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/repository/CartRepository.kt b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/repository/CartRepository.kt index e5ea083..ed7afbc 100644 --- a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/repository/CartRepository.kt +++ b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/repository/CartRepository.kt @@ -12,7 +12,13 @@ class CartRepository( private val context: DSLContext ) { - fun delete() { + fun deleteProductFromCart(productId: Int, userId: Int): Cart? { + context.deleteFrom(CART_PRODUCT) + .where(CART_PRODUCT.CART_FK.eq(userId)) + .and(CART_PRODUCT.PRODUCT_FK.eq(productId)) + .execute() + + return getCart(userId) } fun add(productId: Int, userId: Int) { @@ -59,7 +65,7 @@ class CartRepository( .fetch() if (cartItems.isEmpty()) { - return null + return Cart(emptyList()) } return Cart(cartItems.map { @@ -76,4 +82,14 @@ class CartRepository( ) }) } + + fun changeAmount(productId: Int, userId: Int, amount: Int): Cart? { + context.update(CART_PRODUCT) + .set(CART_PRODUCT.COUNT, amount) + .where(CART_PRODUCT.CART_FK.eq(userId)) + .and(CART_PRODUCT.PRODUCT_FK.eq(productId)) + .execute() + + return getCart(userId) + } } diff --git a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/service/CartService.kt b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/service/CartService.kt index 3c7fe8b..c9ce146 100644 --- a/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/service/CartService.kt +++ b/shopi-backend/src/main/kotlin/ch/bbw/shopibackend/service/CartService.kt @@ -10,11 +10,6 @@ class CartService( private val cartRepository: CartRepository, private val userService: UserService, ) { - - fun deleteCart() { - cartRepository.delete() - } - fun addItemToCart(product: SimpleProduct, bearerToken: String) { val userId = userService.getUserIdFromToken(bearerToken) ?: throw Exception("User not valid") cartRepository.add(product.id, userId) @@ -25,4 +20,14 @@ class CartService( return cartRepository.getCart(userId) } + fun changeAmount(product: SimpleProduct, bearerToken: String, amount: Int): Cart? { + val userId = userService.getUserIdFromToken(bearerToken) ?: throw Exception("User not valid") + + if (amount == 0) { + return cartRepository.deleteProductFromCart(product.id, userId) + } + + return cartRepository.changeAmount(product.id, userId, amount) + } + } diff --git a/shopi-backend/src/main/resources/db/migration/V3__create_cart_table.sql b/shopi-backend/src/main/resources/db/migration/V3__create_cart_table.sql index 6e82db4..dff9f25 100644 --- a/shopi-backend/src/main/resources/db/migration/V3__create_cart_table.sql +++ b/shopi-backend/src/main/resources/db/migration/V3__create_cart_table.sql @@ -15,7 +15,7 @@ CREATE TABLE IF NOT EXISTS cart CREATE TABLE IF NOT EXISTS cart_product ( - count SMALLINT NOT NULL, + count INT NOT NULL, cart_fk INT NOT NULL, CONSTRAINT cart_fk FOREIGN KEY (cart_fk) REFERENCES cart (id), diff --git a/shopi-frontend/package.json b/shopi-frontend/package.json index 31bd392..d868197 100644 --- a/shopi-frontend/package.json +++ b/shopi-frontend/package.json @@ -15,7 +15,6 @@ "@types/node": "^16.18.59", "@types/react": "^18.2.33", "@types/react-dom": "^18.2.14", - "jsonwebtoken": "^9.0.2", "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/shopi-frontend/src/components/ShoppingCart/ShoppingCart.tsx b/shopi-frontend/src/components/ShoppingCart/ShoppingCart.tsx index 948557f..4166660 100644 --- a/shopi-frontend/src/components/ShoppingCart/ShoppingCart.tsx +++ b/shopi-frontend/src/components/ShoppingCart/ShoppingCart.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from "react"; -import { Box, Modal, Table, TableBody, TableContainer, Typography } from "@mui/material"; -import { getCart } from "../../helpers/cartHelpers"; +import { Box, CircularProgress, Modal, Table, TableBody, TableContainer, TextField, Typography } from "@mui/material"; +import { getCart, updateCart } from "../../helpers/cartHelpers"; +import { Product } from "../ProductOverview/ProductOverview"; const boxStyle = { position: "absolute", @@ -13,22 +14,73 @@ const boxStyle = { p: 4, }; +type ShoppingCart = { + items: ShoppingCartItem[]; +}; + +type ShoppingCartItem = { + product: Product; + amount: number; +}; + const ShoppingCart = ({ open, setOpen }: { open: boolean; setOpen: (b: boolean) => void }) => { - const [shoppingCart, setShoppingCart] = useState(null); + const [shoppingCart, setShoppingCart] = useState(null); + const [shoppingCartIsLoaded, setShoppingCartIsLoaded] = useState(false); useEffect(() => { - getCart().then((cart) => setShoppingCart(cart)); + if (open && !shoppingCartIsLoaded) { + getCart().then((cart) => { + setShoppingCart(cart); + setShoppingCartIsLoaded(true); + }); + } }, [open]); + const updateAmount = (product: Product, amount: number) => { + setShoppingCart(null); + setShoppingCartIsLoaded(false); + updateCart(product, amount).then((cart) => { + setShoppingCart(cart); + setShoppingCartIsLoaded(true); + }); + }; + return ( - setOpen(false)}> + { + setOpen(false); + setShoppingCart(null); + setShoppingCartIsLoaded(false); + }} + > Warenkorb - - - -
-
+ {!shoppingCartIsLoaded && } + {shoppingCartIsLoaded && shoppingCart && shoppingCart.items.length === 0 && ( + Keine Produkte im Warenkorb + )} + {shoppingCartIsLoaded && shoppingCart !== null && ( + + + + {shoppingCart.items.map((item) => ( + + + + + + ))} + +
+ updateAmount(item.product, parseInt(e.target.value))} + /> + {item.product.name}{item.amount * item.product.price}
+
+ )}
); diff --git a/shopi-frontend/src/helpers/cartHelpers.ts b/shopi-frontend/src/helpers/cartHelpers.ts index 0ae4f4d..5535bd0 100644 --- a/shopi-frontend/src/helpers/cartHelpers.ts +++ b/shopi-frontend/src/helpers/cartHelpers.ts @@ -22,5 +22,20 @@ export const getCart = async () => { }, }); const data = await response.json(); + return data; }; + +export const updateCart = async (product: Product, amount: number) => { + const response = await fetch("http://localhost:8080/cart", { + method: "PUT", + headers: { + "Access-control-allow-origin": "*", + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + body: JSON.stringify({ product: product, amount: amount }), + }); + + return await response.json(); +};