diff --git a/src/main/java/cc/backend/admin/amateurShow/controller/AdminAmateurShowController.java b/src/main/java/cc/backend/admin/amateurShow/controller/AdminAmateurShowController.java index 453323ed..90093328 100644 --- a/src/main/java/cc/backend/admin/amateurShow/controller/AdminAmateurShowController.java +++ b/src/main/java/cc/backend/admin/amateurShow/controller/AdminAmateurShowController.java @@ -7,6 +7,7 @@ import cc.backend.admin.amateurShow.dto.AdminAmateurShowSummaryResponseDTO; import cc.backend.admin.amateurShow.service.AdminAmateurShowService; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import com.google.protobuf.Api; import io.swagger.v3.oas.annotations.Operation; @@ -16,6 +17,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -44,7 +46,7 @@ public class AdminAmateurShowController { ) } ) - public ApiResponse> showList( + public ApiResponse> showList( @Parameter(description = "페이지 번호(0부터)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -54,8 +56,8 @@ public ApiResponse> showList( @Parameter(description = "검색 키워드, 공연면", example = "실종") @RequestParam(required = false) String keyword ) { - Slice slice = adminAmateurShowService.getShowList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); } + + return ApiResponse.onSuccess(adminAmateurShowService.getShowList(page, size, keyword)); } @GetMapping("/{showId}") @Operation( diff --git a/src/main/java/cc/backend/admin/amateurShow/controller/AdminApprovalController.java b/src/main/java/cc/backend/admin/amateurShow/controller/AdminApprovalController.java index e0516e1c..72d5dda6 100644 --- a/src/main/java/cc/backend/admin/amateurShow/controller/AdminApprovalController.java +++ b/src/main/java/cc/backend/admin/amateurShow/controller/AdminApprovalController.java @@ -6,6 +6,7 @@ import cc.backend.admin.amateurShow.service.AdminAmateurShowService; import cc.backend.admin.amateurShow.service.AdminApprovalService; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -13,6 +14,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -31,7 +33,7 @@ public class AdminApprovalController { summary = "소극장 공연 관리 - 등록 요청 관리", description = "등록 요청 관리 첫페이지, 리스트 조회입니다." ) - public ApiResponse> getApprovalList( + public ApiResponse> getApprovalList( @Parameter(description = "페이지 번호(0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -41,8 +43,8 @@ public ApiResponse> getApprovalList( @Parameter(description = "검색 키워드, 공연 명으로 검색", example = "실종") @RequestParam(required = false) String keyword ){ - Slice slice = adminApprovalService.getApprovalList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); + + return ApiResponse.onSuccess(adminApprovalService.getApprovalList(page, size, keyword)); } @PatchMapping("/{showId}/approve") diff --git a/src/main/java/cc/backend/admin/amateurShow/service/AdminAmateurShowService.java b/src/main/java/cc/backend/admin/amateurShow/service/AdminAmateurShowService.java index d8650ce0..bfc19601 100644 --- a/src/main/java/cc/backend/admin/amateurShow/service/AdminAmateurShowService.java +++ b/src/main/java/cc/backend/admin/amateurShow/service/AdminAmateurShowService.java @@ -7,6 +7,7 @@ import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.repository.AmateurShowRepository; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; @@ -30,23 +31,17 @@ @Transactional(readOnly = true) public class AdminAmateurShowService { private final AmateurShowRepository amateurShowRepository; - private final ApplicationEventPublisher eventPublisher; - public Slice getShowList(int page, int size, String keyword){ + public PageResponse getShowList(int page, int size, String keyword){ Pageable pageable = PageRequest.of(page, size, Sort.by("id").ascending()); - Page pageResult; - if (keyword != null && !keyword.isBlank()) { - pageResult = amateurShowRepository.findByNameContainingIgnoreCase(keyword, pageable); - } else { - pageResult = amateurShowRepository.findAll(pageable); - } + keyword = (keyword == null) ? "" : keyword.trim(); + Page pageResult = amateurShowRepository.findByNameContainingIgnoreCase(keyword, pageable); - List rows = pageResult.getContent().stream() - .map(this::toListDto) - .toList(); - return new SliceImpl<>(rows, pageable, pageResult.hasNext()); + Page dtoPage = pageResult.map(this::toListDto); + + return PageResponse.of(dtoPage); } private AdminAmateurShowListResponseDTO toListDto(AmateurShow show){ diff --git a/src/main/java/cc/backend/admin/amateurShow/service/AdminApprovalService.java b/src/main/java/cc/backend/admin/amateurShow/service/AdminApprovalService.java index be3dfe4d..f06eea33 100644 --- a/src/main/java/cc/backend/admin/amateurShow/service/AdminApprovalService.java +++ b/src/main/java/cc/backend/admin/amateurShow/service/AdminApprovalService.java @@ -5,6 +5,7 @@ import cc.backend.admin.amateurShow.dto.AdminApprovalListResponseDTO; import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.repository.AmateurShowRepository; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.event.entity.ApproveShowEvent; @@ -52,7 +53,7 @@ public AdminAmateurShowSummaryResponseDTO rejectShow(Long showId, AdminAmateurSh return AdminAmateurShowSummaryResponseDTO.from(show); } - public Slice getApprovalList(int page, int size, String keyword) { + public PageResponse getApprovalList(int page, int size, String keyword) { Pageable pageable = PageRequest.of(page, size, Sort.by("id").ascending()); Page pageResult = @@ -60,11 +61,9 @@ public Slice getApprovalList(int page, int size, S ? amateurShowRepository.findByNameContainingIgnoreCase(keyword, pageable) : amateurShowRepository.findAll(pageable); - List content = pageResult.getContent().stream() - .map(this::toApprovalDto) - .toList(); + Page dtoPage = pageResult.map(this::toApprovalDto); - return new SliceImpl<>(content, pageable, pageResult.hasNext()); + return PageResponse.of(dtoPage); } private AdminApprovalListResponseDTO toApprovalDto(AmateurShow show) { diff --git a/src/main/java/cc/backend/admin/board/controller/AdminBoardController.java b/src/main/java/cc/backend/admin/board/controller/AdminBoardController.java index bcfff86f..705efa0d 100644 --- a/src/main/java/cc/backend/admin/board/controller/AdminBoardController.java +++ b/src/main/java/cc/backend/admin/board/controller/AdminBoardController.java @@ -5,6 +5,7 @@ import cc.backend.admin.board.dto.response.AdminReportSummary; import cc.backend.admin.board.service.AdminBoardService; import cc.backend.admin.board.service.AdminReportService; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import cc.backend.board.entity.enums.ReportTarget; import io.swagger.v3.oas.annotations.Operation; @@ -14,6 +15,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -83,7 +85,7 @@ public ResponseEntity deleteTarget( ) }) @GetMapping - public cc.backend.apiPayLoad.ApiResponse> getAllBoardsForAdmin( + public cc.backend.apiPayLoad.ApiResponse> getAllBoardsForAdmin( @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @Parameter(description = "페이지 크기", example = "20") @@ -91,8 +93,7 @@ public cc.backend.apiPayLoad.ApiResponse> @Parameter(description = "검색 키워드, 게시글 제목", example = "예매 방법 꿀팁") @RequestParam(required = false) String keyword) { - Slice slice = adminBoardService.getAllBoardsForAdmin(page, size, keyword); - return cc.backend.apiPayLoad.ApiResponse.onSuccess(SliceResponse.of(slice)); + return cc.backend.apiPayLoad.ApiResponse.onSuccess(adminBoardService.getAllBoardsForAdmin(page, size, keyword)); } @Operation( diff --git a/src/main/java/cc/backend/admin/board/service/AdminBoardService.java b/src/main/java/cc/backend/admin/board/service/AdminBoardService.java index b67c0c56..0ff7ab02 100644 --- a/src/main/java/cc/backend/admin/board/service/AdminBoardService.java +++ b/src/main/java/cc/backend/admin/board/service/AdminBoardService.java @@ -3,6 +3,7 @@ import cc.backend.admin.board.dto.response.AdminBoardDetailResponse; import cc.backend.admin.board.dto.response.AdminBoardDetailWithCommentsResponse; import cc.backend.admin.board.dto.response.AdminBoardListResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.board.dto.response.CommentResponse; @@ -16,10 +17,7 @@ import cc.backend.image.entity.Image; import cc.backend.image.repository.ImageRepository; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.Sort; +import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -39,14 +37,17 @@ public class AdminBoardService { //게시글 목록 조회 @Transactional(readOnly = true) - public Slice getAllBoardsForAdmin(int page, int size, String keyword) { + public PageResponse getAllBoardsForAdmin(int page, int size, String keyword) { // 관리자는 삭제된 게시글도 볼 수 있도록 @SQLDelete 우회 Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending()); - Slice boards = (keyword != null && !keyword.isBlank()) + + Page boards = (keyword != null && !keyword.isBlank()) ? boardRepository.searchBoardsIncludingDeletedByTitle(keyword, pageable) : boardRepository.findAllBoardsIncludingDeleted(pageable); - return boards.map(AdminBoardListResponse::from); + return PageResponse.of( + boards.map(AdminBoardListResponse::from) + ); } //게시글 상세조회 diff --git a/src/main/java/cc/backend/admin/dashboard/controller/DashboardController.java b/src/main/java/cc/backend/admin/dashboard/controller/DashboardController.java index c016bace..84aa89a6 100644 --- a/src/main/java/cc/backend/admin/dashboard/controller/DashboardController.java +++ b/src/main/java/cc/backend/admin/dashboard/controller/DashboardController.java @@ -5,6 +5,7 @@ import cc.backend.admin.dashboard.dto.VisitResponseDTO; import cc.backend.admin.dashboard.service.DashboardService; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -41,27 +42,27 @@ public ApiResponse> getMonthlyVisits() @GetMapping("/approval") @Operation(summary = "등록 요청 - 간편보기", description = "대쉬보드에서 등록 요청 리스트를 조회합니다.") - public ApiResponse> getApprovalSummary( + public ApiResponse> getApprovalSummary( @Parameter(description = "페이지 번호(0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @Parameter(description = "페이지 크기", example = "10") @RequestParam(defaultValue = "10") int size ){ - Slice slice = dashBoardService.getApprovalList(page, size); - return ApiResponse.onSuccess(SliceResponse.of(slice)); + + return ApiResponse.onSuccess(dashBoardService.getApprovalList(page, size)); } @GetMapping("/reservation") @Operation(summary = "예약 현황 - 간편보기", description = "대쉬보드에서 예약 현황 리스트를 조회합니다.") - public ApiResponse> getReservationSummary( + public ApiResponse> getReservationSummary( @Parameter(description = "페이지 번호(0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @Parameter(description = "페이지 크기", example = "10") @RequestParam(defaultValue = "10") int size ){ - Slice slice = dashBoardService.getReservationList(page, size); - return ApiResponse.onSuccess(SliceResponse.of(slice)); } + return ApiResponse.onSuccess(dashBoardService.getReservationList(page, size) + ); } } diff --git a/src/main/java/cc/backend/admin/dashboard/service/DashboardService.java b/src/main/java/cc/backend/admin/dashboard/service/DashboardService.java index 8ecd7fa4..5a549730 100644 --- a/src/main/java/cc/backend/admin/dashboard/service/DashboardService.java +++ b/src/main/java/cc/backend/admin/dashboard/service/DashboardService.java @@ -7,6 +7,7 @@ import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.repository.AmateurRoundsRepository; import cc.backend.amateurShow.repository.AmateurShowRepository; +import cc.backend.apiPayLoad.PageResponse; import com.google.analytics.data.v1beta.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; @@ -81,21 +82,20 @@ public List getMonthlyVisits() { private static final DateTimeFormatter DT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd / HH:mm"); - public Slice getApprovalList(int page, int size) { + public PageResponse getApprovalList(int page, int size) { Pageable pageable = PageRequest.of(page, size, Sort.by("id").ascending()); Page result = amateurShowRepository.findAll(pageable); - List content = result.getContent().stream() - .map(this::toSummaryDto) - .toList(); + Page dtoPage = result.map(this::toSummaryDto); - return new SliceImpl<>(content, pageable, result.hasNext()); + return PageResponse.of(dtoPage); } private ApprovalSummaryResponseDTO toSummaryDto(AmateurShow s) { String dateTime = s.getCreatedAt().format(DT_FMT); - int capacity = s.getTotalSoldTicket(); + int capacity = s.getTotalSoldTicket() != null ? s.getTotalSoldTicket() : 0; // null이면 0으로 처리 + return ApprovalSummaryResponseDTO.builder() .showId(s.getId()) @@ -105,7 +105,7 @@ private ApprovalSummaryResponseDTO toSummaryDto(AmateurShow s) { .build(); } - public Slice getReservationList(int page, int size) { + public PageResponse getReservationList(int page, int size) { Sort sort = Sort.by( Sort.Order.asc("performanceDateTime"), Sort.Order.asc("id") @@ -114,11 +114,8 @@ public Slice getReservationList(int page, int siz Page result = amateurRoundsRepository.findAll(pageable); - List content = result.getContent().stream() - .map(this::toDto) - .toList(); - - return new SliceImpl<>(content, pageable, result.hasNext()); + Page dtoPage = result.map(this::toDto); + return PageResponse.of(dtoPage); } private ReservationSummaryResponseDTO toDto(AmateurRounds r) { diff --git a/src/main/java/cc/backend/admin/inquiry/AdminInquiryController.java b/src/main/java/cc/backend/admin/inquiry/AdminInquiryController.java index 305d2198..01887136 100644 --- a/src/main/java/cc/backend/admin/inquiry/AdminInquiryController.java +++ b/src/main/java/cc/backend/admin/inquiry/AdminInquiryController.java @@ -3,16 +3,14 @@ import cc.backend.admin.inquiry.dto.AdminInquiryRequestDTO; import cc.backend.admin.inquiry.dto.AdminInquiryResponseDTO; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import com.google.protobuf.Api; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.Sort; +import org.springframework.data.domain.*; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -42,7 +40,7 @@ public ApiResponse replyI @Operation(summary = "관리자 문의 리스트/검색 API", description = "관리자가 문의 리스트를 합니다. keyword로 제목/내용 검색을 합니다.") @GetMapping("") - public ApiResponse> getInquiryList( + public ApiResponse> getInquiryList( @Parameter(description = "검색 키워드(제목/내용)") @RequestParam(required = false) String keyword, @Parameter(description = "페이지 번호(0부터 시작)", example = "0") @@ -51,11 +49,7 @@ public ApiResponse slice = - adminInquiryService.getInquiryList(keyword, pageable); - - return ApiResponse.onSuccess(SliceResponse.of(slice)); + return ApiResponse.onSuccess(adminInquiryService.getInquiryList(keyword, pageable)); } } diff --git a/src/main/java/cc/backend/admin/inquiry/AdminInquiryService.java b/src/main/java/cc/backend/admin/inquiry/AdminInquiryService.java index b76c96d0..47408f54 100644 --- a/src/main/java/cc/backend/admin/inquiry/AdminInquiryService.java +++ b/src/main/java/cc/backend/admin/inquiry/AdminInquiryService.java @@ -3,15 +3,13 @@ import cc.backend.admin.inquiry.converter.AdminInquiryResponseConverter; import cc.backend.admin.inquiry.dto.AdminInquiryRequestDTO; import cc.backend.admin.inquiry.dto.AdminInquiryResponseDTO; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.inquiry.entity.Inquiry; import cc.backend.inquiry.repository.InquiryRepository; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; +import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @@ -36,8 +34,8 @@ public AdminInquiryResponseDTO.AdminInquiryDetailResponseDTO replyInquiry(Long i return AdminInquiryResponseConverter.toInquiryDetailDTO(inquiry); } - public Slice getInquiryList(String keyword, - Pageable pageable) { + public PageResponse getInquiryList(String keyword, + Pageable pageable) { Page inquiryPage; if (StringUtils.hasText(keyword)) { // 제목 or 내용 @@ -47,9 +45,10 @@ public Slice getInquiryL // 없으면 inquiryPage = inquiryRepository.findAll(pageable); } - List content = inquiryPage.getContent().stream() - .map(AdminInquiryResponseConverter::toSummaryDTO) - .toList(); - return new SliceImpl<>(content, pageable, inquiryPage.hasNext()); + Page dtoPage = + inquiryPage.map(AdminInquiryResponseConverter::toSummaryDTO); + + // PageResponse.of 사용 + return PageResponse.of(dtoPage); } } diff --git a/src/main/java/cc/backend/admin/member/AdminMemberController.java b/src/main/java/cc/backend/admin/member/AdminMemberController.java index d6e1a4e6..46d084c8 100644 --- a/src/main/java/cc/backend/admin/member/AdminMemberController.java +++ b/src/main/java/cc/backend/admin/member/AdminMemberController.java @@ -4,11 +4,13 @@ import cc.backend.admin.member.dto.AdminMemberListResponseDTO; import cc.backend.admin.member.dto.UpdateMemberDetailRequestDTO; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.*; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.parameters.P; @@ -24,7 +26,7 @@ public class AdminMemberController { @Operation(summary = "사용자 관리 리스트 조회", description = "모든 사용자를 id순으로 리스트로 조회합니다.") @GetMapping("/list") - public ApiResponse> getAllMember( + public ApiResponse> getAllMember( @Parameter(description = "페이지 번호(0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -34,8 +36,7 @@ public ApiResponse> getAllMember( @Parameter(description = "검색할 사용자 아이디(username)", example = "jihee") @RequestParam(required = false) String keyword ) { - Slice slice = adminMemberService.getMemberList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); + return ApiResponse.onSuccess(adminMemberService.getMemberList(page, size, keyword)); } @Operation(summary = "사용자 관리-상세", description = "모든 사용자를 id순으로 리스트로 조회합니다.") diff --git a/src/main/java/cc/backend/admin/member/AdminMemberService.java b/src/main/java/cc/backend/admin/member/AdminMemberService.java index 33bc854c..6de5f777 100644 --- a/src/main/java/cc/backend/admin/member/AdminMemberService.java +++ b/src/main/java/cc/backend/admin/member/AdminMemberService.java @@ -4,6 +4,7 @@ import cc.backend.admin.member.dto.AdminMemberListResponseDTO; import cc.backend.admin.member.dto.UpdateMemberDetailRequestDTO; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.member.entity.Member; @@ -22,7 +23,7 @@ public class AdminMemberService { private final MemberRepository memberRepository; - public Slice getMemberList(int page, int size, String keyword) { + public PageResponse getMemberList(int page, int size, String keyword) { Pageable pageable = PageRequest.of(page, size, Sort.by("id").ascending()); Page pageResult; @@ -33,11 +34,9 @@ public Slice getMemberList(int page, int size, Strin pageResult = memberRepository.findAll(pageable); } - List content = pageResult.getContent().stream() - .map(this::toDto) - .toList(); + Page dtoPage = pageResult.map(this::toDto); - return new SliceImpl<>(content, pageable, pageResult.hasNext()); + return PageResponse.of(dtoPage); } private AdminMemberListResponseDTO toDto(Member m) { diff --git a/src/main/java/cc/backend/admin/photoAlbum/controller/AdminPhotoAlbumController.java b/src/main/java/cc/backend/admin/photoAlbum/controller/AdminPhotoAlbumController.java index 36fffd1a..68240039 100644 --- a/src/main/java/cc/backend/admin/photoAlbum/controller/AdminPhotoAlbumController.java +++ b/src/main/java/cc/backend/admin/photoAlbum/controller/AdminPhotoAlbumController.java @@ -3,6 +3,7 @@ import cc.backend.admin.photoAlbum.dto.AdminPhotoAlbumResponseDTO; import cc.backend.admin.photoAlbum.service.AdminPhotoAlbumService; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import cc.backend.board.entity.enums.BoardType; import cc.backend.member.entity.Member; @@ -32,7 +33,7 @@ public class AdminPhotoAlbumController { @GetMapping("") @Operation(summary = "관리자페이지 사진첩 전체 조회 API", description = "전체 사진첩 업로드 날짜 내림차순 정렬") - public ApiResponse> getAllPhotoAlbum( + public ApiResponse> getAllPhotoAlbum( @ParameterObject Pageable pageable){ return ApiResponse.onSuccess(adminPhotoAlbumService.getAllPhotoAlbum(pageable)); } @@ -51,10 +52,10 @@ public ApiResponse deletePhotoAlbum(@PathVariable Long photoAlbumId){ @GetMapping("/search") @Operation(summary = "관리자페이지 사진첩 검색 API", description = "사진첩 id, 공연 id, 공연제목, 사진첩 내용에 키워드를 포함하면 반환") - public ApiResponse> searchPhotoAlbum( + public ApiResponse> searchPhotoAlbum( @RequestParam String keyword, @ParameterObject Pageable pageable){ - return ApiResponse.onSuccess((adminPhotoAlbumService.searchPhotoAlbum(keyword, pageable))); + return ApiResponse.onSuccess(adminPhotoAlbumService.searchPhotoAlbum(keyword, pageable)); } diff --git a/src/main/java/cc/backend/admin/photoAlbum/service/AdminPhotoAlbumService.java b/src/main/java/cc/backend/admin/photoAlbum/service/AdminPhotoAlbumService.java index d3e973bd..1ee98ca6 100644 --- a/src/main/java/cc/backend/admin/photoAlbum/service/AdminPhotoAlbumService.java +++ b/src/main/java/cc/backend/admin/photoAlbum/service/AdminPhotoAlbumService.java @@ -1,6 +1,7 @@ package cc.backend.admin.photoAlbum.service; import cc.backend.admin.photoAlbum.dto.AdminPhotoAlbumResponseDTO; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; @@ -31,7 +32,7 @@ public class AdminPhotoAlbumService { private final ImageService imageService; @Transactional(readOnly = true) - public Page getAllPhotoAlbum(Pageable pageable) { + public PageResponse getAllPhotoAlbum(Pageable pageable) { Pageable sortedPageable = PageRequest.of( pageable.getPageNumber(), pageable.getPageSize(), @@ -39,13 +40,16 @@ public Page getAllPhotoAlbum(Pag Page photoAlbums = photoAlbumRepository.findAll(sortedPageable); - return photoAlbums.map(photoAlbum -> AdminPhotoAlbumResponseDTO.SimplePhotoAlbumDTO.builder() - .id(photoAlbum.getId()) - .amateurShowName(photoAlbum.getAmateurShow().getName()) - .uploaderId(photoAlbum.getAmateurShow().getMember().getId()) - .uploaderName(photoAlbum.getAmateurShow().getMember().getName()) - .updatedAt(photoAlbum.getUpdatedAt()) - .build()); + return PageResponse.of( + photoAlbums.map(photoAlbum -> AdminPhotoAlbumResponseDTO.SimplePhotoAlbumDTO.builder() + .id(photoAlbum.getId()) + .amateurShowName(photoAlbum.getAmateurShow().getName()) + .uploaderId(photoAlbum.getAmateurShow().getMember().getId()) + .uploaderName(photoAlbum.getAmateurShow().getMember().getName()) + .updatedAt(photoAlbum.getUpdatedAt()) + .build() + ) + ); } @Transactional(readOnly = true) @@ -92,21 +96,19 @@ public String deletePhotoAlbum(Long photoAlbumId) { } @Transactional(readOnly = true) - public Page searchPhotoAlbum(String keyword, Pageable pageable) { - if (keyword == null || keyword.trim().isEmpty()) { - return Page.empty(pageable); - } + public PageResponse searchPhotoAlbum(String keyword, Pageable pageable) { + String kw = (keyword == null) ? "" : keyword.trim(); - Page results = photoAlbumRepository.searchPhotoAlbumByKeyword(keyword, pageable); + Page results = photoAlbumRepository.searchPhotoAlbumByKeyword(kw, pageable); - return results.map(p -> - AdminPhotoAlbumResponseDTO.SimplePhotoAlbumDTO.builder() + return PageResponse.of( + results.map(p -> AdminPhotoAlbumResponseDTO.SimplePhotoAlbumDTO.builder() .id(p.getId()) .amateurShowName(p.getAmateurShow().getName()) .uploaderId(p.getAmateurShow().getMember().getId()) .uploaderName(p.getAmateurShow().getMember().getName()) .updatedAt(p.getUpdatedAt()) - .build() + .build()) ); } } diff --git a/src/main/java/cc/backend/admin/ticket/AdminTicketController.java b/src/main/java/cc/backend/admin/ticket/AdminTicketController.java index 26d34702..446e955b 100644 --- a/src/main/java/cc/backend/admin/ticket/AdminTicketController.java +++ b/src/main/java/cc/backend/admin/ticket/AdminTicketController.java @@ -5,13 +5,13 @@ import cc.backend.admin.ticket.dto.ReservationDetailResponseDTO; import cc.backend.admin.ticket.dto.TicketDetailResponseDTO; import cc.backend.apiPayLoad.ApiResponse; -import cc.backend.apiPayLoad.SliceResponse; -import com.google.protobuf.Api; + +import cc.backend.apiPayLoad.PageResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.*; -import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; @RestController @@ -24,7 +24,7 @@ public class AdminTicketController { @GetMapping("/history") @Operation(summary = "관리자 소극장 티켓 관리 - 표") - public ApiResponse> getTicketHistory( + public ApiResponse> getTicketHistory( @Parameter(description = "페이지 번호(0부터)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -34,8 +34,8 @@ public ApiResponse> getTicketHistory( @Parameter(description = "검색 키워드, 공연 명으로 검색", example = "실종") @RequestParam(required = false) String keyword ){ - Slice slice = adminTicketService.getTicketList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); } + return ApiResponse.onSuccess(adminTicketService.getTicketList(page, size, keyword)); + } @GetMapping("/{realTicketId}") @Operation(summary = "관리자 소극장 티켓 관리 상세조회") @@ -48,7 +48,7 @@ public ApiResponse getTicketDetail( @GetMapping("/reservation/history") @Operation(summary = "관리자 예약 내역 관리 - 표", description = "예매 내역을 리스트 형태로 조회합니다.") - public ApiResponse> getReservationHistory( + public ApiResponse> getReservationHistory( @Parameter(description = "페이지 번호(0부터)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -58,8 +58,8 @@ public ApiResponse> getReservationHi @Parameter(description = "검색 키워드, 공연 명으로 검색", example = "실종") @RequestParam(required = false) String keyword ) { - Slice slice = adminTicketService.getReservationList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); } + return ApiResponse.onSuccess(adminTicketService.getReservationList(page, size, keyword)); + } @GetMapping("/reservation/{realTicketId}") @Operation(summary = "관리자 예약 내역 관리 상세조회") @@ -72,7 +72,7 @@ public ApiResponse getReservationDetail( @GetMapping("/refund/history") @Operation(summary = "관리자 환불 내역 관리 - 표", description = "환불 내역을 리스트 형태로 조회합니다.") - public ApiResponse> getRefundHistory( + public ApiResponse> getRefundHistory( @Parameter(description = "페이지 번호(0부터)", example = "0") @RequestParam(defaultValue = "0") int page, @@ -82,8 +82,9 @@ public ApiResponse> getRefundHistory( @Parameter(description = "검색 키워드, 공연 명으로 검색", example = "실종") @RequestParam(required = false) String keyword ) { - Slice slice = adminTicketService.getRefundList(page, size, keyword); - return ApiResponse.onSuccess(SliceResponse.of(slice)); } + + return ApiResponse.onSuccess(adminTicketService.getRefundList(page, size, keyword)); + } @GetMapping("/refund/{realTicketId}") @Operation(summary = "관리자 환불 내역 관리 상세조회") diff --git a/src/main/java/cc/backend/admin/ticket/AdminTicketService.java b/src/main/java/cc/backend/admin/ticket/AdminTicketService.java index 5a4cefe1..c497be09 100644 --- a/src/main/java/cc/backend/admin/ticket/AdminTicketService.java +++ b/src/main/java/cc/backend/admin/ticket/AdminTicketService.java @@ -4,6 +4,7 @@ import cc.backend.admin.ticket.dto.RefundListResponseDTO; import cc.backend.admin.ticket.dto.ReservationDetailResponseDTO; import cc.backend.admin.ticket.dto.TicketDetailResponseDTO; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.ticket.entity.RealTicket; @@ -24,7 +25,7 @@ public class AdminTicketService { private final RealTicketRepository realTicketRepository; // == 소극장 티켓 관리 == // - public Slice getTicketList(int page, int size, String keyword) { + public PageResponse getTicketList(int page, int size, String keyword) { Sort sort = Sort.by( Sort.Order.desc("id") ); @@ -35,11 +36,9 @@ public Slice getTicketList(int page, int size, String k ? realTicketRepository.findByShowTitleContainingIgnoreCase(keyword, pageable) : realTicketRepository.findAll(pageable); - List content = result.getContent().stream() - .map(this::toTicketDTO) - .toList(); + Page dtoPage = result.map(this::toTicketDTO); - return new SliceImpl<>(content, pageable, result.hasNext()); + return PageResponse.of(dtoPage); } private TicketDetailResponseDTO toTicketDTO(RealTicket t) { @@ -64,7 +63,7 @@ public TicketDetailResponseDTO getTicketDetail(Long realTicketId) { } // == 예약 내역 관리 == // - public Slice getReservationList( + public PageResponse getReservationList( int page, int size, String keyword ) { Sort sort = Sort.by( @@ -78,11 +77,9 @@ public Slice getReservationList( ? realTicketRepository.findByShowTitleContainingIgnoreCase(keyword, pageable) : realTicketRepository.findAll(pageable); - List content = result.getContent().stream() - .map(this::toReservationDTO) - .toList(); + Page dtoPage = result.map(this::toReservationDTO); - return new SliceImpl<>(content, pageable, result.hasNext()); + return PageResponse.of(dtoPage); } private ReservationDetailResponseDTO toReservationDTO(RealTicket t) { @@ -114,7 +111,7 @@ public ReservationDetailResponseDTO getReservationDetail(Long realTicketId) { .build(); } - public Slice getRefundList(int page, int size, String keyword) { + public PageResponse getRefundList(int page, int size, String keyword) { Pageable pageable = PageRequest.of( page, size, @@ -128,15 +125,13 @@ public Slice getRefundList(int page, int size, String key ? realTicketRepository.findByReservationStatusAndShowTitleContainingIgnoreCase(refundStatus, keyword, pageable) : realTicketRepository.findByReservationStatus(refundStatus, pageable); - List content = result.getContent().stream() - .map(this::toRefundDTO) - .toList(); + Page dtoPage = result.map(this::toRefundDTO); - return new SliceImpl<>(content, pageable, result.hasNext()); + return PageResponse.of(dtoPage); } - private RefundListResponseDTO toRefundDTO(RealTicket t) { - return RefundListResponseDTO.builder() + private RefundListResponseDTO.RefundListDTO toRefundDTO(RealTicket t) { + return RefundListResponseDTO.RefundListDTO.builder() .realTicketId(t.getId()) .username(t.getMember() != null ? t.getMember().getUsername() : null) .memberName(t.getMember() != null ? t.getMember().getName() : null) diff --git a/src/main/java/cc/backend/admin/ticket/dto/RefundListResponseDTO.java b/src/main/java/cc/backend/admin/ticket/dto/RefundListResponseDTO.java index 2d6d3830..40d95753 100644 --- a/src/main/java/cc/backend/admin/ticket/dto/RefundListResponseDTO.java +++ b/src/main/java/cc/backend/admin/ticket/dto/RefundListResponseDTO.java @@ -6,17 +6,20 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.List; -@Builder -@AllArgsConstructor -@NoArgsConstructor -@Getter public class RefundListResponseDTO { - private Long realTicketId; - private String username; - private String memberName; - private String showTitle; - private LocalDateTime performanceDateTime; - private LocalDateTime canceledAt; + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + public static class RefundListDTO { + private Long realTicketId; + private String username; + private String memberName; + private String showTitle; + private LocalDateTime performanceDateTime; + private LocalDateTime canceledAt; + } } diff --git a/src/main/java/cc/backend/amateurShow/entity/AmateurShow.java b/src/main/java/cc/backend/amateurShow/entity/AmateurShow.java index 27736a79..c9cbe85a 100644 --- a/src/main/java/cc/backend/amateurShow/entity/AmateurShow.java +++ b/src/main/java/cc/backend/amateurShow/entity/AmateurShow.java @@ -103,15 +103,6 @@ public class AmateurShow extends BaseEntity { @Builder.Default private List amateurRounds = new ArrayList<>(); - @Builder - public AmateurShow(String name, String detailAddress, LocalDate start, LocalDate end, List photoAlbums) { - this.name = name; - this.detailAddress = detailAddress; - this.start = start; - this.end = end; - this.photoAlbums = photoAlbums; - } - public void updateInfo(AmateurUpdateRequestDTO dto) { if (dto.getName() != null) this.name = dto.getName(); //if (dto.getPlace() != null) this.place = dto.getPlace(); @@ -159,12 +150,11 @@ public void reviseShowInfo(String hashtag, String summary, String account, Strin public void approve(){ this.approvalStatus = ApprovalStatus.APPROVED; - this.status = AmateurShowStatus.YET; + this.status = AmateurShowStatus.YET; //이것도 나중에 수정 필요 (스케쥴러로 만들면 승인할때 따로 설정 필요 X) } public void reject(String rejectReason){ this.approvalStatus = ApprovalStatus.REJECTED; - this.status = AmateurShowStatus.REJECT; + this.status = AmateurShowStatus.REJECT; //이거 수정 필요 this.rejectReason = rejectReason; - } } diff --git a/src/main/java/cc/backend/amateurShow/entity/AmateurShowStatus.java b/src/main/java/cc/backend/amateurShow/entity/AmateurShowStatus.java index cb144bab..ee128d12 100644 --- a/src/main/java/cc/backend/amateurShow/entity/AmateurShowStatus.java +++ b/src/main/java/cc/backend/amateurShow/entity/AmateurShowStatus.java @@ -1,5 +1,5 @@ package cc.backend.amateurShow.entity; - +//스케쥴러로 날짜에 맞게 상태 알아서 바뀌도록 해야할 듯 public enum AmateurShowStatus { YET, // 지금 날짜가 공연 날짜 안에 없을 때 (아직 공연 예정) ONGOING, // 지금 날짜가 공연 날짜 안에 있을 때 (예매 진행 중) diff --git a/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java b/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java index 98f628ea..fc9570f3 100644 --- a/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java +++ b/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java @@ -40,17 +40,12 @@ where lower(s.name) like lower(concat('%', :kw, '%')) or lower(s.performerName) like lower(concat('%', :kw, '%')) order by s.createdAt desc """) - Slice findByNameOrPerformer( + Page findByNameOrPerformer( @Param("kw") String keyword, Pageable pageable ); - Slice findByMember_IdAndStatusInOrderByIdDesc( - Long memberId, - Collection statuses, - Pageable pageable - ); Slice findByMember_IdOrderByIdDesc(Long memberId, Pageable pageable); @@ -76,8 +71,6 @@ List findHotShows( @EntityGraph(attributePaths = {"amateurRounds", "amateurNotice"}, type = EntityGraph.EntityGraphType.FETCH) List findAllWithRounds(); - List findByStatusIn(Collection statuses); - @Modifying(clearAutomatically = true) @Query("UPDATE AmateurShow s SET s.status = :newStatus WHERE s.id IN :ids") void updateStatusByIds(@Param("ids") List ids, @Param("newStatus") AmateurShowStatus newStatus); diff --git a/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java b/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java index ce102a32..3760c762 100644 --- a/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java +++ b/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java @@ -8,6 +8,7 @@ import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.Path; import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.StringUtils; import java.time.LocalDate; @@ -94,4 +95,19 @@ public static Specification hasLastRoundOn(LocalDate today) { return cb.equal(subquery, today); }; } + + public static Specification nameOrPerformerContains(String kw) { + return (root, query, cb) -> { + if (!StringUtils.hasText(kw)) { + return null; // 조건 없음 (where 생략) + } + + String like = "%" + kw.toLowerCase() + "%"; + + return cb.or( + cb.like(cb.lower(root.get("name")), like), + cb.like(cb.lower(root.get("performerName")), like) + ); + }; + } } diff --git a/src/main/java/cc/backend/apiPayLoad/PageResponse.java b/src/main/java/cc/backend/apiPayLoad/PageResponse.java new file mode 100644 index 00000000..24b1ac71 --- /dev/null +++ b/src/main/java/cc/backend/apiPayLoad/PageResponse.java @@ -0,0 +1,24 @@ +package cc.backend.apiPayLoad; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Slice; + +import java.util.List; + +public record PageResponse( + List content, + int pageNumber, + int pageSize, + long totalElements, + int totalPages +) { + public static PageResponse of(Page page) { + return new PageResponse<>( + page.getContent(), + page.getNumber(), + page.getSize(), + page.getTotalElements(), // 전체 요소 수 + page.getTotalPages() // 전체 페이지 수 + ); + } +} \ No newline at end of file diff --git a/src/main/java/cc/backend/apiPayLoad/SliceResponse.java b/src/main/java/cc/backend/apiPayLoad/SliceResponse.java index 484d7705..9c4ef953 100644 --- a/src/main/java/cc/backend/apiPayLoad/SliceResponse.java +++ b/src/main/java/cc/backend/apiPayLoad/SliceResponse.java @@ -17,17 +17,8 @@ public class SliceResponse { @Schema(description = "데이터 리스트") private List content; - @Schema(description = "현재 페이지 번호 (0부터 시작)") - private int page; - @Schema(description = "페이지 크기") - private int size; - - @Schema(description = "첫 번째 페이지 여부") - private boolean first; - - @Schema(description = "마지막 페이지 여부") - private boolean last; + private int pageSize; @Schema(description = "다음 페이지 존재 여부") private boolean hasNext; @@ -35,10 +26,7 @@ public class SliceResponse { public static SliceResponse of(Slice slice) { return SliceResponse.builder() .content(slice.getContent()) - .page(slice.getNumber()) - .size(slice.getSize()) - .first(slice.isFirst()) - .last(slice.isLast()) + .pageSize(slice.getSize()) .hasNext(slice.hasNext()) .build(); } diff --git a/src/main/java/cc/backend/board/repository/BoardRepository.java b/src/main/java/cc/backend/board/repository/BoardRepository.java index 75c9720a..77a64cd1 100644 --- a/src/main/java/cc/backend/board/repository/BoardRepository.java +++ b/src/main/java/cc/backend/board/repository/BoardRepository.java @@ -2,6 +2,7 @@ import cc.backend.board.entity.Board; import cc.backend.board.entity.enums.BoardType; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -22,7 +23,7 @@ public interface BoardRepository extends JpaRepository { Optional findByIdIncludingDeleted(@Param("id") Long id); @Query(value = "SELECT * FROM board ORDER BY id DESC", nativeQuery = true) - Slice findAllBoardsIncludingDeleted(Pageable pageable); + Page findAllBoardsIncludingDeleted(Pageable pageable); //Full-context Search // 일반게시판: 제목 + 내용 @@ -76,7 +77,7 @@ Slice searchPromotionBoards( FROM Board b WHERE LOWER(b.title) LIKE LOWER(CONCAT('%', :keyword, '%')) """) - Slice searchBoardsIncludingDeletedByTitle(@Param("keyword") String keyword, Pageable pageable); + Page searchBoardsIncludingDeletedByTitle(@Param("keyword") String keyword, Pageable pageable); } diff --git a/src/main/java/cc/backend/search/SearchController.java b/src/main/java/cc/backend/search/SearchController.java index b63b0f25..76750bd9 100644 --- a/src/main/java/cc/backend/search/SearchController.java +++ b/src/main/java/cc/backend/search/SearchController.java @@ -1,6 +1,7 @@ package cc.backend.search; import cc.backend.apiPayLoad.ApiResponse; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.apiPayLoad.SliceResponse; import cc.backend.member.entity.Member; import cc.backend.search.dto.SearchShowResponseDTO; @@ -33,7 +34,7 @@ public class SearchController { summary = "소극장 공연 검색", description = "공연명, 공연진명을 대상으로 키워드 검색하는 기능." ) - public ApiResponse> searchShows( + public ApiResponse searchShows( @Parameter(description = "작성자 회원 ID", required = true) @AuthenticationPrincipal(expression = "member") Member member, @@ -46,11 +47,7 @@ public ApiResponse> searchShows( @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") int size ) { - Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending()); - Slice slice = - searchService.searchAmateurShows(keyword, pageable); - - return ApiResponse.onSuccess(SliceResponse.of(slice)); + return ApiResponse.onSuccess(searchService.searchAmateurShows(keyword, page, size)); } } diff --git a/src/main/java/cc/backend/search/SearchService.java b/src/main/java/cc/backend/search/SearchService.java index 9fc86840..1c9de0b2 100644 --- a/src/main/java/cc/backend/search/SearchService.java +++ b/src/main/java/cc/backend/search/SearchService.java @@ -2,13 +2,16 @@ import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.repository.AmateurShowRepository; +import cc.backend.amateurShow.repository.specification.AmateurShowSpecification; +import cc.backend.apiPayLoad.PageResponse; import cc.backend.search.dto.SearchShowResponseDTO; import io.micrometer.core.instrument.search.Search; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; +import org.springframework.data.domain.*; +import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import java.util.List; @@ -19,9 +22,29 @@ public class SearchService { private final AmateurShowRepository amateurShowRepository; - public Slice searchAmateurShows(String keyword, Pageable pageable) { - String kw = keyword == null ? "" : keyword.trim(); - Slice slice = amateurShowRepository.findByNameOrPerformer(kw, pageable); - return slice.map(SearchShowResponseDTO::from); + public SearchShowResponseDTO.SearchShowDTO.SearchShowResultDTO searchAmateurShows(String keyword, int page, int size) { + String kw = StringUtils.hasText(keyword) ? keyword.trim() : null; + + Pageable pageable = PageRequest.of( + page, + size, + Sort.by(Sort.Direction.DESC, "createdAt") + ); + + Specification spec = Specification + .where(AmateurShowSpecification.nameOrPerformerContains(kw)) + .and(AmateurShowSpecification.isApproved()); + + // Page로 조회 + Page pageResult = amateurShowRepository.findAll(spec, pageable); + + // DTO 변환 + Page dtoPage = pageResult.map(SearchShowResponseDTO.SearchShowDTO::from); + + // 결과 반환 + return SearchShowResponseDTO.SearchShowDTO.SearchShowResultDTO.builder() + .searchShowDTOs(dtoPage.getContent()) + .total(pageResult.getTotalElements()) // total count 포함 + .build(); } } diff --git a/src/main/java/cc/backend/search/dto/SearchShowResponseDTO.java b/src/main/java/cc/backend/search/dto/SearchShowResponseDTO.java index 0ee0ca26..ff80908b 100644 --- a/src/main/java/cc/backend/search/dto/SearchShowResponseDTO.java +++ b/src/main/java/cc/backend/search/dto/SearchShowResponseDTO.java @@ -9,54 +9,73 @@ import lombok.Getter; import lombok.NoArgsConstructor; -@Builder -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Schema(description = "검색 결과 - 소극장 공연 상세 응답 DTO") +import java.util.List; + public class SearchShowResponseDTO { - @Schema(description = "공연 ID", example = "1") - private Long showId; - - @Schema(description = "공연명", example = "실종") - private String title; - - @Schema(description = "공연진명", example = "홍길동") - private String performerName; - - @Schema(description = "공연장명", example = "문학관 대학로 3층 소극장") - private String hallName; - - @Schema(description = "일정 문자열", example = "2024.04.03(목) 19:00 ~ 2024.10.05(토) 14:00") - private String schedule; - - @Schema(description = "포스터 URL") - private String posterImageUrl; - - @Schema(description = "공연 상태", example = "판매중") - private String status; - - public static SearchShowResponseDTO from(AmateurShow s){ -// String statusLabel = switch (s.getStatus()) { -// case APPROVED_ONGOING -> "예매 진행 중"; -// case APPROVED_ENDED -> "공연 종료"; -// case APPROVED_YET -> "예정"; -// case WAITING_APPROVAL -> "승인 대기"; -// case REJECTED -> "반려"; -// }; - String statusLabel = s.getStatus().toString(); - - String schedule = AmateurConverter.mergeSchedule(s.getStart(), s.getEnd()); - return SearchShowResponseDTO.builder() - .showId(s.getId()) - .title(s.getName()) - .performerName(s.getPerformerName()) - .hallName(s.getHallName()) - .schedule(schedule) - .status(statusLabel) - .posterImageUrl(s.getPosterImageUrl()) - .build(); + + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + @Schema(description = "검색 결과 - 소극장 공연 상세 응답 DTO") + public static class SearchShowDTO{ + @Schema(description = "공연 ID", example = "1") + private Long showId; + + @Schema(description = "공연명", example = "실종") + private String title; + + @Schema(description = "공연진명", example = "홍길동") + private String performerName; + + @Schema(description = "공연장명", example = "문학관 대학로 3층 소극장") + private String hallName; + + @Schema(description = "일정 문자열", example = "2024.04.03(목) 19:00 ~ 2024.10.05(토) 14:00") + private String schedule; + + @Schema(description = "포스터 URL") + private String posterImageUrl; + + @Schema(description = "공연 상태", example = "판매중") + private String status; + + public static SearchShowDTO from(AmateurShow s){ + String statusLabel = + switch (s.getStatus()) { + case ONGOING -> "판매 중"; // 지금 날짜가 공연 날짜 안에 있을 때 (예매 진행 중) + case ENDED -> "공연 종료"; // 지금 날짜가 공연 날짜보다 지났을 때 (공연 종료됨) + case YET -> "공연 예정"; // 지금 날짜가 공연 날짜 안에 없을 때 (아직 공연 예정) + case REJECT -> "X"; + }; +// String statusLabel = s.getStatus().toString(); + String schedule = AmateurConverter.mergeSchedule(s.getStart(), s.getEnd()); + return SearchShowDTO.builder() + .showId(s.getId()) + .title(s.getName()) + .performerName(s.getPerformerName()) + .hallName(s.getHallName()) + .schedule(schedule) + .status(statusLabel) + .posterImageUrl(s.getPosterImageUrl()) + .build(); + } + + @Builder + @AllArgsConstructor + @NoArgsConstructor + @Getter + @Schema(description = "검색 결과") + public static class SearchShowResultDTO{ + private List searchShowDTOs; + private long total; + } + + } + + + }