diff --git a/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java b/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java index f45950d..b5b9af6 100644 --- a/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java +++ b/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java @@ -7,6 +7,7 @@ public record CategoryResponse( String name, String description ) { + public static CategoryResponse from(CategoryEntity entity) { return new CategoryResponse( entity.getId(), diff --git a/src/main/java/com/progbe/domain/prompt/controller/PromptController.java b/src/main/java/com/progbe/domain/prompt/controller/PromptController.java index 8f6a86a..236077a 100644 --- a/src/main/java/com/progbe/domain/prompt/controller/PromptController.java +++ b/src/main/java/com/progbe/domain/prompt/controller/PromptController.java @@ -156,5 +156,17 @@ public ApiResponse likePrompt(@PathVariable Long promptId, @ PromptLikeResponse likePrompt = promptService.likePrompt(promptId, userId); return ApiResponse.success(likePrompt); } + + /** + * 프롬프트 제목 기준 검색 API + * @param keyword + * @param pageable + * @return + */ + @GetMapping("/search/{keyword}") + public ApiResponse searchPrompts(@PathVariable("keyword") String keyword, Pageable pageable) { + PromptListResponse promptListResponse = promptService.searchPromptsByTitle(keyword, pageable); + return ApiResponse.success(promptListResponse); + } } diff --git a/src/main/java/com/progbe/domain/prompt/dto/PromptSummaryResponse.java b/src/main/java/com/progbe/domain/prompt/dto/PromptSummaryResponse.java index 294ef04..941ef1c 100644 --- a/src/main/java/com/progbe/domain/prompt/dto/PromptSummaryResponse.java +++ b/src/main/java/com/progbe/domain/prompt/dto/PromptSummaryResponse.java @@ -1,6 +1,7 @@ package com.progbe.domain.prompt.dto; import com.progbe.domain.category.dto.CategoryResponse; +import com.progbe.domain.prompt.entity.PromptEntity; import java.time.LocalDateTime; @@ -11,5 +12,14 @@ public record PromptSummaryResponse( LocalDateTime createdAt, LocalDateTime updatedAt ) { + public static PromptSummaryResponse of(PromptEntity promptEntity) { + return new PromptSummaryResponse( + promptEntity.getId(), + CategoryResponse.from(promptEntity.getCategory()), + promptEntity.getTitle(), + promptEntity.getCreatedAt(), + promptEntity.getUpdatedAt() + ); + } } diff --git a/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java b/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java index ac011e9..e2d86f6 100644 --- a/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java +++ b/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java @@ -60,6 +60,14 @@ public interface PromptRepository extends JpaRepository { "ORDER BY COUNT(pl) DESC, p.createdAt DESC") Page findPromptSortedLikeCount(Pageable pageable); + @Query("SELECT p FROM PromptEntity p " + + "JOIN FETCH p.category " + + "WHERE p.title LIKE %:keyword% " + + "AND p.deletedAt IS NULL " + + "ORDER BY p.createdAt DESC") + Page findByTitleContaining(@Param("keyword") String keyword, Pageable pageable); + + @Query("SELECT p FROM PromptEntity p " + "JOIN FETCH p.category " + "LEFT JOIN PromptLikeEntity pl ON pl.prompt = p " + diff --git a/src/main/java/com/progbe/domain/prompt/service/PromptService.java b/src/main/java/com/progbe/domain/prompt/service/PromptService.java index 46c706f..1169f65 100644 --- a/src/main/java/com/progbe/domain/prompt/service/PromptService.java +++ b/src/main/java/com/progbe/domain/prompt/service/PromptService.java @@ -190,4 +190,16 @@ public PromptLikeResponse likePrompt(Long promptId, Long userId) { promptLikeRepository.save(newLike); return PromptLikeResponse.of(LikeStatus.LIKE); } + + // 프롬프트 검색 로직 (#33) + public PromptListResponse searchPromptsByTitle(String keyword, Pageable pageable) { + Page searchResult = promptRepository.findByTitleContaining(keyword, pageable); + + return new PromptListResponse( + searchResult.getContent().stream() + .map(PromptSummaryResponse::of) + .toList(), + searchResult.getTotalElements() + ); + } }