From d1f192650b0a78c900ebb4088d5d53037ce2280b Mon Sep 17 00:00:00 2001 From: Jeongho Date: Wed, 12 Jun 2024 03:58:25 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EB=B6=81=EB=A7=88=ED=81=AC=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BookmarkRepository.java | 3 +- .../custom/BookmarkRepositoryCustom.java | 8 ++++ .../custom/BookmarkRepositoryImpl.java | 22 +++++++++ .../recipe/controller/RecipeController.java | 5 +- .../dto/response/CreateRecipeResponse.java | 47 +++++++++++++++++++ .../dto/response/RecipeDetailsResponse.java | 6 ++- .../domain/recipe/service/RecipeService.java | 15 ++++-- 7 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryCustom.java create mode 100644 src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryImpl.java create mode 100644 src/main/java/capstone/recipable/domain/recipe/dto/response/CreateRecipeResponse.java diff --git a/src/main/java/capstone/recipable/domain/bookmark/repository/BookmarkRepository.java b/src/main/java/capstone/recipable/domain/bookmark/repository/BookmarkRepository.java index e8fd098..121c308 100644 --- a/src/main/java/capstone/recipable/domain/bookmark/repository/BookmarkRepository.java +++ b/src/main/java/capstone/recipable/domain/bookmark/repository/BookmarkRepository.java @@ -1,11 +1,12 @@ package capstone.recipable.domain.bookmark.repository; import capstone.recipable.domain.bookmark.entity.Bookmark; +import capstone.recipable.domain.bookmark.repository.custom.BookmarkRepositoryCustom; import capstone.recipable.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; -public interface BookmarkRepository extends JpaRepository { +public interface BookmarkRepository extends JpaRepository, BookmarkRepositoryCustom { List findAllByUser(User user); } diff --git a/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryCustom.java b/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryCustom.java new file mode 100644 index 0000000..5fc9b72 --- /dev/null +++ b/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryCustom.java @@ -0,0 +1,8 @@ +package capstone.recipable.domain.bookmark.repository.custom; + +import capstone.recipable.domain.recipe.entity.Recipe; +import capstone.recipable.domain.user.entity.User; + +public interface BookmarkRepositoryCustom { + boolean isBookmarked(User user, Recipe recipe); +} diff --git a/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryImpl.java b/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryImpl.java new file mode 100644 index 0000000..182c7c7 --- /dev/null +++ b/src/main/java/capstone/recipable/domain/bookmark/repository/custom/BookmarkRepositoryImpl.java @@ -0,0 +1,22 @@ +package capstone.recipable.domain.bookmark.repository.custom; + +import capstone.recipable.domain.recipe.entity.Recipe; +import capstone.recipable.domain.user.entity.User; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; + +import static capstone.recipable.domain.bookmark.entity.QBookmark.bookmark; + +@RequiredArgsConstructor +public class BookmarkRepositoryImpl implements BookmarkRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public boolean isBookmarked(User user, Recipe recipe) { + return jpaQueryFactory + .selectFrom(bookmark) + .where(bookmark.user.eq(user).and(bookmark.recipe.eq(recipe))) + .fetchOne() != null; + } +} diff --git a/src/main/java/capstone/recipable/domain/recipe/controller/RecipeController.java b/src/main/java/capstone/recipable/domain/recipe/controller/RecipeController.java index c565d54..2fc9499 100644 --- a/src/main/java/capstone/recipable/domain/recipe/controller/RecipeController.java +++ b/src/main/java/capstone/recipable/domain/recipe/controller/RecipeController.java @@ -2,6 +2,7 @@ import capstone.recipable.domain.ingredient.service.NaverSearchImageService; import capstone.recipable.domain.recipe.dto.request.CreateRecipeRequest; +import capstone.recipable.domain.recipe.dto.response.CreateRecipeResponse; import capstone.recipable.domain.recipe.dto.response.ImageResponse; import capstone.recipable.domain.recipe.dto.response.RecipeDetailsResponse; import capstone.recipable.domain.recipe.dto.response.RecipeVideoResponse; @@ -49,8 +50,8 @@ public ResponseEntity> getImage(@RequestParam Str 저장한 레시피와 레시피 관련 영상을 반환해줍니다. """) @PostMapping - public ResponseEntity> createRecipe(@RequestBody CreateRecipeRequest request) throws IOException { - RecipeDetailsResponse response = recipeService.createRecipe(request); + public ResponseEntity> createRecipe(@RequestBody CreateRecipeRequest request) throws IOException { + CreateRecipeResponse response = recipeService.createRecipe(request); return SuccessResponse.of(response); } diff --git a/src/main/java/capstone/recipable/domain/recipe/dto/response/CreateRecipeResponse.java b/src/main/java/capstone/recipable/domain/recipe/dto/response/CreateRecipeResponse.java new file mode 100644 index 0000000..e16ea49 --- /dev/null +++ b/src/main/java/capstone/recipable/domain/recipe/dto/response/CreateRecipeResponse.java @@ -0,0 +1,47 @@ +package capstone.recipable.domain.recipe.dto.response; + +import capstone.recipable.domain.bookmark.repository.BookmarkRepository; +import capstone.recipable.domain.recipe.entity.Recipe; +import lombok.*; + +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Builder +public class CreateRecipeResponse { + private Long recipeId; + + private String recipeName; + + private String introduce; + + private String recipeImg; + + private String ingredients; + + private String recipeDetails; + + private List recipeVideoResponses; + + private boolean bookmark = false; + + public static CreateRecipeResponse of(Recipe recipe) { + List responses = recipe.getRecipeVideos().stream() + .map(recipeVideos -> RecipeVideoResponse.of(recipeVideos.getVideoUrl(), + recipeVideos.getTitle(), + recipeVideos.getThumbnail())) + .toList(); + + return CreateRecipeResponse.builder() + .recipeId(recipe.getId()) + .recipeName(recipe.getRecipeName()) + .introduce(recipe.getIntroduce()) + .recipeImg(recipe.getRecipeImg()) + .ingredients(recipe.getIngredients()) + .recipeDetails(recipe.getRecipeDetails()) + .recipeVideoResponses(responses) + .build(); + } +} diff --git a/src/main/java/capstone/recipable/domain/recipe/dto/response/RecipeDetailsResponse.java b/src/main/java/capstone/recipable/domain/recipe/dto/response/RecipeDetailsResponse.java index 4e87ed4..1a6572d 100644 --- a/src/main/java/capstone/recipable/domain/recipe/dto/response/RecipeDetailsResponse.java +++ b/src/main/java/capstone/recipable/domain/recipe/dto/response/RecipeDetailsResponse.java @@ -1,5 +1,6 @@ package capstone.recipable.domain.recipe.dto.response; +import capstone.recipable.domain.bookmark.repository.BookmarkRepository; import capstone.recipable.domain.recipe.entity.Recipe; import lombok.*; @@ -25,7 +26,9 @@ public class RecipeDetailsResponse { private List recipeVideoResponses; - public static RecipeDetailsResponse of(Recipe recipe) { + private boolean bookmark; + + public static RecipeDetailsResponse of(Recipe recipe, boolean isMarked) { List responses = recipe.getRecipeVideos().stream() .map(recipeVideos -> RecipeVideoResponse.of(recipeVideos.getVideoUrl(), recipeVideos.getTitle(), @@ -40,6 +43,7 @@ public static RecipeDetailsResponse of(Recipe recipe) { .ingredients(recipe.getIngredients()) .recipeDetails(recipe.getRecipeDetails()) .recipeVideoResponses(responses) + .bookmark(isMarked) .build(); } } diff --git a/src/main/java/capstone/recipable/domain/recipe/service/RecipeService.java b/src/main/java/capstone/recipable/domain/recipe/service/RecipeService.java index f4c706c..b66d621 100644 --- a/src/main/java/capstone/recipable/domain/recipe/service/RecipeService.java +++ b/src/main/java/capstone/recipable/domain/recipe/service/RecipeService.java @@ -1,8 +1,10 @@ package capstone.recipable.domain.recipe.service; import capstone.recipable.domain.auth.jwt.SecurityContextProvider; +import capstone.recipable.domain.bookmark.repository.BookmarkRepository; import capstone.recipable.domain.ingredient.service.NaverSearchImageService; import capstone.recipable.domain.recipe.dto.request.CreateRecipeRequest; +import capstone.recipable.domain.recipe.dto.response.CreateRecipeResponse; import capstone.recipable.domain.recipe.dto.response.RecipeDetailsResponse; import capstone.recipable.domain.recipe.dto.response.RecipeVideoResponse; import capstone.recipable.domain.recipe.entity.Recipe; @@ -30,18 +32,25 @@ public class RecipeService { private final RecipeVideosRepository recipeVideosRepository; private final YoutubeService youtubeService; private final UserRepository userRepository; + private final BookmarkRepository bookmarkRepository; //레시피 상세 조회 public RecipeDetailsResponse getRecipeDetails(Long recipeId) { + Long userId = SecurityContextProvider.getAuthenticatedUserId(); + User user = userRepository.findById(userId) + .orElseThrow(() -> new ApplicationException(ErrorCode.USER_NOT_FOUND)); + Recipe recipe = recipeRepository.findById(recipeId) .orElseThrow(() -> new ApplicationException(ErrorCode.RECIPE_NOT_FOUND)); - return RecipeDetailsResponse.of(recipe); + boolean isMarked = bookmarkRepository.isBookmarked(user, recipe); + + return RecipeDetailsResponse.of(recipe, isMarked); } //레시피 생성 @Transactional - public RecipeDetailsResponse createRecipe(CreateRecipeRequest request) throws IOException { + public CreateRecipeResponse createRecipe(CreateRecipeRequest request) throws IOException { Long userId = SecurityContextProvider.getAuthenticatedUserId(); User user = userRepository.findById(userId) .orElseThrow(() -> new ApplicationException(ErrorCode.USER_NOT_FOUND)); @@ -60,6 +69,6 @@ public RecipeDetailsResponse createRecipe(CreateRecipeRequest request) throws IO recipe.updateVideo(recipeVideos); - return RecipeDetailsResponse.of(recipe); + return CreateRecipeResponse.of(recipe); } }