Skip to content

Commit

Permalink
[MERGE] 카테고리별 최신 게시물 조회 API 구현 - #434 (#447)
Browse files Browse the repository at this point in the history
  • Loading branch information
rlarlgnszx authored Nov 15, 2024
2 parents 94672ab + 95a6369 commit f4130fb
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
package org.sopt.app.application.playground;

import static org.sopt.app.application.playground.PlaygroundHeaderCreator.*;
import static org.sopt.app.application.playground.PlaygroundHeaderCreator.createAuthorizationHeaderByUserPlaygroundToken;
import static org.sopt.app.application.playground.PlaygroundHeaderCreator.createDefaultHeader;

import lombok.*;
import io.jsonwebtoken.ExpiredJwtException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import org.sopt.app.application.playground.dto.PlayGroundEmploymentResponse;
import org.sopt.app.application.playground.dto.PlaygroundPostInfo.*;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.*;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.sopt.app.application.auth.dto.PlaygroundAuthTokenInfo.RefreshedToken;
import org.sopt.app.common.exception.*;
import org.sopt.app.application.playground.dto.PlayGroundEmploymentResponse;
import org.sopt.app.application.playground.dto.PlayGroundPostCategory;
import org.sopt.app.application.playground.dto.PlaygroundPostInfo.PlaygroundPost;
import org.sopt.app.application.playground.dto.PlaygroundPostInfo.PlaygroundPostResponse;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.ActiveUserIds;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.ActivityCardinalInfo;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.MainView;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.MainViewUser;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.OwnPlaygroundProfile;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.PlaygroundMain;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.PlaygroundProfile;
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.UserActiveInfo;
import org.sopt.app.common.exception.BadRequestException;
import org.sopt.app.common.exception.UnauthorizedException;
import org.sopt.app.common.response.ErrorCode;
import org.sopt.app.domain.enums.UserStatus;
import org.sopt.app.presentation.auth.AppAuthRequest.*;
import org.sopt.app.presentation.auth.AppAuthRequest.AccessTokenRequest;
import org.sopt.app.presentation.auth.AppAuthRequest.CodeRequest;
import org.sopt.app.presentation.home.response.EmploymentPostResponse;
import org.sopt.app.presentation.home.response.RecentPostsResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException.BadRequest;
Expand Down Expand Up @@ -161,12 +181,30 @@ public boolean isCurrentGeneration(Long generation) {
return generation.equals(currentGeneration);
}

public List<RecentPostsResponse> getRecentPosts(String playgroundToken) {
final Map<String, String> accessToken = createAuthorizationHeaderByUserPlaygroundToken(playgroundToken);
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
List<PlayGroundPostCategory> categories = List.of(PlayGroundPostCategory.SOPT_ACTIVITY, PlayGroundPostCategory.FREE, PlayGroundPostCategory.PART);
CompletableFuture<RecentPostsResponse> hotPostFuture = CompletableFuture.supplyAsync(() ->
RecentPostsResponse.of(playgroundClient.getPlaygroundHotPost(accessToken)), executor);
List<CompletableFuture<RecentPostsResponse>> categoryFutures = categories.stream()
.map(category -> CompletableFuture.supplyAsync(() -> playgroundClient.getRecentPosts(accessToken, category.getDisplayName()), executor))
.toList();
List<CompletableFuture<RecentPostsResponse>> allFutures = new ArrayList<>(categoryFutures);
allFutures.addFirst(hotPostFuture);
CompletableFuture<Void> allOf = CompletableFuture.allOf(allFutures.toArray(new CompletableFuture[0]));
return allOf.thenApply(v -> allFutures.stream()
.map(CompletableFuture::join)
.toList())
.join();
}
}

public List<EmploymentPostResponse> getPlaygroundEmploymentPost(String accessToken) {
Map<String, String> requestHeader = createAuthorizationHeaderByUserPlaygroundToken(accessToken);
PlayGroundEmploymentResponse postInfo = playgroundClient.getPlaygroundEmploymentPost(requestHeader,16,10,0);
return postInfo.posts().stream()
.map(EmploymentPostResponse::of)
.collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import org.sopt.app.application.playground.dto.PlaygroundProfileInfo.PlaygroundProfile;
import org.sopt.app.application.playground.dto.PlaygroundUserFindCondition;
import org.sopt.app.application.playground.dto.RecommendedFriendInfo.PlaygroundUserIds;
import org.sopt.app.presentation.auth.AppAuthRequest.AccessTokenRequest;
import org.sopt.app.presentation.auth.AppAuthRequest.CodeRequest;
import org.sopt.app.presentation.auth.AppAuthRequest.*;
import org.sopt.app.presentation.home.response.RecentPostsResponse;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.RequestBody;

Expand Down Expand Up @@ -53,6 +53,9 @@ PlaygroundUserIds getPlaygroundUserIdsByCondition(@HeaderMap Map<String, String>
@RequestLine("GET /api/v1/community/posts/hot")
PlaygroundPostResponse getPlaygroundHotPost(@HeaderMap Map<String, String> headers);

@RequestLine("GET /internal/api/v1/community/post/recent?category={category}")
RecentPostsResponse getRecentPosts(@HeaderMap Map<String, String> headers, @Param("category") String category);

@RequestLine("GET /api/v1/community/posts?categoryId={categoryId}&limit={limit}&cursor={cursor}")
PlayGroundEmploymentResponse getPlaygroundEmploymentPost(@HeaderMap Map<String, String> headers,
@Param int categoryId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.app.application.playground.dto;

public enum PlayGroundPostCategory {
SOPT_ACTIVITY("SOPT 활동"),
FREE("자유"),
PART("파트");
private final String displayName;

PlayGroundPostCategory(String displayName) {
this.displayName = displayName;
}

public String getDisplayName() {
return displayName;
}
}

12 changes: 12 additions & 0 deletions src/main/java/org/sopt/app/facade/HomeFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.sopt.app.domain.entity.User;
import org.sopt.app.domain.enums.UserStatus;
import org.sopt.app.presentation.home.HomeDescriptionResponse;
import org.sopt.app.presentation.home.response.RecentPostsResponse;
import org.sopt.app.presentation.home.response.EmploymentPostResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -69,6 +70,17 @@ private boolean isServiceVisibleToUser(AppServiceInfo appServiceInfo, User user)
return false;
}

public List<RecentPostsResponse> getRecentPosts(User user) {
return playgroundAuthService.getRecentPosts(user.getPlaygroundToken()).stream()
.map(post -> RecentPostsResponse.builder()
.id(post.getId())
.title(post.getTitle())
.category(post.getCategory())
.isHotPost(post.isHotPost())
.build()
).toList();
}

public List<EmploymentPostResponse> getHomeEmploymentPost(User user) {
return playgroundAuthService.getPlaygroundEmploymentPost(user.getPlaygroundToken());
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/sopt/app/presentation/home/HomeController.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.sopt.app.application.meeting.MeetingResponse;
import org.sopt.app.domain.entity.User;
import org.sopt.app.facade.HomeFacade;
import org.sopt.app.presentation.home.response.RecentPostsResponse;
import org.sopt.app.presentation.home.response.EmploymentPostResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand Down Expand Up @@ -54,7 +55,21 @@ public ResponseEntity<List<AppServiceEntryStatusResponse>> getAppService(
);
}


@Operation(summary = "최근 채용탭 10개 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "success"),
@ApiResponse(responseCode = "401", description = "token error", content = @Content),
@ApiResponse(responseCode = "500", description = "server error", content = @Content)
})
@GetMapping("/posts")
public ResponseEntity<List<RecentPostsResponse>> getRecentPost(
@AuthenticationPrincipal User user
) {
return ResponseEntity.ok(
homeFacade.getRecentPosts(user));
}

@ApiResponses({
@ApiResponse(responseCode = "200", description = "success"),
@ApiResponse(responseCode = "401", description = "token error", content = @Content),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.sopt.app.presentation.home.response;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.sopt.app.application.playground.dto.PlaygroundPostInfo.PlaygroundPostResponse;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RecentPostsResponse {
private Long id;
private String title;
private String category;
private String content;
private boolean isHotPost;

public static RecentPostsResponse of(PlaygroundPostResponse playgroundPostResponse) {
return RecentPostsResponse.builder()
.id(playgroundPostResponse.postId())
.title(playgroundPostResponse.title())
.category("HOT")
.content(playgroundPostResponse.content())
.isHotPost(true)
.build();
}
}

0 comments on commit f4130fb

Please sign in to comment.