From 88103ec9881d875d9525db4af1bc22498561fe8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Mon, 16 Dec 2024 17:10:08 +0900 Subject: [PATCH] =?UTF-8?q?=20Feat=20:=20=EB=A0=88=EC=8B=9C=ED=94=BC=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=201.?= =?UTF-8?q?=20=EA=B0=81=20=EB=A0=88=EC=8B=9C=ED=94=BC=EB=B3=84=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=EB=A5=BC=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EB=8B=B9=20=ED=95=9C=20=EA=B0=80=EC=A7=80=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EA=B0=80=EB=8A=A5=20(=20null=20=EB=8F=84?= =?UTF-8?q?=20=EC=9E=88=EC=96=B4=EC=84=9C=20=EC=95=88=20=EB=88=84=EB=A5=BC?= =?UTF-8?q?=20=EC=88=98=20=EC=9E=88=EB=8B=A4)=202.=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=20=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=ED=95=9C=EA=B0=92=EC=9D=B4=20=EB=82=98?= =?UTF-8?q?=EC=98=A8=EB=8B=A4.=20Related=20to=20:=20#20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.idea/modules/refrigerator.main.iml | 19 ++------ .../aggregate/recipe/RecipeLikeDislike.java | 27 +++++++++++ .../controller/recipe/RecipeController.java | 10 +++++ .../dto/recipe/request/RecipeLikeRequest.java | 10 +++++ .../recipe/response/RecipeLikeResponse.java | 12 +++++ .../recipe/RecipeLikeDislikeRepository.java | 14 ++++++ .../service/recipe/RecipeService.java | 3 ++ .../service/recipe/RecipeServiceImpl.java | 45 ++++++++++++++++--- 8 files changed, 118 insertions(+), 22 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index ac8e328..afc1871 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,21 +1,8 @@ - - + + - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java new file mode 100644 index 0000000..8fe52a5 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java @@ -0,0 +1,27 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Entity +@Table(name = "tbl_recipe_like_dislike") +@Data +public class RecipeLikeDislike { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "like_dislike_pk") + private Long id; + + @ManyToOne + @JoinColumn(name = "recipe_pk") + private Recipe recipe; + + @ManyToOne + @JoinColumn(name = "user_pk") + private User user; + + @Column(name = "like_status") + private Boolean likeStatus; +} + diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index d332f82..03ecb0a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -2,8 +2,10 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeLikeResponse; import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; @@ -69,4 +71,12 @@ public ResponseEntity getRandomRecipe() { return ResponseEntity.notFound().build(); } } + + @PostMapping("/reaction") + public ResponseEntity toggleLikeDislike( + @RequestBody RecipeLikeRequest request + ) { + return ResponseEntity.ok(recipeService.toggleLikeDislike(request)); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java new file mode 100644 index 0000000..4deff9c --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java @@ -0,0 +1,10 @@ +package moja.refrigerator.dto.recipe.request; + +import lombok.Data; + +@Data +public class RecipeLikeRequest { + private Long recipePk; + private Long userPk; + private Boolean likeStatus; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java new file mode 100644 index 0000000..a104acf --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java @@ -0,0 +1,12 @@ +package moja.refrigerator.dto.recipe.response; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class RecipeLikeResponse { + private long likesCount; + private long dislikesCount; + private Boolean userReaction; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java new file mode 100644 index 0000000..7510915 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java @@ -0,0 +1,14 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.aggregate.recipe.RecipeLikeDislike; +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.Optional; + +@Repository +public interface RecipeLikeDislikeRepository extends JpaRepository { + Optional findByRecipeAndUser(Recipe recipe, User user); + long countByRecipeAndLikeStatus(Recipe recipe, Boolean likeStatus); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index cb89a94..81c69a5 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -2,8 +2,10 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeLikeResponse; import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; @@ -25,4 +27,5 @@ void updateRecipe( ); List getRecommendedRecipes(Long userPk); RecipeRecommendResponse getRandomRecipe(); + RecipeLikeResponse toggleLikeDislike(RecipeLikeRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index e54afe6..42030fb 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -8,11 +8,9 @@ import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.recipe.RecipeMatchResult; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; -import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; -import moja.refrigerator.dto.recipe.response.RecipeIngredientInfo; -import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; -import moja.refrigerator.dto.recipe.response.RecipeResponse; +import moja.refrigerator.dto.recipe.response.*; import moja.refrigerator.repository.ingredient.IngredientMyRefrigeratorRepository; import moja.refrigerator.repository.recipe.*; import moja.refrigerator.repository.user.UserRepository; @@ -43,6 +41,7 @@ public class RecipeServiceImpl implements RecipeService { private final IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository; private final RecipeIngredientRepository recipeIngredientRepository; private final ReplacableIngredientRepository replacableIngredientRepository; + private final RecipeLikeDislikeRepository recipeLikeDislikeRepository; @Value("${cloud.aws.s3.bucket}") private String bucket; @@ -58,7 +57,8 @@ public RecipeServiceImpl( AmazonS3Client amazonS3Client, IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository, RecipeIngredientRepository recipeIngredientRepository, - ReplacableIngredientRepository replacableIngredientRepository + ReplacableIngredientRepository replacableIngredientRepository, + RecipeLikeDislikeRepository recipeLikeDislikeRepository ) { this.recipeRepository = recipeRepository; this.userRepository = userRepository; @@ -70,8 +70,8 @@ public RecipeServiceImpl( this.ingredientMyRefrigeratorRepository = ingredientMyRefrigeratorRepository; this.recipeIngredientRepository = recipeIngredientRepository; this.replacableIngredientRepository = replacableIngredientRepository; + this.recipeLikeDislikeRepository = recipeLikeDislikeRepository; } - private boolean isImageFile(String fileName) { String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); return List.of("jpg", "jpeg", "png", "gif").contains(extension); @@ -348,4 +348,37 @@ public RecipeRecommendResponse getRandomRecipe() { return response; } + @Override + @Transactional + public RecipeLikeResponse toggleLikeDislike(RecipeLikeRequest request) { + Recipe recipe = recipeRepository.findById(request.getRecipePk()) + .orElseThrow(() -> new IllegalArgumentException("레시피를 찾을 수 없습니다.")); + + User user = userRepository.findById(request.getUserPk()) + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + + Optional existing = + recipeLikeDislikeRepository.findByRecipeAndUser(recipe, user); + + if (existing.isPresent()) { + if (existing.get().getLikeStatus() == request.getLikeStatus()) { + recipeLikeDislikeRepository.delete(existing.get()); + } else { + existing.get().setLikeStatus(request.getLikeStatus()); + } + } else { + RecipeLikeDislike newReaction = new RecipeLikeDislike(); + newReaction.setRecipe(recipe); + newReaction.setUser(user); + newReaction.setLikeStatus(request.getLikeStatus()); + recipeLikeDislikeRepository.save(newReaction); + } + + // 현재 좋아요/싫어요 수 계산 + long likes = recipeLikeDislikeRepository.countByRecipeAndLikeStatus(recipe, true); + long dislikes = recipeLikeDislikeRepository.countByRecipeAndLikeStatus(recipe, false); + + return new RecipeLikeResponse(likes, dislikes, request.getLikeStatus()); + } + } \ No newline at end of file