Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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()
);
}
}

Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
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;
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;
import org.springframework.security.core.parameters.P;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/prompts")
@RequiredArgsConstructor
Expand Down Expand Up @@ -108,5 +109,40 @@ public ResponseEntity<ApiResponse<Void>> deletePrompt(
promptService.deletePrompt(promptId, userId);
return ResponseEntity.ok(ApiResponse.success(null));
}

/**
* 프롬프트 최신순 API
* @param pageable
* @return
*/
@GetMapping("/createDesc")
public ApiResponse<PromptListResponse> createPromptDesc(
@PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
PromptListResponse prompts = promptService.getPromptsSortedTime(pageable);
return ApiResponse.success(prompts);
}

/**
* 프롬프트 좋아요순 API
* @param pageable
* @return
*/
@GetMapping("/likeDesc")
public ApiResponse<PromptListResponse> likePromptDesc(
@PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
PromptListResponse prompts = promptService.getPromptsSortedLikeCount(pageable);
return ApiResponse.success(prompts);
}

/**
* 금일 가장 많은 좋아요순 API
* @return
*/
@GetMapping("/today-hot")
public ApiResponse<List<PromptSummaryResponse>> getTodayHotPrompts() {
List<PromptSummaryResponse> prompts = promptService.getDailyHotPrompts();
return ApiResponse.success(prompts);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -29,5 +30,32 @@ public interface PromptRepository extends JpaRepository<PromptEntity, Long> {
"WHERE p.user.id IN :userIds AND p.deletedAt IS NULL " +
"GROUP BY p.user.id")
List<UserCountDto> countByUserIdsGrouped(@Param("userIds") List<Long> userIds);

@Query("SELECT p FROM PromptEntity p " +
"JOIN FETCH p.category " +
"WHERE p.deletedAt IS NULL " +
"ORDER BY p.createdAt DESC")
Page<PromptEntity> 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<PromptEntity> 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<PromptEntity> findDailyHotPrompts(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
Pageable pageable
);
}

58 changes: 58 additions & 0 deletions src/main/java/com/progbe/domain/prompt/service/PromptService.java
Original file line number Diff line number Diff line change
@@ -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.*;
Expand All @@ -12,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
Expand Down Expand Up @@ -107,4 +112,57 @@ public void deletePrompt(Long promptId, Long userId) {
prompt.delete();
promptRepository.save(prompt);
}

// 최신순 프롬프트 띄어주기 로직 (#31)
public PromptListResponse getPromptsSortedTime(Pageable pageable) {
Page<PromptEntity> promptEntities = promptRepository.findPromptSortedTime(pageable);

List<PromptSummaryResponse> 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()
);
}

// 좋아요순 프롬프트 띄어주기 로직 (#31)
public PromptListResponse getPromptsSortedLikeCount(Pageable pageable) {
Page<PromptEntity> promptEntities = promptRepository.findPromptSortedLikeCount(pageable);

List<PromptSummaryResponse> 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()
);
}

// 오늘의 좋아요를 가장 많이 받은 프롬프트 띄어주기 로직 (#31)
// LocalDateTime 을 이용해서 오늘 (= 00시 ~ 23시 59분) 으로 설정했습니다.
public List<PromptSummaryResponse> getDailyHotPrompts() {
LocalDateTime start = LocalDate.now().atStartOfDay();
LocalDateTime end = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

Pageable topFive = PageRequest.of(0, 3);

List<PromptEntity> promptEntities = promptRepository.findDailyHotPrompts(start, end, topFive);

return promptMapper.toPromptSummaryResponseList(promptEntities);
}
}