Skip to content
Merged
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
Expand Up @@ -79,7 +79,18 @@ public ResponseEntity<ApiResponse<UserPlaceResponseDto>> unsave(

@Operation(
summary = "내 저장 목록 조회",
description = "현재 로그인 사용자의 저장 목록을 페이징으로 조회합니다.",
description = """
현재 로그인 사용자의 저장 목록을 페이징으로 조회합니다.

**검색 기능:**
- `keyword`: 장소명으로 검색 (부분 일치, 대소문자 무관)
- 검색어가 없으면 전체 목록 반환

**예시:**
- `/api/my/places?page=0&size=20` - 전체 목록 조회
- `/api/my/places?keyword=경복궁` - "경복궁" 포함 장소만 조회
- `/api/my/places?keyword=바다&page=0&size=10` - "바다" 검색 + 페이징
""",
security = @SecurityRequirement(name = "JWT TOKEN")
)
@ApiResponses({
Expand All @@ -90,9 +101,10 @@ public ResponseEntity<ApiResponse<UserPlaceResponseDto>> unsave(
public ResponseEntity<ApiResponse<UserPlacePageResponseDto>> mySaved(
@Parameter(hidden = true) @LoginUser User user,
@Parameter(description = "페이지 번호 (0부터 시작)") @RequestParam(value = "page", defaultValue = "0") int page,
@Parameter(description = "페이지 크기") @RequestParam(value = "size", defaultValue = "20") int size) {
@Parameter(description = "페이지 크기") @RequestParam(value = "size", defaultValue = "20") int size,
@Parameter(description = "장소명 검색어 (부분 일치)") @RequestParam(value = "keyword", required = false) String keyword) {

var result = userPlaceService.getMyPlaces(user.getUserId (), UserActionType.SAVE, page, size);
var result = userPlaceService.getMyPlaces(user.getUserId(), UserActionType.SAVE, page, size, keyword);
return ResponseEntity.ok(ApiResponse.ok(result));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,24 +161,34 @@ public long getActionCountByContentId(String contentId, UserActionType type) {
}

@Transactional(readOnly = true)
public UserPlacePageResponseDto getMyPlaces(Long userId, UserActionType type, int page, int size) {
public UserPlacePageResponseDto getMyPlaces(Long userId, UserActionType type, int page, int size, String keyword) {
userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

var pageable = org.springframework.data.domain.PageRequest.of(page, size);
var pageResult = userPlaceRepository.findByUser_UserIdAndType(userId, type, pageable);

var items = pageResult.getContent().stream().map(up -> {
var place = up.getPlace();
return UserPlaceItemDto.builder()
.cnctrLevel(place.getCnctrLevel())
.contentId(place.getContentId())
.placeName(place.getName())
.likeCount(place.getLikeCount())
.themeName(place.getTheme() != null ? place.getTheme().getName() : null)
.savedAt(up.getCreatedAt())
.build();
}).toList();
var items = pageResult.getContent().stream()
// 검색 필터링
.filter(up -> {
if (keyword == null || keyword.isBlank()) {
return true; // 검색어 없으면 모두 통과
}
String placeName = up.getPlace().getName();
return placeName != null && placeName.toLowerCase()
.contains(keyword.toLowerCase());
})
.map(up -> {
var place = up.getPlace();
return UserPlaceItemDto.builder()
.cnctrLevel(place.getCnctrLevel())
.contentId(place.getContentId())
.placeName(place.getName())
.likeCount(place.getLikeCount())
.themeName(place.getTheme() != null ? place.getTheme().getName() : null)
.savedAt(up.getCreatedAt())
.build();
}).toList();

return UserPlacePageResponseDto.of(
items,
Expand Down