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 @@ -16,6 +16,7 @@
import stackpot.stackpot.feed.entity.enums.Category;
import stackpot.stackpot.feed.service.FeedQueryService;
import stackpot.stackpot.feed.service.FeedCommandService;
import stackpot.stackpot.user.dto.response.UserMyPageResponseDto;

import java.util.Map;

Expand Down Expand Up @@ -137,37 +138,7 @@ public ResponseEntity<ApiResponse<Map>> toggleLike(@PathVariable Long feedId) {
"message", isLiked ? "좋아요를 눌렀습니다." : "좋아요를 취소했습니다."
)));
}
@GetMapping("/{userId}")
@Operation(
summary = "사용자별 Feed 조회 API",
description = "사용자의 feed를 조회합니다."
)
public ResponseEntity<ApiResponse<FeedResponseDto.FeedPreviewList>> getFeedsByUserId(
@Parameter(description = "사용자 ID", example = "1")
@PathVariable("userId") Long userId,

@Parameter(description = "커서", example = "100", required = false)
@RequestParam(value = "cursor", required = false) Long cursor,

@Parameter(description = "페이지 크기", example = "10")
@RequestParam(value = "size", defaultValue = "10") int size
) {
FeedResponseDto.FeedPreviewList feedPreviewList = feedQueryService.getFeedsByUserId(userId, cursor, size);
return ResponseEntity.ok(ApiResponse.onSuccess(feedPreviewList));
}

@Operation(summary = "나의 Feed 조회 API")
@GetMapping("/my-feeds")
@ApiErrorCodeExamples({
ErrorStatus.USER_NOT_FOUND
})
public ResponseEntity<ApiResponse<FeedResponseDto.FeedPreviewList>> getFeeds(
@RequestParam(name = "cursor", required = false) Long cursor,
@RequestParam(name = "size", defaultValue = "10") int size) {

FeedResponseDto.FeedPreviewList feedPreviewList = feedQueryService.getFeeds(cursor, size);
return ResponseEntity.ok(ApiResponse.onSuccess(feedPreviewList));
}

@PostMapping("/series")
@Operation(summary = "시리즈 생성/삭제 동기화 API",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public FeedResponseDto.FeedDto feedDto(Feed feed, Boolean isOwner, Boolean isLik
return FeedResponseDto.FeedDto.builder()
.feedId(feed.getFeedId())
.writerId(feed.getUser().getId())
.writer(feed.getUser().getNickname() + " 씨앗")
.writer(feed.getUser().getNickname() + " 새싹")
.writerRole(feed.getUser().getRole())
.title(feed.getTitle())
.content(feed.getContent())
Expand Down Expand Up @@ -61,7 +61,7 @@ public FeedResponseDto.CreatedFeedDto createFeedDto(Feed feed) {
.title(feed.getTitle())
.content(feed.getContent())
.writerId(feed.getUser().getId())
.writer(feed.getUser().getNickname()+ " 씨앗")
.writer(feed.getUser().getNickname()+ " 새싹")
.writerRole(feed.getUser().getRole())
.categories(feed.getCategories().stream()
.map(Enum::name)
Expand Down Expand Up @@ -91,7 +91,7 @@ public FeedSearchResponseDto toSearchDto(Feed feed) {
.feedId(feed.getFeedId())
.title(feed.getTitle())
.content(feed.getContent())
.creatorNickname(feed.getUser().getNickname()+" 씨앗")
.creatorNickname(feed.getUser().getNickname()+" 새싹")
.creatorRole(mapRoleName(String.valueOf(feed.getUser().getRole())))
.createdAt(DateFormatter.koreanFormatter(feed.getCreatedAt()))
.likeCount(feed.getLikeCount()) // 좋아요 개수 포함
Expand All @@ -110,7 +110,7 @@ public FeedResponseDto.AuthorizedFeedDto toAuthorizedFeedDto(Feed feed, boolean
FeedResponseDto.CreatedFeedDto createdDto = FeedResponseDto.CreatedFeedDto.builder()
.feedId(feed.getFeedId())
.writerId(feed.getUser().getId())
.writer(feed.getUser().getNickname()+" 씨앗")
.writer(feed.getUser().getNickname()+" 새싹")
.writerRole(feed.getUser().getRole())
.title(feed.getTitle())
.content(feed.getContent())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

import stackpot.stackpot.feed.entity.Feed;
import stackpot.stackpot.feed.dto.FeedResponseDto;
import stackpot.stackpot.user.dto.response.UserMyPageResponseDto;

import java.util.Map;

public interface FeedQueryService {
FeedResponseDto.FeedPreviewList getPreViewFeeds(String category, String sort, Long cursor, int limit);
FeedResponseDto.AuthorizedFeedDto getFeed(Long feedId);
FeedResponseDto.FeedPreviewList getFeedsByUserId(Long userId, Long nextCursor, int pageSize);
UserMyPageResponseDto getFeedsByUserId(Long userId, Long nextCursor, int pageSize);
// FeedResponseDto.FeedPreviewList searchByUserIdByKeyword(Long userId, Long nextCursor, int pageSize);
FeedResponseDto.FeedPreviewList getFeeds(Long nextCursor, int pageSize);
UserMyPageResponseDto getFeeds(Long nextCursor, int pageSize);
Map<Long, String> getMySeries();
Long getLikeCount(Long feedId);
Feed getFeedByFeedId(Long feedId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import stackpot.stackpot.feed.repository.SeriesRepository;
import stackpot.stackpot.notification.service.NotificationCommandService;
import stackpot.stackpot.save.repository.FeedSaveRepository;
import stackpot.stackpot.user.dto.response.UserMyPageResponseDto;
import stackpot.stackpot.user.entity.User;
import stackpot.stackpot.user.repository.UserRepository;

Expand Down Expand Up @@ -179,7 +180,7 @@ public FeedResponseDto.AuthorizedFeedDto getFeed(Long feedId) {
}

@Transactional
public FeedResponseDto.FeedPreviewList getFeedsByUserId(Long userId, Long nextCursor, int pageSize) {
public UserMyPageResponseDto getFeedsByUserId(Long userId, Long nextCursor, int pageSize) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
boolean isAuthenticated = authentication != null
&& !(authentication instanceof AnonymousAuthenticationToken)
Expand All @@ -201,13 +202,9 @@ public FeedResponseDto.FeedPreviewList getFeedsByUserId(Long userId, Long nextCu
: List.of();

Pageable pageable = PageRequest.of(0, pageSize, Sort.by(Sort.Direction.DESC, "feedId"));
List<Feed> feeds;

if (nextCursor == null) {
feeds = feedRepository.findByUser_Id(userId, pageable);
} else {
feeds = feedRepository.findByUserIdAndFeedIdBefore(userId, nextCursor, pageable);
}
List<Feed> feeds = (nextCursor == null)
? feedRepository.findByUser_Id(userId, pageable)
: feedRepository.findByUserIdAndFeedIdBefore(userId, nextCursor, pageable);

List<FeedResponseDto.FeedDto> feedDtos = feeds.stream()
.map(feed -> {
Expand All @@ -220,18 +217,23 @@ public FeedResponseDto.FeedPreviewList getFeedsByUserId(Long userId, Long nextCu
})
.collect(Collectors.toList());

Long nextCursorResult = (!feeds.isEmpty() && feeds.size() >= pageSize)
? feeds.get(feeds.size() - 1).getFeedId()
: null;
// 조회 대상 유저 정보
User targetUser = userRepository.findById(userId)
.orElseThrow(() -> new UserHandler(ErrorStatus.USER_NOT_FOUND));

return FeedResponseDto.FeedPreviewList.builder()
List<String> seriesComments = targetUser.getSeriesList().stream()
.map(Series::getComment)
.collect(Collectors.toList());

return UserMyPageResponseDto.builder()
.id(targetUser.getId())
.seriesComments(seriesComments)
.feeds(feedDtos)
.nextCursor(nextCursorResult)
.build();
}

@Override
public FeedResponseDto.FeedPreviewList getFeeds(Long nextCursor, int pageSize) {
public UserMyPageResponseDto getFeeds(Long nextCursor, int pageSize) {
User user = authService.getCurrentUser();

Pageable pageable = PageRequest.of(0, pageSize, Sort.by(Sort.Direction.DESC, "feedId"));
Expand All @@ -253,13 +255,14 @@ public FeedResponseDto.FeedPreviewList getFeeds(Long nextCursor, int pageSize) {
})
.collect(Collectors.toList());

Long nextCursorResult = (!feeds.isEmpty() && feeds.size() >= pageSize)
? feeds.get(feeds.size() - 1).getFeedId()
: null;
List<String> seriesComments = user.getSeriesList().stream()
.map(Series::getComment)
.collect(Collectors.toList());

return FeedResponseDto.FeedPreviewList.builder()
return UserMyPageResponseDto.builder()
.id(user.getId())
.seriesComments(seriesComments)
.feeds(feedDtos)
.nextCursor(nextCursorResult)
.build();
}

Expand Down
20 changes: 11 additions & 9 deletions src/main/java/stackpot/stackpot/pot/controller/PotController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Tag(name = "Pot Management", description = "팟 관리 API")
@RestController
Expand Down Expand Up @@ -69,13 +70,12 @@ public ResponseEntity<ApiResponse<CursorPageResponse<CompletedPotResponseDto>>>
@Operation(
summary = "모든 팟 조회 API",
description = """
- Role: FRONTEND / BACKEND / DESIGN / PLANNING / (NULL)
만약 null인 경우 모든 role에 대해서 조회합니다.
- onlyMine: true인 경우 로그인한 사용자가 만든 팟 중 모집 중(RECRUITING)인 팟만 조회합니다.
false 또는 null인 경우 전체 팟 목록에서 조건에 맞는 팟을 조회합니다."""
- recruitmentRoles: 여러 역할(FRONTEND, BACKEND 등)을 리스트로 받습니다.
ex) /api/pots?recruitmentRoles=BACKEND&recruitmentRoles=FRONTEND
- onlyMine: true인 경우 로그인한 사용자가 만든 팟 중 모집 중(RECRUITING)인 팟만 조회합니다."""
)
public ResponseEntity<ApiResponse<Map<String, Object>>> getPots(
@RequestParam(required = false) String recruitmentRole,
@RequestParam(required = false) List<String> recruitmentRoles,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) Boolean onlyMine) {
Expand All @@ -84,12 +84,14 @@ public ResponseEntity<ApiResponse<Map<String, Object>>> getPots(
throw new EnumHandler(ErrorStatus.INVALID_PAGE);
}

Role roleEnum = null;
if (recruitmentRole != null && !recruitmentRole.isEmpty()) {
roleEnum = Role.valueOf(recruitmentRole.trim().toUpperCase());
List<Role> roleEnums = null;
if (recruitmentRoles != null && !recruitmentRoles.isEmpty()) {
roleEnums = recruitmentRoles.stream()
.map(role -> Role.valueOf(role.trim().toUpperCase()))
.collect(Collectors.toList());
}

Map<String, Object> response = potQueryService.getAllPotsWithPaging(roleEnum, page, size, onlyMine);
Map<String, Object> response = potQueryService.getAllPotsWithPaging(roleEnums, page, size, onlyMine);
return ResponseEntity.ok(ApiResponse.onSuccess(response));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public PotApplicationResponseDto toDto(PotApplication entity) {
.applicationId(entity.getApplicationId())
.potRole(roleInfo)
.userId(entity.getUser().getId())
.userNickname(entity.getUser().getNickname() + " 씨앗")
.userNickname(entity.getUser().getNickname() + " 새싹")
.build();

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public PotPreviewResponseDto toPrviewDto(User user, Pot pot, List<String> recrui
return PotPreviewResponseDto.builder()
.userId(user.getId())
.userRole(user.getRole().name())
.userNickname(user.getNickname() + " 씨앗")
.userNickname(user.getNickname() + " 새싹")
.potId(pot.getPotId())
.potName(pot.getPotName())
.potContent(pot.getPotContent())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public PotDetailResponseDto toPotDetailResponseDto(User user, Pot pot, String re
return PotDetailResponseDto.builder()
.userId(user.getId())
.userRole(user.getRole().name())
.userNickname(user.getNickname() + " 씨앗")
.userNickname(user.getNickname() + " 새싹")
.isOwner(isOwner)
.potId(pot.getPotId())
.potName(pot.getPotName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,16 @@ public interface PotRepository extends JpaRepository<Pot, Long> {
"ORDER BY COUNT(pa.applicationId) DESC, p.createdAt DESC")
Page<Pot> findAllOrderByApplicantsCountDesc(Pageable pageable);

/// 특정 Role을 기준으로 지원자 수 많은 순 정렬
/// 여러 Role을 기준으로 지원자 수 많은 순 정렬
@Query("SELECT p FROM Pot p " +
"LEFT JOIN PotRecruitmentDetails prd ON p = prd.pot " +
"LEFT JOIN PotApplication pa ON p = pa.pot " +
"WHERE prd.recruitmentRole = :recruitmentRole " +
"WHERE prd.recruitmentRole IN :roles " +
"GROUP BY p " +
"ORDER BY COUNT(pa.applicationId) DESC, p.createdAt DESC")
Page<Pot> findByRecruitmentRoleOrderByApplicantsCountDesc(@Param("recruitmentRole") Role recruitmentRole, Pageable pageable);
Page<Pot> findByRecruitmentRolesInOrderByApplicantsCountDesc(@Param("roles") List<Role> roles, Pageable pageable);

List<Pot> findByPotMembers_UserIdOrderByCreatedAtDesc(Long userId);


}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public interface PotQueryService {
List<AppliedPotResponseDto> getAppliedPots();
PotSummaryResponseDTO getPotSummary(Long potId);
CursorPageResponse<CompletedPotResponseDto> getUserCompletedPots(Long userId, Long cursor, int size);
Map<String, Object> getAllPotsWithPaging(Role role, int page, int size, Boolean onlyMine);
Map<String, Object> getAllPotsWithPaging(List<Role> roles, int page, int size, Boolean onlyMine);
Map<String, Object> getMyRecruitingPotsWithPaging(Integer page, Integer size);
Pot getPotByPotId(Long potId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public CursorPageResponse<CompletedPotResponseDto> getUserCompletedPots(Long use
}

@Override
public Map<String, Object> getAllPotsWithPaging(Role role, int page, int size, Boolean onlyMine) {
public Map<String, Object> getAllPotsWithPaging(List<Role> roles, int page, int size, Boolean onlyMine) {
User user = null;

// 로그인 여부와 무관하게 인증된 사용자인 경우 user 정보 가져오기
Expand All @@ -265,9 +265,11 @@ public Map<String, Object> getAllPotsWithPaging(Role role, int page, int size, B
if (onlyMine != null && onlyMine && user != null) {
potPage = potRepository.findByUserIdAndPotStatus(user.getId(), "RECRUITING", pageable);
} else {
potPage = (role == null)
? potRepository.findAllOrderByApplicantsCountDesc(pageable)
: potRepository.findByRecruitmentRoleOrderByApplicantsCountDesc(role, pageable);
if (roles == null || roles.isEmpty()) {
potPage = potRepository.findAllOrderByApplicantsCountDesc(pageable);
} else {
potPage = potRepository.findByRecruitmentRolesInOrderByApplicantsCountDesc(roles, pageable);
}
}

List<Pot> pots = potPage.getContent();
Expand All @@ -285,19 +287,18 @@ public Map<String, Object> getAllPotsWithPaging(Role role, int page, int size, B
? potMemberRepository.findPotIdsByUserIdAndPotIds(user.getId(), potIds)
: Collections.emptySet();


List<PotPreviewResponseDto> content = pots.stream()
.map(pot -> {
Long potId = pot.getPotId();
List<String> roles = pot.getRecruitmentDetails().stream()
List<String> potRoles = pot.getRecruitmentDetails().stream()
.map(rd -> String.valueOf(rd.getRecruitmentRole()))
.collect(Collectors.toList());

boolean isSaved = savedPotIds.contains(potId);
int saveCount = potSaveCountMap.getOrDefault(potId, 0);
boolean isMember = memberPotIds.contains(potId);

return potConverter.toPrviewDto(pot.getUser(), pot, roles, isSaved, saveCount, isMember);
return potConverter.toPrviewDto(pot.getUser(), pot, potRoles, isSaved, saveCount, isMember);
})
.collect(Collectors.toList());

Expand All @@ -310,7 +311,6 @@ public Map<String, Object> getAllPotsWithPaging(Role role, int page, int size, B

return response;
}

@Override
public Pot getPotByPotId(Long potId) {
return potRepository.findById(potId).orElseThrow(() -> new PotHandler(ErrorStatus.POT_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import stackpot.stackpot.feed.entity.mapping.FeedSave;
import stackpot.stackpot.user.entity.User;

import java.util.List;
import java.util.Optional;
import java.util.*;

@Repository
public interface FeedSaveRepository extends JpaRepository<FeedSave, Long> {
Expand All @@ -30,6 +29,23 @@ public interface FeedSaveRepository extends JpaRepository<FeedSave, Long> {

@Query("SELECT COUNT(fs) FROM FeedSave fs WHERE fs.feed.feedId = :feedId")
long countByFeedId(@Param("feedId") Long feedId);
@Query("""
SELECT fs.feed.feedId, COUNT(fs)
FROM FeedSave fs
WHERE fs.feed.feedId IN :feedIds
GROUP BY fs.feed.feedId
""")
List<Object[]> countByFeedIdsRaw(@Param("feedIds") List<Long> feedIds);

default Map<Long, Long> countByFeedIds(List<Long> feedIds) {
if (feedIds == null || feedIds.isEmpty()) return Collections.emptyMap();
Map<Long, Long> map = new HashMap<>();
for (Object[] row : countByFeedIdsRaw(feedIds)) {
map.put((Long) row[0], (Long) row[1]);
}
return map;
}


}

Loading