diff --git a/src/main/java/com/moongeul/backend/api/post/controller/PostController.java b/src/main/java/com/moongeul/backend/api/post/controller/PostController.java index 7c54193..7bf4ec1 100644 --- a/src/main/java/com/moongeul/backend/api/post/controller/PostController.java +++ b/src/main/java/com/moongeul/backend/api/post/controller/PostController.java @@ -1,8 +1,7 @@ package com.moongeul.backend.api.post.controller; -import com.moongeul.backend.api.post.dto.PostRequestDTO; -import com.moongeul.backend.api.post.dto.PostIdResponseDTO; -import com.moongeul.backend.api.post.dto.PostResponseDTO; +import com.moongeul.backend.api.post.dto.*; +import com.moongeul.backend.api.post.entity.PostVisibility; import com.moongeul.backend.api.post.service.PostService; import com.moongeul.backend.common.response.ApiResponse; import com.moongeul.backend.common.response.SuccessStatus; @@ -10,6 +9,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -44,6 +44,32 @@ public ResponseEntity> createPost(@Authentication return ApiResponse.success(SuccessStatus.CREATE_POST_SUCCESS, response); } + @Operation( + summary = "기록(게시글) 전체 조회 API", + description = "메인페이지(홈화면)에서 사용되는 기록(게시글)의 전체 조회 API 입니다." + + "

[enum] postVisibility -> 전체 공개 : PUBLIC, 팔로워 공개 : FOLLOWERS, 나만보기 : PRIVATE" + ) + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "기록(게시글) 전체 조회 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "페이지는 1 이상이어야 합니다.(1부터 시작)") + }) + @GetMapping + public ResponseEntity> getAllPost( + @AuthenticationPrincipal UserDetails userDetails, + @RequestParam(required = false, defaultValue = "PUBLIC") PostVisibility postVisibility, + @RequestParam(required = false, defaultValue = "1") @Min(value = 1, message = "페이지는 1 이상이어야 합니다.(1부터 시작)") Integer page, + @RequestParam(required = false, defaultValue = "10") @Min(value = 1, message = "한 페이지당 개수는 1 이상이어야 합니다.") Integer size + ) { + + PostAllRequestDTO postAllRequestDTO = PostAllRequestDTO.builder() + .postVisibility(postVisibility) + .page(page) + .size(size) + .build(); + PostAllResponseDTO response = postService.getPostAll(postAllRequestDTO, userDetails.getUsername()); + return ApiResponse.success(SuccessStatus.GET_ALL_POST_SUCCESS, response); + } + @Operation( summary = "기록(게시글) 상세 조회 API", description = "기록(게시글)의 상세 조회 API 입니다." @@ -53,9 +79,9 @@ public ResponseEntity> createPost(@Authentication @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "해당 기록(게시글)을 찾을 수 없습니다.") }) @GetMapping("/{id}") - public ResponseEntity> getPost(@PathVariable Long id) { + public ResponseEntity> getPost(@PathVariable Long id) { - PostResponseDTO response = postService.getPostDetail(id); + PostDTO response = postService.getPostDetail(id); return ApiResponse.success(SuccessStatus.GET_POST_SUCCESS, response); } diff --git a/src/main/java/com/moongeul/backend/api/post/dto/PostAllRequestDTO.java b/src/main/java/com/moongeul/backend/api/post/dto/PostAllRequestDTO.java new file mode 100644 index 0000000..8ad1660 --- /dev/null +++ b/src/main/java/com/moongeul/backend/api/post/dto/PostAllRequestDTO.java @@ -0,0 +1,23 @@ +package com.moongeul.backend.api.post.dto; + +import com.moongeul.backend.api.post.entity.PostVisibility; +import jakarta.validation.constraints.Min; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PostAllRequestDTO { + + private PostVisibility postVisibility = PostVisibility.PUBLIC; // 공개여부 (기본값 PUBLIC(전체공개)) + + @Min(value = 1, message = "페이지는 1 이상이어야 합니다.") + private Integer page = 1; // 페이지 번호 (기본값 1) + + @Min(value = 1, message = "한 페이지당 개수는 1 이상이어야 합니다.") + private Integer size = 10; // 한 페이지당 개수 (기본값 10, 최대 100) +} diff --git a/src/main/java/com/moongeul/backend/api/post/dto/PostAllResponseDTO.java b/src/main/java/com/moongeul/backend/api/post/dto/PostAllResponseDTO.java new file mode 100644 index 0000000..255ef41 --- /dev/null +++ b/src/main/java/com/moongeul/backend/api/post/dto/PostAllResponseDTO.java @@ -0,0 +1,22 @@ +package com.moongeul.backend.api.post.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PostAllResponseDTO { + + private Long total; // 전체 검색 결과 수 + private Integer page; // 현재 페이지 + private Integer size; // 페이지당 개수 + private Integer totalPages; // 전체 페이지 수 + private Boolean isLast; // 마지막 페이지 여부 + private List data; // 기록 리스트 +} diff --git a/src/main/java/com/moongeul/backend/api/post/dto/PostResponseDTO.java b/src/main/java/com/moongeul/backend/api/post/dto/PostDTO.java similarity index 92% rename from src/main/java/com/moongeul/backend/api/post/dto/PostResponseDTO.java rename to src/main/java/com/moongeul/backend/api/post/dto/PostDTO.java index bd35ca5..13178cb 100644 --- a/src/main/java/com/moongeul/backend/api/post/dto/PostResponseDTO.java +++ b/src/main/java/com/moongeul/backend/api/post/dto/PostDTO.java @@ -11,7 +11,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class PostResponseDTO { +public class PostDTO { private BookInfo bookInfo; // 책 정보 private double rating; // 별점 @@ -27,6 +27,7 @@ public static class BookInfo{ private String title; // 책 제목 private String author; // 저자 private String publisher; // 출판사 + private Double ratingAverage; // 별점 평균 } @Getter diff --git a/src/main/java/com/moongeul/backend/api/post/service/PostService.java b/src/main/java/com/moongeul/backend/api/post/service/PostService.java index d6843e1..3d819f6 100644 --- a/src/main/java/com/moongeul/backend/api/post/service/PostService.java +++ b/src/main/java/com/moongeul/backend/api/post/service/PostService.java @@ -7,12 +7,11 @@ import com.moongeul.backend.api.bookshelf.util.BookshelfCalculator; import com.moongeul.backend.api.member.entity.Member; import com.moongeul.backend.api.member.repository.MemberRepository; -import com.moongeul.backend.api.post.dto.PostRequestDTO; -import com.moongeul.backend.api.post.dto.PostIdResponseDTO; +import com.moongeul.backend.api.post.dto.*; import com.moongeul.backend.api.category.entity.Category; -import com.moongeul.backend.api.post.dto.PostResponseDTO; import com.moongeul.backend.api.post.entity.Post; import com.moongeul.backend.api.category.repository.CategoryRepository; +import com.moongeul.backend.api.post.entity.PostVisibility; import com.moongeul.backend.api.post.entity.Quote; import com.moongeul.backend.api.post.repository.PostRepository; import com.moongeul.backend.api.post.repository.QuoteRepository; @@ -21,6 +20,9 @@ import com.moongeul.backend.common.response.ErrorStatus; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +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; @@ -86,34 +88,68 @@ public PostIdResponseDTO createPost(PostRequestDTO postRequestDTO, String email) .build(); } + /* 기록(게시글) 전체 조회 */ + @Transactional + public PostAllResponseDTO getPostAll(PostAllRequestDTO postAllRequestDTO, String email){ + + Pageable pageable = PageRequest.of(postAllRequestDTO.getPage() - 1, postAllRequestDTO.getSize()); + + // 빈 페이지 객체로 초기화 (null 방지) + Page postPage = Page.empty(pageable); + + if(postAllRequestDTO.getPostVisibility().equals(PostVisibility.PUBLIC)){ + postPage = postRepository.findAll(pageable); + } else if(postAllRequestDTO.getPostVisibility().equals(PostVisibility.FOLLOWERS)){ + // TODO: 팔로워 게시물 조회 로직 (예: postRepository.findAllByFollowers(email, pageable)) + postPage = postRepository.findAll(pageable); // 임시 + } + + List postDTOList = new ArrayList<>(); + if (!postPage.isEmpty()) { + for(Post post : postPage.getContent()){ + postDTOList.add(getPostDetail(post.getId())); + } + } + + return PostAllResponseDTO.builder() + .total(postPage.getTotalElements()) + .page(postPage.getNumber() + 1) // 페이지 1부터 시작(임의 지정) + .size(postPage.getSize()) + .totalPages(postPage.getTotalPages()) + .isLast(postPage.isLast()) + .data(postDTOList) + .build(); + } + /* 기록(게시글) 상세 조회 */ @Transactional - public PostResponseDTO getPostDetail(Long postId){ + public PostDTO getPostDetail(Long postId){ Post post = getPost(postId); Book book = getBook(post.getBook().getIsbn()); // 책 정보(필요 정보만) DTO - PostResponseDTO.BookInfo bookInfo = PostResponseDTO.BookInfo.builder() + PostDTO.BookInfo bookInfo = PostDTO.BookInfo.builder() .isbn(book.getIsbn()) .bookImage(book.getBookImage()) .title(book.getTitle()) .author(book.getAuthor()) .publisher(book.getPublisher()) + .ratingAverage(book.getRatingAverage()) .build(); // 인상깊은구절 조회 List quotes = quoteRepository.findByPostId(postId); // 리스트 반환이기에 `orElseThrow()` 사용 x - List quoteDTOList = new ArrayList<>(); + List quoteDTOList = new ArrayList<>(); for(Quote quote : quotes){ - PostResponseDTO.QuoteDTO quoteDTO = PostResponseDTO.QuoteDTO.builder() + PostDTO.QuoteDTO quoteDTO = PostDTO.QuoteDTO.builder() .quoteContent(quote.getQuoteContent()) .pageNumber(quote.getPageNumber()) .build(); quoteDTOList.add(quoteDTO); } - return PostResponseDTO.builder() + return PostDTO.builder() .bookInfo(bookInfo) .rating(post.getRating()) .content(post.getContent()) diff --git a/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java b/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java index cd8fa20..60d9aaf 100644 --- a/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java +++ b/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java @@ -32,6 +32,7 @@ public enum SuccessStatus { /* POST */ CREATE_POST_SUCCESS(HttpStatus.OK, "글쓰기 성공"), + GET_ALL_POST_SUCCESS(HttpStatus.OK, "기록(게시글) 전체 조회 성공"), GET_POST_SUCCESS(HttpStatus.OK, "기록(게시글) 상세 조회 성공"), UPDATE_POST_SUCCESS(HttpStatus.OK, "기록(게시글) 수정 성공"), DELETE_POST_SUCCESS(HttpStatus.OK, "기록(게시글) 삭제 성공"),