Skip to content

Commit 41914a4

Browse files
authored
AIM-78-내가-좋아요-누른-챌린지-목록-조회 (#74)
* feat: 좋아요한 챌린지 목록 조회 쿼리 구현 * feat: 좋아요한 챌린지 목록 조회 서비스 구현 * feat: 좋아요한 챌린지 목록 조회 API 추가
1 parent 257717f commit 41914a4

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

src/main/java/targeter/aim/domain/challenge/controller/ChallengeReadController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,18 @@ public ChallengeDto.ChallengePageResponse getAllChallenges(
8585
) {
8686
return challengeService.getAllChallenges(request, userDetails, pageable);
8787
}
88+
89+
@GetMapping("/liked")
90+
@Operation(
91+
summary = "내가 좋아요 누른 챌린지 목록 조회",
92+
description = "로그인한 사용자가 좋아요를 누른 챌린지 목록을 정렬 조건과 검색 키워드에 따라 페이지네이션 조회합니다."
93+
)
94+
public ChallengeDto.ChallengePageResponse getLikedChallenges(
95+
@ModelAttribute @ParameterObject ChallengeDto.AllListSearchCondition request,
96+
@PageableDefault(size = 16) @ParameterObject Pageable pageable,
97+
@AuthenticationPrincipal UserDetails userDetails
98+
) {
99+
return challengeService.getLikedChallenges(request, userDetails, pageable);
100+
}
101+
88102
}

src/main/java/targeter/aim/domain/challenge/repository/ChallengeQueryRepository.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,4 +601,81 @@ public List<Challenge> findSimpleMyChallenges(Long userId, ChallengeMode mode) {
601601
.orderBy(challenge.startedAt.desc()) // 최신순 정렬
602602
.fetch(); // List로 반환
603603
}
604+
605+
public Page<ChallengeDto.ChallengeListResponse> paginateLiked(
606+
UserDetails userDetails,
607+
Pageable pageable,
608+
ChallengeDto.ChallengeSortType sortType
609+
) {
610+
return paginateLikedByKeyword(userDetails, pageable, sortType, null);
611+
}
612+
613+
public Page<ChallengeDto.ChallengeListResponse> paginateLikedByKeyword(
614+
UserDetails userDetails,
615+
Pageable pageable,
616+
ChallengeDto.ChallengeSortType sortType,
617+
String keyword
618+
) {
619+
JPAQuery<Tuple> query = buildLikedBaseQuery(userDetails, keyword);
620+
applySorting(query, sortType);
621+
622+
List<Tuple> tuples = query
623+
.offset(pageable.getOffset())
624+
.limit(pageable.getPageSize())
625+
.fetch();
626+
627+
Long total = buildCountLikedQuery(userDetails, keyword).fetchOne();
628+
629+
return new PageImpl<>(
630+
enrichDetails(tuples),
631+
pageable,
632+
total == null ? 0 : total
633+
);
634+
}
635+
636+
private JPAQuery<Tuple> buildLikedBaseQuery(
637+
UserDetails userDetails,
638+
String keyword
639+
) {
640+
JPAQuery<Tuple> query = queryFactory
641+
.select(
642+
challenge,
643+
Expressions.TRUE,
644+
JPAExpressions.select(challengeLiked.count())
645+
.from(challengeLiked)
646+
.where(challengeLiked.challenge.eq(challenge))
647+
)
648+
.from(challengeLiked)
649+
.join(challengeLiked.challenge, challenge)
650+
.where(challengeLiked.user.id.eq(userDetails.getUser().getId()))
651+
.leftJoin(challenge.host).fetchJoin()
652+
.leftJoin(challenge.host.tier).fetchJoin()
653+
.leftJoin(challenge.host.profileImage).fetchJoin();
654+
655+
BooleanExpression keywordPredicate = keywordCondition(keyword);
656+
if (keywordPredicate != null) {
657+
query.where(keywordPredicate);
658+
}
659+
660+
return query;
661+
}
662+
663+
private JPAQuery<Long> buildCountLikedQuery(
664+
UserDetails userDetails,
665+
String keyword
666+
) {
667+
JPAQuery<Long> query = queryFactory
668+
.select(challenge.count())
669+
.from(challengeLiked)
670+
.join(challengeLiked.challenge, challenge)
671+
.where(challengeLiked.user.id.eq(userDetails.getUser().getId()));
672+
673+
BooleanExpression keywordPredicate = keywordCondition(keyword);
674+
if (keywordPredicate != null) {
675+
query.where(keywordPredicate);
676+
}
677+
678+
return query;
679+
}
680+
604681
}

src/main/java/targeter/aim/domain/challenge/service/ChallengeReadService.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,4 +348,31 @@ public ChallengeDto.ChallengePageResponse getAllChallenges(
348348

349349
return ChallengeDto.ChallengePageResponse.from(page);
350350
}
351+
352+
public ChallengeDto.ChallengePageResponse getLikedChallenges(
353+
ChallengeDto.AllListSearchCondition condition,
354+
UserDetails userDetails,
355+
Pageable pageable
356+
) {
357+
if (userDetails == null) {
358+
return ChallengeDto.ChallengePageResponse.from(
359+
Page.empty(pageable)
360+
);
361+
}
362+
363+
ChallengeDto.ChallengeSortType sortType = condition.getSort();
364+
String keyword = normalizeKeyword(condition.getKeyword());
365+
366+
Page<ChallengeDto.ChallengeListResponse> page =
367+
keyword != null
368+
? challengeQueryRepository.paginateLikedByKeyword(
369+
userDetails, pageable, sortType, keyword
370+
)
371+
: challengeQueryRepository.paginateLiked(
372+
userDetails, pageable, sortType
373+
);
374+
375+
return ChallengeDto.ChallengePageResponse.from(page);
376+
}
377+
351378
}

0 commit comments

Comments
 (0)