diff --git a/src/main/java/org/sopt/app/application/playground/PlaygroundAuthService.java b/src/main/java/org/sopt/app/application/playground/PlaygroundAuthService.java index ce1ac8b5..57a124c8 100755 --- a/src/main/java/org/sopt/app/application/playground/PlaygroundAuthService.java +++ b/src/main/java/org/sopt/app/application/playground/PlaygroundAuthService.java @@ -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; @@ -161,6 +181,25 @@ public boolean isCurrentGeneration(Long generation) { return generation.equals(currentGeneration); } + public List getRecentPosts(String playgroundToken) { + final Map accessToken = createAuthorizationHeaderByUserPlaygroundToken(playgroundToken); + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + List categories = List.of(PlayGroundPostCategory.SOPT_ACTIVITY, PlayGroundPostCategory.FREE, PlayGroundPostCategory.PART); + CompletableFuture hotPostFuture = CompletableFuture.supplyAsync(() -> + RecentPostsResponse.of(playgroundClient.getPlaygroundHotPost(accessToken)), executor); + List> categoryFutures = categories.stream() + .map(category -> CompletableFuture.supplyAsync(() -> playgroundClient.getRecentPosts(accessToken, category.getDisplayName()), executor)) + .toList(); + List> allFutures = new ArrayList<>(categoryFutures); + allFutures.addFirst(hotPostFuture); + CompletableFuture allOf = CompletableFuture.allOf(allFutures.toArray(new CompletableFuture[0])); + return allOf.thenApply(v -> allFutures.stream() + .map(CompletableFuture::join) + .toList()) + .join(); + } + } + public List getPlaygroundEmploymentPost(String accessToken) { Map requestHeader = createAuthorizationHeaderByUserPlaygroundToken(accessToken); PlayGroundEmploymentResponse postInfo = playgroundClient.getPlaygroundEmploymentPost(requestHeader,16,10,0); @@ -168,5 +207,4 @@ public List getPlaygroundEmploymentPost(String accessTok .map(EmploymentPostResponse::of) .collect(Collectors.toList()); } - } diff --git a/src/main/java/org/sopt/app/application/playground/PlaygroundClient.java b/src/main/java/org/sopt/app/application/playground/PlaygroundClient.java index a9ae93de..66edf17c 100755 --- a/src/main/java/org/sopt/app/application/playground/PlaygroundClient.java +++ b/src/main/java/org/sopt/app/application/playground/PlaygroundClient.java @@ -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; @@ -53,6 +53,9 @@ PlaygroundUserIds getPlaygroundUserIdsByCondition(@HeaderMap Map @RequestLine("GET /api/v1/community/posts/hot") PlaygroundPostResponse getPlaygroundHotPost(@HeaderMap Map headers); + @RequestLine("GET /internal/api/v1/community/post/recent?category={category}") + RecentPostsResponse getRecentPosts(@HeaderMap Map headers, @Param("category") String category); + @RequestLine("GET /api/v1/community/posts?categoryId={categoryId}&limit={limit}&cursor={cursor}") PlayGroundEmploymentResponse getPlaygroundEmploymentPost(@HeaderMap Map headers, @Param int categoryId, diff --git a/src/main/java/org/sopt/app/application/playground/dto/PlayGroundPostCategory.java b/src/main/java/org/sopt/app/application/playground/dto/PlayGroundPostCategory.java new file mode 100644 index 00000000..e88a317c --- /dev/null +++ b/src/main/java/org/sopt/app/application/playground/dto/PlayGroundPostCategory.java @@ -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; + } +} + diff --git a/src/main/java/org/sopt/app/facade/HomeFacade.java b/src/main/java/org/sopt/app/facade/HomeFacade.java index 13734939..98e73310 100755 --- a/src/main/java/org/sopt/app/facade/HomeFacade.java +++ b/src/main/java/org/sopt/app/facade/HomeFacade.java @@ -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; @@ -69,6 +70,17 @@ private boolean isServiceVisibleToUser(AppServiceInfo appServiceInfo, User user) return false; } + public List 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 getHomeEmploymentPost(User user) { return playgroundAuthService.getPlaygroundEmploymentPost(user.getPlaygroundToken()); } diff --git a/src/main/java/org/sopt/app/presentation/home/HomeController.java b/src/main/java/org/sopt/app/presentation/home/HomeController.java index fd6e4ad2..21159809 100644 --- a/src/main/java/org/sopt/app/presentation/home/HomeController.java +++ b/src/main/java/org/sopt/app/presentation/home/HomeController.java @@ -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; @@ -54,7 +55,21 @@ public ResponseEntity> 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> getRecentPost( + @AuthenticationPrincipal User user + ) { + return ResponseEntity.ok( + homeFacade.getRecentPosts(user)); + } + @ApiResponses({ @ApiResponse(responseCode = "200", description = "success"), @ApiResponse(responseCode = "401", description = "token error", content = @Content), diff --git a/src/main/java/org/sopt/app/presentation/home/response/RecentPostsResponse.java b/src/main/java/org/sopt/app/presentation/home/response/RecentPostsResponse.java new file mode 100644 index 00000000..d6dbcf83 --- /dev/null +++ b/src/main/java/org/sopt/app/presentation/home/response/RecentPostsResponse.java @@ -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(); + } +} \ No newline at end of file