Skip to content

Commit b17ffa2

Browse files
authored
Merge pull request #137 from prgrms-web-devcourse-final-project/feature/EA3-138-recruitment-post-implement
[EA3-138] Feature: 모집글 조회 반환값 추가 및 정리
2 parents bb52bd2 + f86ec7d commit b17ffa2

File tree

18 files changed

+227
-109
lines changed

18 files changed

+227
-109
lines changed

src/main/java/grep/neogul_coder/domain/main/controller/MainController.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import grep.neogul_coder.domain.main.controller.dto.response.MainResponse;
44
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostPagingInfo;
55
import grep.neogul_coder.domain.recruitment.post.service.RecruitmentPostService;
6-
import grep.neogul_coder.domain.study.controller.StudySpecification;
76
import grep.neogul_coder.domain.study.controller.dto.response.StudyItemResponse;
87
import grep.neogul_coder.domain.study.service.StudyService;
98
import grep.neogul_coder.global.auth.Principal;
@@ -28,11 +27,11 @@ public class MainController implements MainSpecification {
2827

2928
@GetMapping
3029
public ApiResponse<MainResponse> getMain(@PageableDefault(size = 10) Pageable pageable,
31-
@AuthenticationPrincipal Principal userDetails) {
30+
@AuthenticationPrincipal Principal userDetails) {
3231
Long userId = userDetails.getUserId();
3332

3433
List<StudyItemResponse> myStudies = studyService.getMyStudies(userId);
35-
RecruitmentPostPagingInfo recruitingStudies = recruitmentPostService.getPagingInfo(pageable);
34+
RecruitmentPostPagingInfo recruitingStudies = recruitmentPostService.getPagingInfo(pageable, null);
3635
MainResponse response = MainResponse.from(myStudies, recruitingStudies);
3736

3837
return ApiResponse.success(response);

src/main/java/grep/neogul_coder/domain/recruitment/comment/controller/dto/response/CommentsWithWriterInfo.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@
44
import com.querydsl.core.annotations.QueryProjection;
55
import io.swagger.v3.oas.annotations.media.Schema;
66
import lombok.Getter;
7+
import lombok.ToString;
78

9+
import java.time.LocalDate;
10+
import java.time.LocalDateTime;
11+
import java.time.LocalTime;
12+
13+
@ToString
814
@Getter
915
public class CommentsWithWriterInfo {
1016

17+
@Schema(example = "3", description = "회원 식별자")
18+
private Long userId;
19+
1120
@Schema(example = "테스터", description = "닉네임")
1221
private String nickname;
1322

@@ -17,23 +26,25 @@ public class CommentsWithWriterInfo {
1726
@Schema(example = "참여 하고 싶습니다!", description = "댓글 내용")
1827
private String content;
1928

20-
@JsonIgnore
21-
private Long userId;
29+
@Schema(example = "2025-07-18", description = "댓글 생성일")
30+
private LocalDate createdAt;
2231

2332
@JsonIgnore
2433
private boolean activated;
2534

2635
@QueryProjection
2736
public CommentsWithWriterInfo(Long userId, String nickname, String imageUrl,
28-
String content, boolean activated) {
37+
String content, LocalDateTime createdAt, boolean activated) {
2938
this.userId = userId;
3039
this.nickname = nickname;
3140
this.imageUrl = imageUrl;
3241
this.content = content;
42+
this.createdAt = createdAt.toLocalDate();
3343
this.activated = activated;
3444
}
3545

3646
public CommentsWithWriterInfo updateNickName(String nickname) {
37-
return new CommentsWithWriterInfo(this.userId, nickname, this.imageUrl, this.content, this.activated);
47+
return new CommentsWithWriterInfo(this.userId, nickname, this.imageUrl, this.content,
48+
LocalDateTime.of(this.createdAt, LocalTime.MIDNIGHT), this.activated);
3849
}
3950
}

src/main/java/grep/neogul_coder/domain/recruitment/comment/repository/RecruitmentPostCommentQueryRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public List<CommentsWithWriterInfo> findCommentsWithWriterInfo(Long recruitmentP
3939
user.nickname,
4040
user.profileImageUrl.as("imageUrl"),
4141
recruitmentPostComment.content,
42+
recruitmentPostComment.createdDate,
4243
user.activated
4344
)
4445
)

src/main/java/grep/neogul_coder/domain/recruitment/post/controller/RecruitmentPostController.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import grep.neogul_coder.domain.recruitment.post.controller.dto.request.RecruitmentPostStatusUpdateRequest;
44
import grep.neogul_coder.domain.recruitment.post.controller.dto.request.RecruitmentPostUpdateRequest;
55
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentApplicationPagingInfo;
6-
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostCommentPagingInfo;
76
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostInfo;
87
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostPagingInfo;
98
import grep.neogul_coder.domain.recruitment.post.service.RecruitmentPostService;
@@ -25,7 +24,14 @@ public class RecruitmentPostController implements RecruitmentPostSpecification {
2524

2625
@GetMapping
2726
public ApiResponse<RecruitmentPostPagingInfo> getPagingInfo(@PageableDefault(size = 10) Pageable pageable) {
28-
RecruitmentPostPagingInfo response = recruitmentPostService.getPagingInfo(pageable);
27+
RecruitmentPostPagingInfo response = recruitmentPostService.getPagingInfo(pageable, null);
28+
return ApiResponse.success(response);
29+
}
30+
31+
@GetMapping("/me")
32+
public ApiResponse<RecruitmentPostPagingInfo> getMyPostPagingInfo(@PageableDefault(size = 10) Pageable pageable,
33+
@AuthenticationPrincipal Principal userDetails) {
34+
RecruitmentPostPagingInfo response = recruitmentPostService.getPagingInfo(pageable, userDetails.getUserId());
2935
return ApiResponse.success(response);
3036
}
3137

@@ -64,9 +70,4 @@ public ApiResponse<RecruitmentApplicationPagingInfo> getApplications(@PageableDe
6470
return ApiResponse.success(new RecruitmentApplicationPagingInfo());
6571
}
6672

67-
@GetMapping("{recruitment-post-id}/comments")
68-
public ApiResponse<RecruitmentPostCommentPagingInfo> getComments(@PageableDefault(size = 5) Pageable pageable,
69-
@PathVariable("recruitment-post-id") long recruitmentPostId) {
70-
return ApiResponse.success(new RecruitmentPostCommentPagingInfo());
71-
}
7273
}

src/main/java/grep/neogul_coder/domain/recruitment/post/controller/RecruitmentPostSpecification.java

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import grep.neogul_coder.domain.recruitment.post.controller.dto.request.RecruitmentPostStatusUpdateRequest;
44
import grep.neogul_coder.domain.recruitment.post.controller.dto.request.RecruitmentPostUpdateRequest;
55
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentApplicationPagingInfo;
6-
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostCommentPagingInfo;
76
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostInfo;
87
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostPagingInfo;
98
import grep.neogul_coder.global.auth.Principal;
@@ -27,6 +26,45 @@ public interface RecruitmentPostSpecification {
2726
@Operation(summary = "모집 상태 변경", description = "모집글의 상태를 변경 합니다.")
2827
ApiResponse<Long> changeStatus(long recruitmentPostId, RecruitmentPostStatusUpdateRequest request, Principal userDetails);
2928

29+
@Operation(
30+
summary = "내가 등록한 모집글 페이징 조회",
31+
description = """
32+
내가 등록한 모집글 목록을 페이징하여 조회합니다.
33+
34+
✅ 요청 예시:
35+
`GET /recruitment-posts/me?page=0&size=5`
36+
37+
✅ 응답 예시:
38+
```json
39+
{
40+
"data": {
41+
"postInfos": [
42+
{
43+
"subject": "자바 스터디 모집 합니다!",
44+
"content": "자바 스터디는 주 3회 오후 6시에 진행 됩니다.",
45+
"category": "IT",
46+
"studyType": "온라인",
47+
"status": "모집중",
48+
"commentCount": 3,
49+
"createAt": "2025-07-15"
50+
},
51+
{
52+
"subject": "이펙티브 자바 함께 읽어요",
53+
"content": "이펙티브 자바 3판을 함께 읽으며 토론하는 스터디입니다.",
54+
"category": "개발",
55+
"studyType": "오프라인",
56+
"status": "모집완료",
57+
"commentCount": 5,
58+
"createAt": "2025-07-10"
59+
}
60+
]
61+
}
62+
}
63+
```
64+
"""
65+
)
66+
ApiResponse<RecruitmentPostPagingInfo> getMyPostPagingInfo(Pageable pageable, Principal userDetails);
67+
3068
@Operation(
3169
summary = "모집글 페이징 조회",
3270
description = """
@@ -93,34 +131,4 @@ public interface RecruitmentPostSpecification {
93131
)
94132
ApiResponse<RecruitmentApplicationPagingInfo> getApplications(Pageable pageable, long recruitmentPostId);
95133

96-
@Operation(
97-
summary = "모집글 댓글 페이징 조회",
98-
description = """
99-
특정 모집글에 작성된 댓글들을 페이징하여 조회합니다.
100-
101-
✅ 요청 형식:
102-
`GET /recruitment-posts/{id}/comments?page=0&size=5`
103-
104-
✅ 응답 예시:
105-
```json
106-
{
107-
"commentsInfos": [
108-
{
109-
"nickname": "테스터",
110-
"imageUrl": "www.s3.com",
111-
"content": "참여 하고 싶습니다!"
112-
},
113-
{
114-
"nickname": "철수",
115-
"imageUrl": "www.s3.com/철수.png",
116-
"content": "스터디에 관심 있습니다!"
117-
}
118-
],
119-
"totalPage": 3,
120-
"totalElementCount": 20
121-
}
122-
```
123-
"""
124-
)
125-
ApiResponse<RecruitmentPostCommentPagingInfo> getComments(Pageable pageable, long recruitmentPostId);
126134
}

src/main/java/grep/neogul_coder/domain/recruitment/post/controller/dto/response/RecruitmentPostCommentPagingInfo.java

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/main/java/grep/neogul_coder/domain/recruitment/post/controller/dto/response/RecruitmentPostInfo.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,31 @@
33
import grep.neogul_coder.domain.recruitment.comment.controller.dto.response.CommentsWithWriterInfo;
44
import io.swagger.v3.oas.annotations.media.Schema;
55
import lombok.Getter;
6+
import lombok.ToString;
67

78
import java.util.List;
89

10+
@ToString
911
@Getter
1012
public class RecruitmentPostInfo {
1113

1214
@Schema(example = "{ category: IT, location: 서울, studyType: OFFLINE, startedDate: 2025-07-09, endDate: 2025-08-10... }")
13-
private RecruitmentPostDetailsInfo postDetailsInfo;
15+
private RecruitmentPostWithStudyInfo postDetailsInfo;
1416

1517
@Schema(example = "[ {nickname: 닉네임, imageUrl: www.., content: 댓글}, {nickname: 닉네임2, imageUrl: www.., content: 댓글2} ]")
1618
private List<CommentsWithWriterInfo> commentsWithWriterInfos;
1719

1820
@Schema(example = "2", description = "신청 내역 수")
1921
private int applicationCount;
2022

21-
public RecruitmentPostInfo(RecruitmentPostDetailsInfo postInfo, List<CommentsWithWriterInfo> comments, int applicationCount) {
23+
@Schema(example = "3", description = "댓글 개수")
24+
private int commentCount;
25+
26+
public RecruitmentPostInfo(RecruitmentPostWithStudyInfo postInfo, List<CommentsWithWriterInfo> comments, int applicationCount) {
2227
this.postDetailsInfo = postInfo;
2328
this.commentsWithWriterInfos = comments;
2429
this.applicationCount = applicationCount;
30+
this.commentCount = comments.size();
2531
}
2632

2733
}

src/main/java/grep/neogul_coder/domain/recruitment/post/controller/dto/response/RecruitmentPostPagingInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import grep.neogul_coder.domain.study.Study;
66
import io.swagger.v3.oas.annotations.media.Schema;
77
import lombok.Getter;
8+
import lombok.ToString;
89

910
import java.time.LocalDate;
1011
import java.util.Collections;
1112
import java.util.List;
1213
import java.util.Map;
1314

15+
@ToString
1416
@Getter
1517
public class RecruitmentPostPagingInfo {
1618

@@ -34,9 +36,13 @@ public static RecruitmentPostPagingInfo of(List<RecruitmentPost> recruitmentPost
3436
return new RecruitmentPostPagingInfo(postInfos);
3537
}
3638

39+
@ToString
3740
@Getter
3841
static class RecruitmentPostInfo {
3942

43+
@Schema(example = "3", description = "모집글 식별자")
44+
private long recruitmentPostId;
45+
4046
@Schema(example = "자바 스터디 모집 합니다!", description = "제목")
4147
private String subject;
4248

@@ -59,6 +65,7 @@ static class RecruitmentPostInfo {
5965
private LocalDate createAt;
6066

6167
private RecruitmentPostInfo(RecruitmentPost post, Study study, List<RecruitmentPostComment> comments) {
68+
this.recruitmentPostId = post.getId();
6269
this.subject = post.getSubject();
6370
this.content = post.getContent();
6471
this.category = study.getCategory().name();
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212

1313
@ToString
1414
@Getter
15-
public class RecruitmentPostDetailsInfo {
15+
public class RecruitmentPostWithStudyInfo {
1616

1717
@Schema(example = "닉네임", description = "작성자 회원 닉네임")
1818
private String nickname;
1919

20+
@Schema(example = "3", description = "모집글 식별자")
21+
private final long recruitmentPostId;
22+
2023
@Schema(example = "너굴 코더 스터디를 모집 합니다", description = "제목")
2124
private String subject;
2225

@@ -48,11 +51,12 @@ public class RecruitmentPostDetailsInfo {
4851
private LocalDateTime endDate;
4952

5053
@QueryProjection
51-
public RecruitmentPostDetailsInfo(String nickname, String subject, String content,
52-
int recruitmentCount, LocalDateTime createdDate, LocalDate expiredDate,
53-
Category category, String location, StudyType studyType,
54-
LocalDateTime startedDate, LocalDateTime endDate) {
54+
public RecruitmentPostWithStudyInfo(String nickname, long recruitmentPostId, String subject,
55+
String content, int recruitmentCount, LocalDateTime createdDate,
56+
LocalDate expiredDate, Category category, String location,
57+
StudyType studyType, LocalDateTime startedDate, LocalDateTime endDate) {
5558
this.nickname = nickname;
59+
this.recruitmentPostId = recruitmentPostId;
5660
this.subject = subject;
5761
this.content = content;
5862
this.recruitmentCount = recruitmentCount;

src/main/java/grep/neogul_coder/domain/recruitment/post/repository/RecruitmentPostQueryRepository.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import com.querydsl.jpa.impl.JPAQueryFactory;
44
import grep.neogul_coder.domain.recruitment.post.RecruitmentPost;
5-
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.QRecruitmentPostDetailsInfo;
6-
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostDetailsInfo;
5+
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.QRecruitmentPostWithStudyInfo;
6+
import grep.neogul_coder.domain.recruitment.post.controller.dto.response.RecruitmentPostWithStudyInfo;
77
import jakarta.persistence.EntityManager;
88
import org.springframework.data.domain.Pageable;
99
import org.springframework.stereotype.Repository;
@@ -25,10 +25,11 @@ public RecruitmentPostQueryRepository(EntityManager em) {
2525
this.queryFactory = new JPAQueryFactory(em);
2626
}
2727

28-
public RecruitmentPostDetailsInfo findPostDetailsInfo(Long recruitmentPostId) {
28+
public RecruitmentPostWithStudyInfo findPostWithStudyInfo(Long recruitmentPostId) {
2929
return queryFactory.select(
30-
new QRecruitmentPostDetailsInfo(
30+
new QRecruitmentPostWithStudyInfo(
3131
user.nickname,
32+
recruitmentPost.id,
3233
recruitmentPost.subject,
3334
recruitmentPost.content,
3435
recruitmentPost.recruitmentCount,
@@ -50,12 +51,24 @@ public RecruitmentPostDetailsInfo findPostDetailsInfo(Long recruitmentPostId) {
5051
).fetchOne();
5152
}
5253

53-
public List<RecruitmentPost> findPaging(Pageable pageable) {
54+
public List<RecruitmentPost> findAllByFilter(Pageable pageable) {
5455
return queryFactory.selectFrom(recruitmentPost)
5556
.where(recruitmentPost.activated.isTrue())
5657
.offset(pageable.getOffset())
5758
.limit(pageable.getPageSize())
5859
.orderBy(recruitmentPost.createdDate.desc())
5960
.fetch();
6061
}
62+
63+
public List<RecruitmentPost> findAllByFilter(Pageable pageable, Long userId) {
64+
return queryFactory.selectFrom(recruitmentPost)
65+
.where(
66+
recruitmentPost.userId.eq(userId),
67+
recruitmentPost.activated.isTrue()
68+
)
69+
.offset(pageable.getOffset())
70+
.limit(pageable.getPageSize())
71+
.orderBy(recruitmentPost.createdDate.desc())
72+
.fetch();
73+
}
6174
}

0 commit comments

Comments
 (0)