Skip to content

Commit

Permalink
feat: 팔로워 조회 API 구현 (#86)
Browse files Browse the repository at this point in the history
* feat: 팔로워 목록 조회 API 구현 (#65)

* fix: size default값 변경 (#65)

* feat: 응답에 cursorId 포함 (#65)
  • Loading branch information
kdkdhoho authored Feb 8, 2024
1 parent 44d0072 commit c123e8c
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.listywave.user.application.dto;

import com.listywave.user.application.domain.User;
import java.util.Collections;
import java.util.List;
import lombok.Builder;

@Builder
public record FollowersResponse(
List<FollowerInfo> followers,
int totalCount,
Long cursorId,
boolean hasNext
) {

public static FollowersResponse of(List<User> users, int totalCount, boolean hasNext) {
return FollowersResponse.builder()
.followers(FollowerInfo.toList(users))
.totalCount(totalCount)
.cursorId(users.get(users.size() - 1).getId())
.hasNext(hasNext)
.build();
}

public static FollowersResponse empty() {
return FollowersResponse.builder()
.followers(Collections.emptyList())
.totalCount(0)
.hasNext(false)
.build();
}
}

@Builder
record FollowerInfo(
Long id,
String nickname,
String profileImageUrl
) {

public static List<FollowerInfo> toList(List<User> users) {
return users.stream()
.map(FollowerInfo::of)
.toList();
}

public static FollowerInfo of(User user) {
return FollowerInfo.builder()
.id(user.getId())
.nickname(user.getNickname())
.profileImageUrl(user.getProfileImageUrl())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.listywave.user.application.domain.User;
import com.listywave.user.application.dto.AllUserListsResponse;
import com.listywave.user.application.dto.AllUserResponse;
import com.listywave.user.application.dto.FollowersResponse;
import com.listywave.user.application.dto.FollowingsResponse;
import com.listywave.user.application.dto.RecommendUsersResponse;
import com.listywave.user.application.dto.UserInfoResponse;
Expand Down Expand Up @@ -103,7 +104,26 @@ public void unfollow(Long followingUserId, String accessToken) {

followRepository.deleteByFollowingUserAndFollowerUser(followingUser, followerUser);
}


public FollowersResponse getFollowers(Long userId, int size, int cursorId) {
User followingUser = userRepository.getById(userId);

List<Follow> follows = followRepository.findAllByFollowingUser(followingUser, size, cursorId);
List<User> followerUsers = follows.stream()
.map(Follow::getFollowerUser)
.toList();

if (followerUsers.isEmpty()) {
return FollowersResponse.empty();
}

int totalCount = followRepository.countByFollowingUser(followingUser);
if (followerUsers.size() > size) {
return FollowersResponse.of(followerUsers.subList(0, size), totalCount, true);
}
return FollowersResponse.of(followerUsers, totalCount, false);
}

@Transactional(readOnly = true)
public List<RecommendUsersResponse> getRecommendUsers() {
List<User> recommendUsers = userRepository.getRecommendUsers();
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/listywave/user/presentation/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.listywave.list.application.domain.CategoryType;
import com.listywave.user.application.dto.AllUserListsResponse;
import com.listywave.user.application.dto.AllUserResponse;
import com.listywave.user.application.dto.FollowersResponse;
import com.listywave.user.application.dto.FollowingsResponse;
import com.listywave.user.application.dto.RecommendUsersResponse;
import com.listywave.user.application.dto.UserInfoResponse;
Expand Down Expand Up @@ -59,6 +60,16 @@ ResponseEntity<FollowingsResponse> getFollowings(@PathVariable(name = "userId")
return ResponseEntity.ok(response);
}

@GetMapping("/users/{userId}/followers")
ResponseEntity<FollowersResponse> getFollowers(
@PathVariable(name = "userId") Long userId,
@RequestParam(name = "size", defaultValue = "20") int size,
@RequestParam(name = "cursorId", defaultValue = "0") int cursorId
) {
FollowersResponse response = userService.getFollowers(userId, size, cursorId);
return ResponseEntity.ok(response);
}

@PostMapping("/follow/{userId}")
ResponseEntity<Void> follow(
@PathVariable(value = "userId") Long followingUserId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import com.listywave.user.application.domain.Follow;
import com.listywave.user.application.domain.User;
import com.listywave.user.repository.follow.custom.CustomFollowRepository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FollowRepository extends JpaRepository<Follow, Long> {
public interface FollowRepository extends JpaRepository<Follow, Long>, CustomFollowRepository {

List<Follow> getAllByFollowerUser(User user);

void deleteByFollowingUserAndFollowerUser(User following, User follower);

int countByFollowingUser(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.listywave.user.repository.follow.custom;

import com.listywave.user.application.domain.Follow;
import com.listywave.user.application.domain.User;
import java.util.List;

public interface CustomFollowRepository {

List<Follow> findAllByFollowingUser(User user, int size, int cursorId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.listywave.user.repository.follow.custom.impl;

import static com.listywave.user.application.domain.QFollow.follow;

import com.listywave.user.application.domain.Follow;
import com.listywave.user.application.domain.User;
import com.listywave.user.repository.follow.custom.CustomFollowRepository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class CustomFollowRepositoryImpl implements CustomFollowRepository {

private final JPAQueryFactory queryFactory;

@Override
public List<Follow> findAllByFollowingUser(User followingUser, int size, int cursorId) {
return queryFactory.selectFrom(follow)
.where(
follow.followingUser.eq(followingUser),
follow.followingUser.id.gt(cursorId)
)
.orderBy(follow.createdDate.desc())
.limit(size + 1)
.fetch();
}
}

0 comments on commit c123e8c

Please sign in to comment.