From f3b82cbfd69d41bd6c2e3536da1b6fa92e21f97a Mon Sep 17 00:00:00 2001 From: HyeonSeong Date: Thu, 19 Feb 2026 15:36:16 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A1=AC=ED=94=84?= =?UTF-8?q?=ED=8A=B8=20=EC=B5=9C=EC=8B=A0=EC=88=9C=20API=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/category/dto/CategoryResponse.java | 9 ++++++++ .../prompt/controller/PromptController.java | 13 ++++++++++++ .../prompt/repository/PromptRepository.java | 6 ++++++ .../domain/prompt/service/PromptService.java | 21 +++++++++++++++++++ 4 files changed, 49 insertions(+) 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 b4b6f18..f45950d 100644 --- a/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java +++ b/src/main/java/com/progbe/domain/category/dto/CategoryResponse.java @@ -1,9 +1,18 @@ package com.progbe.domain.category.dto; +import com.progbe.domain.category.entity.CategoryEntity; + public record CategoryResponse( Long categoryId, String name, String description ) { + public static CategoryResponse from(CategoryEntity entity) { + return new CategoryResponse( + entity.getId(), + entity.getName(), + entity.getDescription() + ); + } } 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 55b54a1..bd555f9 100644 --- a/src/main/java/com/progbe/domain/prompt/controller/PromptController.java +++ b/src/main/java/com/progbe/domain/prompt/controller/PromptController.java @@ -9,6 +9,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -108,5 +109,17 @@ public ResponseEntity> deletePrompt( promptService.deletePrompt(promptId, userId); return ResponseEntity.ok(ApiResponse.success(null)); } + + /** + * 프롬프트 최신순 API + * @param pageable + * @return + */ + @GetMapping("/createDesc") + public ApiResponse createPromptDesc( + @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) { + PromptListResponse prompts = promptService.getPromptsSortedTime(pageable); + return ApiResponse.success(prompts); + } } 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 e158106..fd7d328 100644 --- a/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java +++ b/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java @@ -29,5 +29,11 @@ public interface PromptRepository extends JpaRepository { "WHERE p.user.id IN :userIds AND p.deletedAt IS NULL " + "GROUP BY p.user.id") List countByUserIdsGrouped(@Param("userIds") List userIds); + + @Query("SELECT p FROM PromptEntity p " + + "JOIN FETCH p.category " + + "WHERE p.category = 'PUBLIC' " + + "ORDER BY p.createdAt DESC") + Page findPromptSortedTime(Pageable pageable); } 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 f5bdfa0..53afcc9 100644 --- a/src/main/java/com/progbe/domain/prompt/service/PromptService.java +++ b/src/main/java/com/progbe/domain/prompt/service/PromptService.java @@ -1,5 +1,6 @@ package com.progbe.domain.prompt.service; +import com.progbe.domain.category.dto.CategoryResponse; import com.progbe.domain.category.entity.CategoryEntity; import com.progbe.domain.category.repository.CategoryRepository; import com.progbe.domain.prompt.dto.*; @@ -107,4 +108,24 @@ public void deletePrompt(Long promptId, Long userId) { prompt.delete(); promptRepository.save(prompt); } + + // 최신순 프롬프트 띄어주기 로직 (#31) + public PromptListResponse getPromptsSortedTime(Pageable pageable) { + Page promptEntities = promptRepository.findPromptSortedTime(pageable); + + List promptList = promptEntities.getContent().stream() + .map(entity -> new PromptSummaryResponse( + entity.getId(), + promptMapper.toCategoryResponse(entity.getCategory()), + entity.getTitle(), + entity.getCreatedAt(), + entity.getUpdatedAt() + )) + .toList(); + + return new PromptListResponse( + promptList, + promptEntities.getTotalElements() + ); + } } From e0838157316a3b99a65a5b5092d1a87d3b6e5329 Mon Sep 17 00:00:00 2001 From: HyeonSeong Date: Thu, 19 Feb 2026 15:45:18 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A1=AC=ED=94=84?= =?UTF-8?q?=ED=8A=B8=20=EC=A2=8B=EC=95=84=EC=9A=94=EC=88=9C=20API=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prompt/controller/PromptController.java | 14 +++++++++++++ .../prompt/repository/PromptRepository.java | 10 +++++++++- .../domain/prompt/service/PromptService.java | 20 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) 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 bd555f9..54828ee 100644 --- a/src/main/java/com/progbe/domain/prompt/controller/PromptController.java +++ b/src/main/java/com/progbe/domain/prompt/controller/PromptController.java @@ -13,6 +13,7 @@ import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.parameters.P; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; @@ -121,5 +122,18 @@ public ApiResponse createPromptDesc( PromptListResponse prompts = promptService.getPromptsSortedTime(pageable); return ApiResponse.success(prompts); } + + /** + * 프롬프트 좋아요순 API + * @param pageable + * @return + */ + @GetMapping("/likeDesc") + public ApiResponse likePromptDesc( + @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) { + PromptListResponse prompts = promptService.getPromptsSortedLikeCount(pageable); + return ApiResponse.success(prompts); + } + } 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 fd7d328..547be06 100644 --- a/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java +++ b/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java @@ -32,8 +32,16 @@ public interface PromptRepository extends JpaRepository { @Query("SELECT p FROM PromptEntity p " + "JOIN FETCH p.category " + - "WHERE p.category = 'PUBLIC' " + + "WHERE p.deletedAt IS NULL " + "ORDER BY p.createdAt DESC") Page findPromptSortedTime(Pageable pageable); + + @Query("SELECT p FROM PromptEntity p " + + "JOIN FETCH p.category " + + "LEFT JOIN PromptLikeEntity pl ON pl.prompt = p " + + "WHERE p.deletedAt IS NULL " + + "GROUP BY p.id, p.category.id " + + "ORDER BY COUNT(pl) DESC, p.createdAt DESC") + Page findPromptSortedLikeCount(Pageable pageable); } 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 53afcc9..6d03830 100644 --- a/src/main/java/com/progbe/domain/prompt/service/PromptService.java +++ b/src/main/java/com/progbe/domain/prompt/service/PromptService.java @@ -128,4 +128,24 @@ public PromptListResponse getPromptsSortedTime(Pageable pageable) { promptEntities.getTotalElements() ); } + + // 좋아요순 프롬프트 띄어주기 로직 (#31) + public PromptListResponse getPromptsSortedLikeCount(Pageable pageable) { + Page promptEntities = promptRepository.findPromptSortedLikeCount(pageable); + + List promptList = promptEntities.getContent().stream() + .map(entity -> new PromptSummaryResponse( + entity.getId(), + promptMapper.toCategoryResponse(entity.getCategory()), + entity.getTitle(), + entity.getCreatedAt(), + entity.getUpdatedAt() + )) + .toList(); + + return new PromptListResponse( + promptList, + promptEntities.getTotalElements() + ); + } } From f8d32608de5800ca41eb5f51376fb028f627a413 Mon Sep 17 00:00:00 2001 From: HyeonSeong Date: Thu, 19 Feb 2026 15:56:44 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat=20:=20=EA=B8=88=EC=9D=BC=20=EA=B0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=A7=8E=EC=9D=80=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=EC=88=9C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prompt/controller/PromptController.java | 17 +++++++++++++---- .../prompt/repository/PromptRepository.java | 14 ++++++++++++++ .../domain/prompt/service/PromptService.java | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) 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 54828ee..80a4d80 100644 --- a/src/main/java/com/progbe/domain/prompt/controller/PromptController.java +++ b/src/main/java/com/progbe/domain/prompt/controller/PromptController.java @@ -1,9 +1,6 @@ package com.progbe.domain.prompt.controller; -import com.progbe.domain.prompt.dto.PromptCreateRequest; -import com.progbe.domain.prompt.dto.PromptListResponse; -import com.progbe.domain.prompt.dto.PromptResponse; -import com.progbe.domain.prompt.dto.PromptUpdateRequest; +import com.progbe.domain.prompt.dto.*; import com.progbe.domain.prompt.service.PromptService; import com.progbe.global.common.ApiResponse; import jakarta.validation.Valid; @@ -17,6 +14,8 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/prompts") @RequiredArgsConstructor @@ -135,5 +134,15 @@ public ApiResponse likePromptDesc( return ApiResponse.success(prompts); } + /** + * 금일 가장 많은 좋아요순 API + * @return + */ + @GetMapping("/today-hot") + public ApiResponse> getTodayHotPrompts() { + List prompts = promptService.getDailyHotPrompts(); + return ApiResponse.success(prompts); + } + } 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 547be06..d796be7 100644 --- a/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java +++ b/src/main/java/com/progbe/domain/prompt/repository/PromptRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -43,5 +44,18 @@ public interface PromptRepository extends JpaRepository { "GROUP BY p.id, p.category.id " + "ORDER BY COUNT(pl) DESC, p.createdAt DESC") Page findPromptSortedLikeCount(Pageable pageable); + + @Query("SELECT p FROM PromptEntity p " + + "JOIN FETCH p.category " + + "LEFT JOIN PromptLikeEntity pl ON pl.prompt = p " + + "AND pl.createdAt >= :start AND pl.createdAt <= :end " + + "WHERE p.deletedAt IS NULL " + + "GROUP BY p.id, p.category.id " + + "ORDER BY COUNT(pl) DESC, p.createdAt DESC") + List findDailyHotPrompts( + @Param("start") LocalDateTime start, + @Param("end") LocalDateTime end, + Pageable pageable + ); } 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 6d03830..ded066b 100644 --- a/src/main/java/com/progbe/domain/prompt/service/PromptService.java +++ b/src/main/java/com/progbe/domain/prompt/service/PromptService.java @@ -13,10 +13,14 @@ import com.progbe.global.error.exception.CustomException; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; @Service @@ -148,4 +152,17 @@ public PromptListResponse getPromptsSortedLikeCount(Pageable pageable) { promptEntities.getTotalElements() ); } + + // 오늘의 좋아요를 가장 많이 받은 프롬프트 띄어주기 로직 (#31) + // LocalDateTime 을 이용해서 오늘 (= 00시 ~ 23시 59분) 으로 설정했습니다. + public List getDailyHotPrompts() { + LocalDateTime start = LocalDate.now().atStartOfDay(); + LocalDateTime end = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); + + Pageable topFive = PageRequest.of(0, 3); + + List promptEntities = promptRepository.findDailyHotPrompts(start, end, topFive); + + return promptMapper.toPromptSummaryResponseList(promptEntities); + } }