Skip to content

Commit

Permalink
[FEAT] 커뮤니티 게시글 전체 조회 및 상세조회(인터페이스 우선배포) (#254)
Browse files Browse the repository at this point in the history
* feat: dao 클래스

* delete: 안쓰는 파일들 삭제

* feat: post response

* feat: repository 추가

* chore: comment service 객체

* feat: controller 클래스

* feat: comment response

* feat: service 객체 추가

* feat: CategoryDto

* feat: CategoryHelper

* feat: exception 객체

* feat: mapper 객체

* feat: unversion file

* chore: query dao
  • Loading branch information
yujindonut authored Oct 29, 2023
1 parent d522f44 commit 913ba52
Show file tree
Hide file tree
Showing 24 changed files with 795 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.sopt.makers.internal.domain.InternalMemberDetails;
import org.sopt.makers.internal.dto.community.CommentListResponse;
import org.sopt.makers.internal.dto.community.CommentSaveRequest;
import org.sopt.makers.internal.dto.community.*;
import org.sopt.makers.internal.mapper.CommunityResponseMapper;
import org.sopt.makers.internal.service.CommunityCategoryService;
import org.sopt.makers.internal.service.CommunityCommentService;
import org.sopt.makers.internal.service.CommuntiyPostService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -18,14 +20,58 @@
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/community")
@SecurityRequirement(name = "Authorization")
@Tag(name = "Community 관련 API", description = "Community 관련 API List")
public class CommunityController {

private final CommuntiyPostService communtiyPostService;
private final CommunityCategoryService communityCategoryService;
private final CommunityCommentService communityCommentService;
private final CommunityResponseMapper communityResponseMapper;

@Operation(summary = "커뮤니티 전체 카테고리 조회")
@GetMapping("/category")
public ResponseEntity<List<CategoryDto>> getCategoryList() {
val response = communityCategoryService.getAllCategory();
return ResponseEntity.status(HttpStatus.OK).body(response);
}

@Operation(summary = "커뮤니티 글 상세 조회")
@GetMapping("/posts/{postId}")
public ResponseEntity<CategoryPostMemberDao> getCategoryList(@PathVariable("postId") Long postId) {
val response = communtiyPostService.getPostById(postId);
return ResponseEntity.status(HttpStatus.OK).body(response);
}

@Operation(
summary = "커뮤니티 글 전체 조회",
description =
"""
categoryId: 카테고리 전체조회시 id값, 전체일 경우 null\n
cursor: 처음 조회시 null, 이외에 마지막 글 id
"""
)
@GetMapping("/posts")
public ResponseEntity<PostAllResponse> getAllPosts (
@RequestParam(required = false, name = "categoryId") Long categoryId,
@RequestParam(required = false, name = "limit") Integer limit,
@RequestParam(required = false, name = "cursor") Long cursor
) {
val posts = communtiyPostService.getAllPosts(categoryId, limit, cursor);
val hasNextPosts = (limit != null && posts.size() > limit);
if (hasNextPosts) posts.remove(posts.size() - 1);
val postResponse = posts.stream().map(post -> {
val comments = communityCommentService.getCommentLists(post.id());
return communityResponseMapper.toPostResponse(post, comments);
}).collect(Collectors.toList());
val response = new PostAllResponse(categoryId, hasNextPosts, postResponse);
return ResponseEntity.status(HttpStatus.OK).body(response);
}

@Operation(summary = "커뮤니티 댓글 생성 API")
@PostMapping("/{postId}/comment")
Expand All @@ -36,7 +82,6 @@ public ResponseEntity<Map<String, Boolean>> createComment(
) {
val writerId = memberDetails.getId();
communityCommentService.createComment(writerId, postId, request);

return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("success", true));
}

Expand All @@ -54,7 +99,6 @@ public ResponseEntity<Map<String, Boolean>> deleteComment(
) {
val writerId = memberDetails.getId();
communityCommentService.deleteComment(commentId, writerId);

return ResponseEntity.status(HttpStatus.OK).body(Map.of("success", true));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.sopt.makers.internal.dto.community;

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

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.sopt.makers.internal.domain.community.Category;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CategoryDto {

private Long id;
private String name;
private List<CategoryDto> children;

public static List<CategoryDto> toDtoList(List<Category> categories) {
CategoryHelper helper = CategoryHelper.newInstance(
categories,
c -> new CategoryDto(c.getId(), c.getName(), new ArrayList<>()),
Category::getParent,
Category::getId,
CategoryDto::getChildren);
return helper.convert();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.sopt.makers.internal.dto.community;

import org.sopt.makers.internal.exception.CannotConvertHelperException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class CategoryHelper<K, E, D> {

private List<E> entities;
private Function<E, D> toDto;
private Function<E, E> getParent;
private Function<E, K> getKey;
private Function<D, List<D>> getChildren;

public static <K, E, D> CategoryHelper newInstance(List<E> entities, Function<E, D> toDto, Function<E, E> getParent,
Function<E, K> getKey, Function<D, List<D>> getChildren) {
return new CategoryHelper<K, E, D>(entities, toDto, getParent, getKey, getChildren);
}

private CategoryHelper(List<E> entities, Function<E, D> toDto, Function<E, E> getParent, Function<E, K> getKey,
Function<D, List<D>> getChildren) {
this.entities = entities;
this.toDto = toDto;
this.getParent = getParent;
this.getKey = getKey;
this.getChildren = getChildren;
}

public List<D> convert() {
try {
return convertInternal();
} catch (NullPointerException e) {
throw new CannotConvertHelperException(e.getMessage());
}
}

private List<D> convertInternal() {
Map<K, D> map = new HashMap<>();
List<D> roots = new ArrayList<>();

for (E e : entities) {
D dto = toDto(e);
map.put(getKey(e), dto);
if (hasParent(e)) {
E parent = getParent(e);
K parentKey = getKey(parent);
D parentDto = map.get(parentKey);
getChildren(parentDto).add(dto);
} else {
roots.add(dto);
}
}
return roots;
}

private boolean hasParent(E e) {
return getParent(e) != null;
}

private E getParent(E e) {
return getParent.apply(e);
}

private D toDto(E e) {
return toDto.apply(e);
}

private K getKey(E e) {
return getKey.apply(e);
}

private List<D> getChildren(D d) {
return getChildren.apply(d);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.sopt.makers.internal.dto.community;

import com.querydsl.core.annotations.QueryProjection;
import org.sopt.makers.internal.domain.MemberCareer;
import org.sopt.makers.internal.domain.MemberSoptActivity;

import java.time.LocalDateTime;
import java.util.List;

public record CategoryPostMemberDao(
Long id,
Long categoryId,
Long userId,
String userName,
String profileImage,
List<MemberSoptActivity> activities,
List<MemberCareer> careers,
String title,
String content,
Integer hits,
Boolean isQuestion,
Boolean isBlindWriter,
String[] images,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
@QueryProjection
public CategoryPostMemberDao {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.sopt.makers.internal.dto.community;

import com.querydsl.core.annotations.QueryProjection;
import org.sopt.makers.internal.domain.MemberCareer;
import org.sopt.makers.internal.domain.MemberSoptActivity;

import java.time.LocalDateTime;
import java.util.List;

public record CommentDao(
Long id,
Long userId,
String userName,
String profileImage,
List<MemberSoptActivity> activities,
List<MemberCareer> careers,
String content,
Boolean isBlindWriter,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
@QueryProjection
public CommentDao {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sopt.makers.internal.dto.community;

import org.sopt.makers.internal.domain.MemberCareer;
import org.sopt.makers.internal.domain.MemberSoptActivity;

import java.time.LocalDateTime;
import java.util.List;

public record CommentResponse(
Long id,
Long userId,
String userName,
String profileImage,
List<MemberSoptActivity> activities,
List<MemberCareer> careers,
String content,
Boolean isBlindWriter,
LocalDateTime createdAt,
LocalDateTime updatedAt
){}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.sopt.makers.internal.dto.community;

public class CommunityCommentDao {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.sopt.makers.internal.dto.community;

import io.swagger.v3.oas.annotations.media.Schema;

import java.time.LocalDate;
import java.util.List;

public record CommunityMemberProfileResponse(
@Schema(required = true)
Long id,
@Schema(required = true)
String name,
String profileImage,
@Schema(required = true)
List<MemberSoptActivityResponse> activities,
List<MemberLinkResponse> links,
List<MemberCareerResponse> careers,
Boolean allowOfficial
) {

public record UserFavorResponse(
Boolean isPourSauceLover,
Boolean isHardPeachLover,
Boolean isMintChocoLover,
Boolean isRedBeanFishBreadLover,
Boolean isSojuLover,
Boolean isRiceTteokLover
){}

public record MemberLinkResponse(
Long id,
String title,
String url
){}

public record MemberSoptActivityResponse(
Long id,
Integer generation,
String part,
String team
){}

public record MemberCareerResponse(
Long id,
String companyName,
String title,
String startDate,
String endDate,
Boolean isCurrent
){}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.makers.internal.dto.community;

import io.swagger.v3.oas.annotations.media.Schema;
import org.sopt.makers.internal.domain.MemberCareer;
import org.sopt.makers.internal.domain.MemberSoptActivity;

import java.util.List;

public record CommunityMemberResponse(
Long id,
String name,
String image,
@Schema(required = true)
List<MemberSoptActivity> activities,
List<MemberCareer> careers
){}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.makers.internal.dto.community;

import java.util.List;

public record PostAllResponse(
Long categoryId,
Boolean hasNext,
List<PostResponse> posts
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.sopt.makers.internal.dto.community;

import io.swagger.v3.oas.annotations.media.Schema;
import org.sopt.makers.internal.dto.member.MemberProfileResponse;

import java.time.LocalDateTime;
import java.util.List;

public record PostResponse(
@Schema(required = true)
Long id,
CommunityMemberResponse member,
Long writerId,
String title,
String content,
Integer hits,
String[] images,
Boolean isQuestion,
Boolean isBlindWriter,
LocalDateTime createdAt,
List<CommentResponse> comments
) {}
Loading

0 comments on commit 913ba52

Please sign in to comment.