diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml
index 397c268..ac8e328 100644
--- a/refrigerator/.idea/modules/refrigerator.main.iml
+++ b/refrigerator/.idea/modules/refrigerator.main.iml
@@ -1,9 +1,6 @@
-
-
-
@@ -20,4 +17,5 @@
-
\ 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