diff --git a/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantController.java b/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantController.java index e1008f1..5d79c80 100644 --- a/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantController.java +++ b/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantController.java @@ -1,5 +1,6 @@ package com.neuefische.team2.backend.restaurant; +import com.neuefische.team2.backend.restaurant.domain.NewCommentDTO; import com.neuefische.team2.backend.restaurant.domain.NewRestaurantDTO; import com.neuefische.team2.backend.exceptions.ResourceNotFoundException; import com.neuefische.team2.backend.restaurant.domain.Restaurant; @@ -12,6 +13,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.List; @RestController @@ -37,7 +39,7 @@ Restaurant getRestaurantById(@PathVariable @Valid String id) { @PostMapping @ResponseStatus(HttpStatus.CREATED) public Restaurant addRestaurant(@RequestBody @Valid NewRestaurantDTO newRestaurantDTO) { - Restaurant restaurant = new Restaurant(null, newRestaurantDTO.title(), newRestaurantDTO.city()); + Restaurant restaurant = new Restaurant(null, newRestaurantDTO.title(), newRestaurantDTO.city(), new ArrayList<>()); return restaurantService.addRestaurant(restaurant); } @@ -50,4 +52,16 @@ Restaurant putRestaurant(@Valid @RequestBody NewRestaurantDTO newRestaurantDTO, void deleteRestaurant(@PathVariable String id) { restaurantService.deleteRestaurant(id); } + + + @PostMapping("/{id}/comments") + public Restaurant addComment(@PathVariable String id, @RequestBody NewCommentDTO comment) { + return restaurantService.addCommentToRestaurant(id, comment.text()); + } + + + @GetMapping("/{id}/comments") + public List getComments(@PathVariable String id) { + return restaurantService.getCommentsForRestaurant(id); + } } diff --git a/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantService.java b/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantService.java index e2c42f2..5d33cc5 100644 --- a/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantService.java +++ b/backend/src/main/java/com/neuefische/team2/backend/restaurant/RestaurantService.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; @Service @@ -44,12 +45,13 @@ public Restaurant addRestaurant(Restaurant restaurant) { public Restaurant updateRestaurant(NewRestaurantDTO updatedRestaurantDTO, String id) throws ResourceNotFoundException { logger.info("Trying to update restaurant with ID {}", id); - + Restaurant existingRestaurant = this.findRestaurantById(id); this.findRestaurantById(id); Restaurant updatedRestaurant = new Restaurant( id, updatedRestaurantDTO.title().trim(), - updatedRestaurantDTO.city().trim() + updatedRestaurantDTO.city().trim(), + existingRestaurant.comments() ); Restaurant savedRestaurant = restaurantRepository.save(updatedRestaurant); @@ -61,4 +63,29 @@ public void deleteRestaurant(String id) { this.findRestaurantById(id); restaurantRepository.deleteById(id); } + + public Restaurant addCommentToRestaurant(String id, String commentText) throws ResourceNotFoundException { + logger.info("Trying to add comment to restaurant with ID {}", id); + + Restaurant restaurant = this.findRestaurantById(id); + List updatedComments = new ArrayList<>(restaurant.comments() != null ? restaurant.comments() : new ArrayList<>()); + Restaurant.Comment comment = new Restaurant.Comment(commentText, System.currentTimeMillis()); + updatedComments.add(comment); + + Restaurant updatedRestaurant = new Restaurant( + restaurant.id(), + restaurant.title(), + restaurant.city(), + updatedComments + ); + return restaurantRepository.save(updatedRestaurant); + } + + + public List getCommentsForRestaurant(String id) throws ResourceNotFoundException { + logger.info("Trying to get comments for restaurant with ID {}", id); + + Restaurant restaurant = this.findRestaurantById(id); + return restaurant.comments(); + } } diff --git a/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/NewCommentDTO.java b/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/NewCommentDTO.java new file mode 100644 index 0000000..2d6c908 --- /dev/null +++ b/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/NewCommentDTO.java @@ -0,0 +1,7 @@ +package com.neuefische.team2.backend.restaurant.domain; + +public record NewCommentDTO( + String text + +) { +} diff --git a/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/Restaurant.java b/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/Restaurant.java index 4ad79e0..17329a7 100644 --- a/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/Restaurant.java +++ b/backend/src/main/java/com/neuefische/team2/backend/restaurant/domain/Restaurant.java @@ -4,6 +4,8 @@ import jakarta.validation.constraints.NotBlank; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.List; + @Document("restaurants") public record Restaurant( @Id @@ -13,6 +15,11 @@ public record Restaurant( String title, @NotBlank(message = "Restaurant-Stadt muss vorhanden sein.") - String city + String city, + List comments ) { + public record Comment( + String text, + long createdAt + ) {} } diff --git a/frontend/src/components/Comments/CommentsSection.tsx b/frontend/src/components/Comments/CommentsSection.tsx new file mode 100644 index 0000000..68da497 --- /dev/null +++ b/frontend/src/components/Comments/CommentsSection.tsx @@ -0,0 +1,56 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; + +type CommentsSectionProps = { + restaurantId: string; +}; + +function CommentsSection({ restaurantId }: CommentsSectionProps) { + const [comments, setComments] = useState<{ text: string }[]>([]); + const [newComment, setNewComment] = useState<{ text: string }>({ text: "" }); + + useEffect(() => { + axios + .get(`/api/restaurants/${restaurantId}/comments`) + .then((response) => { + setComments(response.data); + }) + .catch((error) => { + console.error("There was an error fetching the comments!", error); + }); + }, [restaurantId]); + + const handleAddComment = () => { + axios + .post(`/api/restaurants/${restaurantId}/comments`, newComment) + .then((response) => { + setComments(response.data.comments); + setNewComment({ text: "" }); + }) + .catch((error) => { + console.error("There was an error adding the comment!", error); + }); + }; + + return ( +
+

Comments

+ setNewComment({ text: e.target.value })} + placeholder="Add a comment" + /> + +
    + {comments.length > 0 ? ( + comments.map((comment, index) =>
  • {comment.text}
  • ) + ) : ( +
  • No comments available.
  • + )} +
+
+ ); +} + +export default CommentsSection; diff --git a/frontend/src/pages/ViewRestaurantPage.tsx b/frontend/src/pages/ViewRestaurantPage.tsx index d2bcbd8..689dd42 100644 --- a/frontend/src/pages/ViewRestaurantPage.tsx +++ b/frontend/src/pages/ViewRestaurantPage.tsx @@ -9,6 +9,7 @@ import { logtail } from "../logger.ts"; import AlertBox from "../components/AlertBox/AlertBox.tsx"; import { mutate } from "swr"; import { RestaurantType } from "../model/Restaurant.ts"; +import CommentsSection from "../components/Comments/CommentsSection.tsx"; export default function ViewRestaurantPage() { const navigate = useNavigate(); @@ -78,6 +79,7 @@ export default function ViewRestaurantPage() { > Delete + ); }