From 3a21e7fafd79bf07952f359ceed477d7a8172980 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 14 Nov 2024 13:04:24 +0100 Subject: [PATCH 01/12] implement client --- .../main/java/springweb/backend/Client.java | 11 +++++++ .../springweb/backend/ClientController.java | 33 +++++++++++++++++++ .../springweb/backend/ClientRepository.java | 6 ++++ .../java/springweb/backend/ClientService.java | 28 ++++++++++++++++ .../springweb/backend/GroceryController.java | 3 +- .../springweb/backend/GroceryService.java | 4 +-- frontend/public/_GroceryDB.clients.json | 30 +++++++++++++++++ 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 backend/src/main/java/springweb/backend/Client.java create mode 100644 backend/src/main/java/springweb/backend/ClientController.java create mode 100644 backend/src/main/java/springweb/backend/ClientRepository.java create mode 100644 backend/src/main/java/springweb/backend/ClientService.java create mode 100644 frontend/public/_GroceryDB.clients.json diff --git a/backend/src/main/java/springweb/backend/Client.java b/backend/src/main/java/springweb/backend/Client.java new file mode 100644 index 0000000..4f532d3 --- /dev/null +++ b/backend/src/main/java/springweb/backend/Client.java @@ -0,0 +1,11 @@ +package springweb.backend; + +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.List; + +@Document("clients") +public record Client( + List shoppingList +) { +} diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java new file mode 100644 index 0000000..7eb96ba --- /dev/null +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -0,0 +1,33 @@ +package springweb.backend; + + +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +@RestController +@RequestMapping("/api/store/clients") +public class ClientController { + + ClientService clientService; + + public ClientController(ClientService groceryService) { + this.clientService = groceryService; + } + + @GetMapping + public List getAllGroceryProducts() { + return clientService.getAllClients(); + } + + + + /* + @PostMapping + public GroceryProduct addGroceryProduct(@RequestBody GroceryProduct groceryProduct) { + return clientService.addGroceryProduct(groceryProduct); + } + * */ + +} diff --git a/backend/src/main/java/springweb/backend/ClientRepository.java b/backend/src/main/java/springweb/backend/ClientRepository.java new file mode 100644 index 0000000..89ec0ab --- /dev/null +++ b/backend/src/main/java/springweb/backend/ClientRepository.java @@ -0,0 +1,6 @@ +package springweb.backend; + +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface ClientRepository extends MongoRepository { +} diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java new file mode 100644 index 0000000..16f8321 --- /dev/null +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -0,0 +1,28 @@ +package springweb.backend; + +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ClientService { + ClientRepository clientRepository; + + public ClientService(ClientRepository clientRepository) { + this.clientRepository = clientRepository; + } + + + public List getAllClients() { + return clientRepository.findAll(); + } + + + + /* + public GroceryProduct addGroceryProduct(GroceryProduct groceryProduct) { + + return clientRepository.save(groceryProduct); + } + * */ +} diff --git a/backend/src/main/java/springweb/backend/GroceryController.java b/backend/src/main/java/springweb/backend/GroceryController.java index 3972ceb..78902c2 100644 --- a/backend/src/main/java/springweb/backend/GroceryController.java +++ b/backend/src/main/java/springweb/backend/GroceryController.java @@ -1,7 +1,6 @@ package springweb.backend; -import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -10,7 +9,7 @@ @RestController -@RequestMapping("/api/store") +@RequestMapping("/api/store/products") public class GroceryController { GroceryService groceryService; diff --git a/backend/src/main/java/springweb/backend/GroceryService.java b/backend/src/main/java/springweb/backend/GroceryService.java index 5926138..ffbdc5b 100644 --- a/backend/src/main/java/springweb/backend/GroceryService.java +++ b/backend/src/main/java/springweb/backend/GroceryService.java @@ -1,7 +1,5 @@ package springweb.backend; -import lombok.NoArgsConstructor; -import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; import java.util.List; @@ -18,4 +16,6 @@ public GroceryService(GroceryRepository groceryRepository) { public List getAllGroceryProducts() { return groceryRepository.findAll(); } + + } diff --git a/frontend/public/_GroceryDB.clients.json b/frontend/public/_GroceryDB.clients.json new file mode 100644 index 0000000..e0b9d14 --- /dev/null +++ b/frontend/public/_GroceryDB.clients.json @@ -0,0 +1,30 @@ +[{ + "_id": "1", + "shoppingList": [{ + "category": "fruit", + "name": "apple", + "price": 1.5, + "image": "apple.jpg" + }, + { + "category": "fruit", + "name": "banana", + "price": 1, + "image": "banane.jpg" + }] +}, +{ + "_id": "2", + "shoppingList": [{ + "category": "fruit", + "name": "apple", + "price": 1.5, + "image": "apple.jpg" + }, + { + "category": "fruit", + "name": "banana", + "price": 1, + "image": "banane.jpg" + }] +}] \ No newline at end of file From 1cabd64ccfa2e9c5867ae748fa0fe7a418497885 Mon Sep 17 00:00:00 2001 From: NrdnKrmt Date: Thu, 14 Nov 2024 15:54:44 +0100 Subject: [PATCH 02/12] Fix: shoppingList dummy JSON --- frontend/public/_GroceryDB.clients.json | 68 ++++++++++++++----------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/frontend/public/_GroceryDB.clients.json b/frontend/public/_GroceryDB.clients.json index e0b9d14..faa509d 100644 --- a/frontend/public/_GroceryDB.clients.json +++ b/frontend/public/_GroceryDB.clients.json @@ -1,30 +1,40 @@ -[{ - "_id": "1", - "shoppingList": [{ - "category": "fruit", - "name": "apple", - "price": 1.5, - "image": "apple.jpg" +[ + { + "_id": "1", + "shoppingList": [ + { + "_id": "1", + "category": "fruit", + "name": "apple", + "price": 1.5, + "image": "apple.jpg" + }, + { + "_id": "2", + "category": "fruit", + "name": "banana", + "price": 1, + "image": "banane.jpg" + } + ] }, - { - "category": "fruit", - "name": "banana", - "price": 1, - "image": "banane.jpg" - }] -}, -{ - "_id": "2", - "shoppingList": [{ - "category": "fruit", - "name": "apple", - "price": 1.5, - "image": "apple.jpg" - }, - { - "category": "fruit", - "name": "banana", - "price": 1, - "image": "banane.jpg" - }] -}] \ No newline at end of file + { + "_id": "2", + "shoppingList": [ + { + "_id": "1", + "category": "fruit", + "name": "apple", + "price": 1.5, + "image": "apple.jpg" + }, + { + "_id": "2", + "category": "fruit", + "name": "banana", + "price": 1, + "image": "banane.jpg" + } + ] + } +] \ No newline at end of file From 23efe8a897cafdde2a6e0eab91bfd6a0ac55c72b Mon Sep 17 00:00:00 2001 From: NrdnKrmt Date: Thu, 14 Nov 2024 16:22:29 +0100 Subject: [PATCH 03/12] Fix: products not showing in frontend --- frontend/src/components/ProductView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/ProductView.tsx b/frontend/src/components/ProductView.tsx index bec7273..170cbd7 100644 --- a/frontend/src/components/ProductView.tsx +++ b/frontend/src/components/ProductView.tsx @@ -11,7 +11,7 @@ export default function ProductView() { function fetchAllProducts() { axios({ method: "GET", - url: "api/store", + url: "api/store/products", }) .then((response) => { From 99a46cdb0d6afe18df171ae5000009a2d4128d67 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 14 Nov 2024 19:20:58 +0100 Subject: [PATCH 04/12] add post and delete requests for client and product in shopping list --- .../springweb/backend/ClientController.java | 25 +++++-- .../java/springweb/backend/ClientService.java | 65 +++++++++++++++++-- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java index 7eb96ba..be5a2bb 100644 --- a/backend/src/main/java/springweb/backend/ClientController.java +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -17,17 +17,32 @@ public ClientController(ClientService groceryService) { } @GetMapping - public List getAllGroceryProducts() { + public List getAllClients() { return clientService.getAllClients(); } + @GetMapping({"id"}) + public List getAllGroceryProductsFromClient(@PathVariable String id) { + return clientService.getAllGroceryProductsFromClient(id); + } + @PostMapping("{id}/shoppingList") + public Client addGroceryProductToClient(@PathVariable String id, @RequestBody GroceryProduct groceryProduct) { + return clientService.addGroceryProductToClient(groceryProduct, id); + } - /* @PostMapping - public GroceryProduct addGroceryProduct(@RequestBody GroceryProduct groceryProduct) { - return clientService.addGroceryProduct(groceryProduct); + public Client addClient(@RequestBody Client client) { + return clientService.addClient(client); } - * */ + @DeleteMapping({"id"}) + public void deleteClientById(@PathVariable String id) { + clientService.deleteClientById(id); + } + + @DeleteMapping("{idClient}/shoppingList{idProduct}") + public void deleteProductByIdFromClientById(@PathVariable String idClient, @PathVariable String idProduct) { + clientService.deleteProductByIdFromClientById(idClient,idProduct); + } } diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java index 16f8321..b578077 100644 --- a/backend/src/main/java/springweb/backend/ClientService.java +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -3,6 +3,8 @@ import org.springframework.stereotype.Service; import java.util.List; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; @Service public class ClientService { @@ -19,10 +21,65 @@ public List getAllClients() { - /* - public GroceryProduct addGroceryProduct(GroceryProduct groceryProduct) { + public Client addGroceryProductToClient(GroceryProduct groceryProduct,String id) { - return clientRepository.save(groceryProduct); + if (clientRepository.existsById(id)){ + GroceryProduct newGroceryProduct = new GroceryProduct( + groceryProduct.id(), + groceryProduct.category(), + groceryProduct.name(), + groceryProduct.price(), + groceryProduct.image()); + + Client client = clientRepository.findById(id).get(); + client.shoppingList().add(newGroceryProduct); + return clientRepository.save(client); + }else { + throw new NoSuchElementException("No Client found with Id:" + id); + } + } + + public Client addClient(Client client) { + return clientRepository.save(client); + } + + public boolean deleteClientById(String id) { + if (clientRepository.existsById(id)){ + clientRepository.deleteById(id); + return true; + }else { + throw new NoSuchElementException("No Client found with Id:" + id); + } + } + + public List getAllGroceryProductsFromClient(String id) { + if (clientRepository.existsById(id)){ + return clientRepository.findById(id).get().shoppingList(); + } + throw new NoSuchElementException("No Client found with Id:" + id); + } + + public void deleteProductByIdFromClientById(String idClient, String idProduct) { + if (clientRepository.existsById(idClient)){ + Client client = clientRepository.findById(idClient).get(); + boolean productExists = client.shoppingList() + .stream() + .anyMatch(product -> product.id().equals(idProduct)); + if (!client.shoppingList().isEmpty() && productExists){ + + List filteredList = client.shoppingList() + .stream() + .filter(product -> !product.id().equals(idProduct)) + .collect(Collectors.toList()); + + client.shoppingList().clear(); + client.shoppingList().addAll(filteredList); + + clientRepository.save(client); + } + throw new NoSuchElementException("No Product found with Id:" + idProduct); + + } + throw new NoSuchElementException("No Client found with Id:" + idClient); } - * */ } From ae6ebb8b52bec8563fdf26394fc7fabc640a308e Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Thu, 14 Nov 2024 19:46:53 +0100 Subject: [PATCH 05/12] add shopping list view component to frontend with according data client --- frontend/src/App.tsx | 2 ++ frontend/src/Client.ts | 6 ++++ frontend/src/components/ShoppingListView.css | 11 ++++++ frontend/src/components/ShoppingListView.tsx | 37 ++++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 frontend/src/Client.ts create mode 100644 frontend/src/components/ShoppingListView.css create mode 100644 frontend/src/components/ShoppingListView.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7a823f0..792bec4 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,7 @@ import './App.css' import ProductView from "./components/ProductView.tsx"; +import ShoppingListView from "./components/ShoppingListView.tsx"; export default function App() { @@ -8,6 +9,7 @@ export default function App() { <>

Grocery

+ ) } diff --git a/frontend/src/Client.ts b/frontend/src/Client.ts new file mode 100644 index 0000000..035f5c9 --- /dev/null +++ b/frontend/src/Client.ts @@ -0,0 +1,6 @@ +import {Product} from "./Product.ts"; + +export type Client ={ + id: number, + shoppingList: [Product], +} \ No newline at end of file diff --git a/frontend/src/components/ShoppingListView.css b/frontend/src/components/ShoppingListView.css new file mode 100644 index 0000000..cbae032 --- /dev/null +++ b/frontend/src/components/ShoppingListView.css @@ -0,0 +1,11 @@ +.shoppingListView-container{ + font-family: Arial, sans-serif; + border: 10px solid hsl(100,10%, 80%); + border-radius: 50px; + background-color: pink; + width: 55% +} + +.shoppingList-container{ + +} \ No newline at end of file diff --git a/frontend/src/components/ShoppingListView.tsx b/frontend/src/components/ShoppingListView.tsx new file mode 100644 index 0000000..96b5b9e --- /dev/null +++ b/frontend/src/components/ShoppingListView.tsx @@ -0,0 +1,37 @@ +import "./ShoppingListView.css" +import {useEffect, useState} from "react"; +import axios from "axios"; +import {Client} from "../Client.ts"; + +export default function ShoppingListView() { + + const [client, setClient] = useState([]) + + function fetchClientById() { + axios({ + method: "GET", + url: "api/store/clients/1", + + }) + .then((response) => { + setClient(response.data) + }) + } + + useEffect(() => fetchClientById, []); + + if (!client) { + return "Lade..." + } + + return ( +
+

Shopping Cart

+
+ { +

clients

+ } +
+
+ ); +}; \ No newline at end of file From 7d8e82786b304fb9a428fb79aaf10c6bda17808b Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 15 Nov 2024 11:01:51 +0100 Subject: [PATCH 06/12] add deploy file --- .github/workflows/deploy.yml | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..fe9b7e3 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,89 @@ +name: "Deploy App" + +on: + push: + branches: + - main + +jobs: + build-frontend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Build Frontend + working-directory: frontend + run: | + npm install + npm run build + + - uses: actions/upload-artifact@v4 + with: + name: frontend-build + path: frontend/dist/ + + build-backend: + runs-on: ubuntu-latest + needs: build-frontend + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: frontend-build + path: backend/src/main/resources/static + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '21' # must match the version in the pom.xml + distribution: 'temurin' + cache: 'maven' + + - name: Build with maven + run: mvn -B package --file backend/pom.xml + + - uses: actions/upload-artifact@v4 + with: + name: app.jar + path: backend/target/app.jar # must match the finalName in the pom.xml + + push-to-docker-hub: + runs-on: ubuntu-latest + needs: build-backend + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: app.jar + path: backend/target + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} # must match the name of the Dockerhub account + password: ${{ secrets.DOCKERHUB_PASSWORD }} # must match the password of the Dockerhub account + + - name: Build and push + uses: docker/build-push-action@v5 + with: + push: true + tags: ${{ secrets.DOCKERHUB_TAG }} # Example: username/project:latest + context: . + + deploy: + name: deploy-to-render + runs-on: ubuntu-latest + needs: push-to-docker-hub + environment: + name: Capstone Project # Capstone Project name + url: https://neuefische.de/ # Link to deployment + steps: + - name: Trigger Render.com Deployment + run: | + curl -X POST ${{ secrets.RENDER_DEPLOY }} #muss mit der url des Render Deployments übereinstimmen \ No newline at end of file From e56837a8cd73e699e0e75cc6ce60826ea288f9bb Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 15 Nov 2024 11:03:14 +0100 Subject: [PATCH 07/12] add Sopping ListCard --- frontend/src/components/ShoppingListCard.css | 0 frontend/src/components/ShoppingListCard.tsx | 14 ++++++++++++++ frontend/src/components/ShoppingListView.tsx | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/ShoppingListCard.css create mode 100644 frontend/src/components/ShoppingListCard.tsx diff --git a/frontend/src/components/ShoppingListCard.css b/frontend/src/components/ShoppingListCard.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/components/ShoppingListCard.tsx b/frontend/src/components/ShoppingListCard.tsx new file mode 100644 index 0000000..c582268 --- /dev/null +++ b/frontend/src/components/ShoppingListCard.tsx @@ -0,0 +1,14 @@ +import "./ShoppingListCard.css" +import {Product} from "../Product.ts"; + +type Props = { + product: Product +} + +export function ShoppingListCard(props: Props) { + return ( +
+

{props.product.id} - {props.product.name} - {props.product.category} - {props.product.price}

+
+ ); +}; \ No newline at end of file diff --git a/frontend/src/components/ShoppingListView.tsx b/frontend/src/components/ShoppingListView.tsx index 96b5b9e..cb99fe7 100644 --- a/frontend/src/components/ShoppingListView.tsx +++ b/frontend/src/components/ShoppingListView.tsx @@ -2,6 +2,7 @@ import "./ShoppingListView.css" import {useEffect, useState} from "react"; import axios from "axios"; import {Client} from "../Client.ts"; +import {ShoppingListCard} from "./ShoppingListCard.tsx"; export default function ShoppingListView() { @@ -27,9 +28,11 @@ export default function ShoppingListView() { return (

Shopping Cart

+

clients

{ -

clients

+ + client[0].shoppingList.map((product) => ) }
From c5ff64e8374c147734f0c0fcb4dab418ae203200 Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Fri, 15 Nov 2024 14:19:58 +0100 Subject: [PATCH 08/12] add Get client by id endpoint --- .../java/springweb/backend/ClientController.java | 8 ++++---- .../main/java/springweb/backend/ClientService.java | 9 ++++++++- frontend/src/Client.ts | 2 +- frontend/src/components/ShoppingListCard.tsx | 3 ++- frontend/src/components/ShoppingListView.tsx | 14 ++++---------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java index be5a2bb..58b90e4 100644 --- a/backend/src/main/java/springweb/backend/ClientController.java +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -10,7 +10,7 @@ @RequestMapping("/api/store/clients") public class ClientController { - ClientService clientService; + private final ClientService clientService; public ClientController(ClientService groceryService) { this.clientService = groceryService; @@ -21,9 +21,9 @@ public List getAllClients() { return clientService.getAllClients(); } - @GetMapping({"id"}) - public List getAllGroceryProductsFromClient(@PathVariable String id) { - return clientService.getAllGroceryProductsFromClient(id); + @GetMapping({"{id}"}) + public Client getClientByID(@PathVariable String id) { + return clientService.getClientById(id); } @PostMapping("{id}/shoppingList") diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java index b578077..e1a47c9 100644 --- a/backend/src/main/java/springweb/backend/ClientService.java +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -8,7 +8,7 @@ @Service public class ClientService { - ClientRepository clientRepository; + private final ClientRepository clientRepository; public ClientService(ClientRepository clientRepository) { this.clientRepository = clientRepository; @@ -59,6 +59,13 @@ public List getAllGroceryProductsFromClient(String id) { throw new NoSuchElementException("No Client found with Id:" + id); } + public Client getClientById(String id) { + if (clientRepository.existsById(id)){ + return clientRepository.findById(id).get(); + } + throw new NoSuchElementException("No Client found with Id:" + id); + } + public void deleteProductByIdFromClientById(String idClient, String idProduct) { if (clientRepository.existsById(idClient)){ Client client = clientRepository.findById(idClient).get(); diff --git a/frontend/src/Client.ts b/frontend/src/Client.ts index 035f5c9..4c4ed6c 100644 --- a/frontend/src/Client.ts +++ b/frontend/src/Client.ts @@ -1,6 +1,6 @@ import {Product} from "./Product.ts"; export type Client ={ - id: number, + id: string, shoppingList: [Product], } \ No newline at end of file diff --git a/frontend/src/components/ShoppingListCard.tsx b/frontend/src/components/ShoppingListCard.tsx index c582268..f666f0b 100644 --- a/frontend/src/components/ShoppingListCard.tsx +++ b/frontend/src/components/ShoppingListCard.tsx @@ -1,4 +1,5 @@ import "./ShoppingListCard.css" +//import {Client} from "../Client.ts"; import {Product} from "../Product.ts"; type Props = { @@ -8,7 +9,7 @@ type Props = { export function ShoppingListCard(props: Props) { return (
-

{props.product.id} - {props.product.name} - {props.product.category} - {props.product.price}

+

{props.product.name}

); }; \ No newline at end of file diff --git a/frontend/src/components/ShoppingListView.tsx b/frontend/src/components/ShoppingListView.tsx index cb99fe7..625d40a 100644 --- a/frontend/src/components/ShoppingListView.tsx +++ b/frontend/src/components/ShoppingListView.tsx @@ -2,13 +2,12 @@ import "./ShoppingListView.css" import {useEffect, useState} from "react"; import axios from "axios"; import {Client} from "../Client.ts"; -import {ShoppingListCard} from "./ShoppingListCard.tsx"; export default function ShoppingListView() { - const [client, setClient] = useState([]) + const [client, setClient] = useState() - function fetchClientById() { + function fetchClients() { axios({ method: "GET", url: "api/store/clients/1", @@ -19,7 +18,7 @@ export default function ShoppingListView() { }) } - useEffect(() => fetchClientById, []); + useEffect(() => fetchClients, []); if (!client) { return "Lade..." @@ -29,12 +28,7 @@ export default function ShoppingListView() {

Shopping Cart

clients

-
- { - - client[0].shoppingList.map((product) => ) - } -
+ {client.id}
); }; \ No newline at end of file From fe5868ad784b81103de5cca48044092b47d27786 Mon Sep 17 00:00:00 2001 From: NrdnKrmt Date: Fri, 15 Nov 2024 15:07:36 +0100 Subject: [PATCH 09/12] Add: Basic HTTP Requests --- .../main/java/springweb/backend/Client.java | 1 + .../springweb/backend/ClientController.java | 22 +++++--- .../java/springweb/backend/ClientService.java | 52 ++++++++++--------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/backend/src/main/java/springweb/backend/Client.java b/backend/src/main/java/springweb/backend/Client.java index 4f532d3..626d221 100644 --- a/backend/src/main/java/springweb/backend/Client.java +++ b/backend/src/main/java/springweb/backend/Client.java @@ -6,6 +6,7 @@ @Document("clients") public record Client( + String id, List shoppingList ) { } diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java index 58b90e4..4aeb869 100644 --- a/backend/src/main/java/springweb/backend/ClientController.java +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -4,6 +4,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.NoSuchElementException; @RestController @@ -12,8 +13,8 @@ public class ClientController { private final ClientService clientService; - public ClientController(ClientService groceryService) { - this.clientService = groceryService; + public ClientController(ClientService clientService) { + this.clientService = clientService; } @GetMapping @@ -23,26 +24,31 @@ public List getAllClients() { @GetMapping({"{id}"}) public Client getClientByID(@PathVariable String id) { - return clientService.getClientById(id); + return clientService.getClientById(id).orElseThrow(() -> new NoSuchElementException("Task not found")); } - @PostMapping("{id}/shoppingList") + /* @PostMapping("{id}/shoppingList") public Client addGroceryProductToClient(@PathVariable String id, @RequestBody GroceryProduct groceryProduct) { return clientService.addGroceryProductToClient(groceryProduct, id); - } + }*/ @PostMapping public Client addClient(@RequestBody Client client) { return clientService.addClient(client); } - @DeleteMapping({"id"}) + @PutMapping("/{id}") + public Client updateTask(@PathVariable String id, @RequestBody Client clientDto) { + return clientService.updateClient(id, clientDto); + } + + @DeleteMapping({"{id}"}) public void deleteClientById(@PathVariable String id) { clientService.deleteClientById(id); } - @DeleteMapping("{idClient}/shoppingList{idProduct}") + /* @DeleteMapping("{idClient}/shoppingList{idProduct}") public void deleteProductByIdFromClientById(@PathVariable String idClient, @PathVariable String idProduct) { clientService.deleteProductByIdFromClientById(idClient,idProduct); - } + }*/ } diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java index e1a47c9..6fda6bb 100644 --- a/backend/src/main/java/springweb/backend/ClientService.java +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.NoSuchElementException; -import java.util.stream.Collectors; +import java.util.Optional; @Service public class ClientService { @@ -14,16 +14,17 @@ public ClientService(ClientRepository clientRepository) { this.clientRepository = clientRepository; } - public List getAllClients() { return clientRepository.findAll(); } + public Optional getClientById(String id) { + return clientRepository.findById(id); + } + /* public Client addGroceryProductToClient(GroceryProduct groceryProduct, String id) { - public Client addGroceryProductToClient(GroceryProduct groceryProduct,String id) { - - if (clientRepository.existsById(id)){ + if (clientRepository.existsById(id)) { GroceryProduct newGroceryProduct = new GroceryProduct( groceryProduct.id(), groceryProduct.category(), @@ -34,45 +35,48 @@ public Client addGroceryProductToClient(GroceryProduct groceryProduct,String id) Client client = clientRepository.findById(id).get(); client.shoppingList().add(newGroceryProduct); return clientRepository.save(client); - }else { + } else { throw new NoSuchElementException("No Client found with Id:" + id); } - } + }*/ - public Client addClient(Client client) { + public Client addClient(Client clientDto) { + Client client = new Client(clientDto.id(), clientDto.shoppingList()); return clientRepository.save(client); } + public Client updateClient(String id, Client clientDto) { + if (clientRepository.existsById(id)) { + Client updatedClient = new Client(id, clientDto.shoppingList()); + return clientRepository.save(updatedClient); + } else { + throw new NoSuchElementException("No Client found with Id:" + id); + } + } + public boolean deleteClientById(String id) { - if (clientRepository.existsById(id)){ + if (clientRepository.existsById(id)) { clientRepository.deleteById(id); return true; - }else { + } else { throw new NoSuchElementException("No Client found with Id:" + id); } } - public List getAllGroceryProductsFromClient(String id) { - if (clientRepository.existsById(id)){ + /*public List getAllGroceryProductsFromClient(String id) { + if (clientRepository.existsById(id)) { return clientRepository.findById(id).get().shoppingList(); } throw new NoSuchElementException("No Client found with Id:" + id); - } + }*/ - public Client getClientById(String id) { - if (clientRepository.existsById(id)){ - return clientRepository.findById(id).get(); - } - throw new NoSuchElementException("No Client found with Id:" + id); - } - - public void deleteProductByIdFromClientById(String idClient, String idProduct) { - if (clientRepository.existsById(idClient)){ + /*public void deleteProductByIdFromClientById(String idClient, String idProduct) { + if (clientRepository.existsById(idClient)) { Client client = clientRepository.findById(idClient).get(); boolean productExists = client.shoppingList() .stream() .anyMatch(product -> product.id().equals(idProduct)); - if (!client.shoppingList().isEmpty() && productExists){ + if (!client.shoppingList().isEmpty() && productExists) { List filteredList = client.shoppingList() .stream() @@ -88,5 +92,5 @@ public void deleteProductByIdFromClientById(String idClient, String idProduct) { } throw new NoSuchElementException("No Client found with Id:" + idClient); - } + }*/ } From c74c2e853b065a2d013b4b1c37ee1a72d979df2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dario=20K=C3=B6pp?= Date: Fri, 15 Nov 2024 16:47:12 +0100 Subject: [PATCH 10/12] Add ClientServiceTest --- .../springweb/backend/ClientController.java | 4 +- .../java/springweb/backend/ClientService.java | 10 ++-- .../springweb/backend/ClientServiceTest.java | 58 +++++++++++++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 backend/src/test/java/springweb/backend/ClientServiceTest.java diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java index 4aeb869..9c673f5 100644 --- a/backend/src/main/java/springweb/backend/ClientController.java +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -27,10 +27,10 @@ public Client getClientByID(@PathVariable String id) { return clientService.getClientById(id).orElseThrow(() -> new NoSuchElementException("Task not found")); } - /* @PostMapping("{id}/shoppingList") + @PostMapping("{id}/shoppingList") public Client addGroceryProductToClient(@PathVariable String id, @RequestBody GroceryProduct groceryProduct) { return clientService.addGroceryProductToClient(groceryProduct, id); - }*/ + } @PostMapping public Client addClient(@RequestBody Client client) { diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java index 6fda6bb..8bfb24b 100644 --- a/backend/src/main/java/springweb/backend/ClientService.java +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -22,15 +22,17 @@ public Optional getClientById(String id) { return clientRepository.findById(id); } - /* public Client addGroceryProductToClient(GroceryProduct groceryProduct, String id) { + public Client addGroceryProductToClient(GroceryProduct groceryProduct, String id) { if (clientRepository.existsById(id)) { - GroceryProduct newGroceryProduct = new GroceryProduct( + /*GroceryProduct newGroceryProduct = new GroceryProduct( groceryProduct.id(), groceryProduct.category(), groceryProduct.name(), groceryProduct.price(), - groceryProduct.image()); + groceryProduct.image());* + + */ Client client = clientRepository.findById(id).get(); client.shoppingList().add(newGroceryProduct); @@ -38,7 +40,7 @@ public Optional getClientById(String id) { } else { throw new NoSuchElementException("No Client found with Id:" + id); } - }*/ + } public Client addClient(Client clientDto) { Client client = new Client(clientDto.id(), clientDto.shoppingList()); diff --git a/backend/src/test/java/springweb/backend/ClientServiceTest.java b/backend/src/test/java/springweb/backend/ClientServiceTest.java new file mode 100644 index 0000000..0db07e3 --- /dev/null +++ b/backend/src/test/java/springweb/backend/ClientServiceTest.java @@ -0,0 +1,58 @@ +package springweb.backend; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; + +import static com.mongodb.internal.connection.tlschannel.util.Util.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +public class ClientServiceTest { + + private final ClientRepository mockUserRepo = mock(ClientRepository.class); + + @Test + public void GetAllClients_Test() { + // GIVEN + GroceryProduct product = new GroceryProduct("1", "Fruit", "Apple", 0.99, "apple.jpg"); + List shoppingList1 = List.of(product); + Client expectedClient1 = new Client("123", shoppingList1); + + GroceryProduct product2 = new GroceryProduct("2", "Fruit", "Banana", 500, "banane.jpg"); + GroceryProduct product3 = new GroceryProduct("3", "Fruit", "Kiwi", 1.80, "ps5.jpg"); + List shoppingList2 = List.of(product2, product3); + Client expectedClient2 = new Client("456", shoppingList2); + + List clientList = List.of(expectedClient1, expectedClient2); + + when(mockUserRepo.findAll()).thenReturn(clientList); + ClientService clientService = new ClientService(mockUserRepo); + + // WHEN + List actual = clientService.getAllClients(); + + // THEN + verify(mockUserRepo).findAll(); + assertEquals(clientList, actual); + } + + @Test + public void GetClientById_Test() { + // GIVEN + GroceryProduct product = new GroceryProduct("1", "Fruit", "Apple", 0.99, "apple.jpg"); + List shoppingList = List.of(product); + Client expectedClient = new Client("123", shoppingList); + + when(mockUserRepo.findById("123")).thenReturn(Optional.of(expectedClient)); + ClientService clientService = new ClientService(mockUserRepo); + + // WHEN + Optional result = clientService.getClientById("123"); + + // THEN + verify(mockUserRepo).findById("123"); + assertTrue(result.isPresent()); + assertEquals(expectedClient, result.get()); + } +} \ No newline at end of file From 6169145c82ac269e26f0e7f806fb8e3aa03dddce Mon Sep 17 00:00:00 2001 From: NrdnKrmt Date: Fri, 15 Nov 2024 17:10:43 +0100 Subject: [PATCH 11/12] Add: Controller/Service functionality --- .../springweb/backend/ClientController.java | 4 +-- .../java/springweb/backend/ClientService.java | 29 ++++++++----------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/backend/src/main/java/springweb/backend/ClientController.java b/backend/src/main/java/springweb/backend/ClientController.java index 9c673f5..fb55799 100644 --- a/backend/src/main/java/springweb/backend/ClientController.java +++ b/backend/src/main/java/springweb/backend/ClientController.java @@ -47,8 +47,8 @@ public void deleteClientById(@PathVariable String id) { clientService.deleteClientById(id); } - /* @DeleteMapping("{idClient}/shoppingList{idProduct}") + @DeleteMapping("{idClient}/shoppingList/{idProduct}") public void deleteProductByIdFromClientById(@PathVariable String idClient, @PathVariable String idProduct) { clientService.deleteProductByIdFromClientById(idClient,idProduct); - }*/ + } } diff --git a/backend/src/main/java/springweb/backend/ClientService.java b/backend/src/main/java/springweb/backend/ClientService.java index 8bfb24b..43b1bb2 100644 --- a/backend/src/main/java/springweb/backend/ClientService.java +++ b/backend/src/main/java/springweb/backend/ClientService.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; +import java.util.stream.Collectors; @Service public class ClientService { @@ -25,17 +26,8 @@ public Optional getClientById(String id) { public Client addGroceryProductToClient(GroceryProduct groceryProduct, String id) { if (clientRepository.existsById(id)) { - /*GroceryProduct newGroceryProduct = new GroceryProduct( - groceryProduct.id(), - groceryProduct.category(), - groceryProduct.name(), - groceryProduct.price(), - groceryProduct.image());* - - */ - Client client = clientRepository.findById(id).get(); - client.shoppingList().add(newGroceryProduct); + client.shoppingList().add(groceryProduct); return clientRepository.save(client); } else { throw new NoSuchElementException("No Client found with Id:" + id); @@ -65,14 +57,16 @@ public boolean deleteClientById(String id) { } } - /*public List getAllGroceryProductsFromClient(String id) { + /* WIP + public List getAllGroceryProductsFromClient(String id) { if (clientRepository.existsById(id)) { return clientRepository.findById(id).get().shoppingList(); } throw new NoSuchElementException("No Client found with Id:" + id); - }*/ + } + */ - /*public void deleteProductByIdFromClientById(String idClient, String idProduct) { + public void deleteProductByIdFromClientById(String idClient, String idProduct) { if (clientRepository.existsById(idClient)) { Client client = clientRepository.findById(idClient).get(); boolean productExists = client.shoppingList() @@ -89,10 +83,11 @@ public boolean deleteClientById(String id) { client.shoppingList().addAll(filteredList); clientRepository.save(client); + } else { + throw new NoSuchElementException("No Product found with Id:" + idProduct); } - throw new NoSuchElementException("No Product found with Id:" + idProduct); - + } else { + throw new NoSuchElementException("No Client found with Id:" + idClient); } - throw new NoSuchElementException("No Client found with Id:" + idClient); - }*/ + } } From e1d4bb95a6a264c0ada2376bf512ee28ea982c2e Mon Sep 17 00:00:00 2001 From: NrdnKrmt Date: Fri, 15 Nov 2024 17:28:34 +0100 Subject: [PATCH 12/12] Fix: fetchClient as function --- frontend/src/components/ShoppingListView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/ShoppingListView.tsx b/frontend/src/components/ShoppingListView.tsx index 625d40a..6ecdee8 100644 --- a/frontend/src/components/ShoppingListView.tsx +++ b/frontend/src/components/ShoppingListView.tsx @@ -18,7 +18,7 @@ export default function ShoppingListView() { }) } - useEffect(() => fetchClients, []); + useEffect(() => fetchClients(), []); if (!client) { return "Lade..."