Skip to content

Commit bd1718e

Browse files
committed
2 parents eaa82bb + c703bb8 commit bd1718e

File tree

13 files changed

+647
-65
lines changed

13 files changed

+647
-65
lines changed

back/src/main/java/com/back/domain/comment/repository/CommentRepository.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import jakarta.persistence.LockModeType;
55
import org.springframework.data.domain.Page;
66
import org.springframework.data.domain.Pageable;
7+
import org.springframework.data.jpa.repository.EntityGraph;
78
import org.springframework.data.jpa.repository.JpaRepository;
89
import org.springframework.data.jpa.repository.Lock;
910
import org.springframework.data.jpa.repository.Query;
1011
import org.springframework.data.repository.query.Param;
1112
import org.springframework.stereotype.Repository;
1213

14+
import java.util.List;
1315
import java.util.Optional;
1416

1517
/**
@@ -25,4 +27,15 @@ public interface CommentRepository extends JpaRepository<Comment, Long> {
2527
@Lock(LockModeType.PESSIMISTIC_WRITE)
2628
@Query("SELECT c FROM Comment c WHERE c.id = :commentId")
2729
Optional<Comment> findByIdWithLock(@Param("commentId") Long commentId);
30+
31+
@EntityGraph(attributePaths = {"post"})
32+
Page<Comment> findByUserIdOrderByCreatedDateDesc(Long userId, Pageable pageable);
33+
34+
@Query("""
35+
select c.post.id, count(c)
36+
from Comment c
37+
where c.post.id in :postIds
38+
group by c.post.id
39+
""")
40+
List<Object[]> countByPostIdIn(@Param("postIds") List<Long> postIds);
2841
}

back/src/main/java/com/back/domain/post/repository/PostRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.back.domain.post.entity.Post;
44
import jakarta.persistence.LockModeType;
5+
import org.springframework.data.domain.Page;
6+
import org.springframework.data.domain.Pageable;
57
import org.springframework.data.jpa.repository.JpaRepository;
68
import org.springframework.data.jpa.repository.Lock;
79
import org.springframework.data.jpa.repository.Query;
@@ -20,4 +22,6 @@ public interface PostRepository extends JpaRepository<Post, Long>, PostRepositor
2022
Optional<Post> findByIdWithLock(@Param("postId") Long postId);
2123

2224
int countByUserId(Long userId);
25+
26+
Page<Post> findByUserIdOrderByCreatedDateDesc(Long userId, Pageable pageable);
2327
}

back/src/main/java/com/back/domain/scenario/entity/Scenario.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.back.domain.node.entity.BaseLine;
44
import com.back.domain.node.entity.DecisionLine;
5-
import com.back.domain.post.entity.Post;
65
import com.back.domain.user.entity.User;
76
import com.back.global.baseentity.BaseEntity;
87
import jakarta.persistence.*;
@@ -73,4 +72,7 @@ public class Scenario extends BaseEntity {
7372

7473
// 시나리오 대표 이미지 URL
7574
private String img;
75+
76+
// 대표 시나리오 여부
77+
private boolean representative;
7678
}

back/src/main/java/com/back/domain/scenario/repository/ScenarioRepository.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.back.domain.scenario.entity.ScenarioStatus;
55
import org.springframework.data.domain.Page;
66
import org.springframework.data.domain.Pageable;
7-
import org.springframework.data.jpa.repository.EntityGraph;
87
import org.springframework.data.jpa.repository.JpaRepository;
98
import org.springframework.data.jpa.repository.Query;
109
import org.springframework.data.repository.query.Param;
@@ -31,23 +30,17 @@ public interface ScenarioRepository extends JpaRepository<Scenario, Long> {
3130
@Query("SELECT s FROM Scenario s WHERE s.decisionLine.id = :decisionLineId")
3231
Optional<Scenario> findByDecisionLineId(@Param("decisionLineId") Long decisionLineId);
3332

34-
// 사용자별 베이스라인 시나리오 제외 시나리오 목록 조회 (MyPage용, 페이징구현 및 N+1 방지)
35-
@EntityGraph(attributePaths = {"user", "decisionLine", "decisionLine.baseLine"})
36-
@Query("SELECT s FROM Scenario s " +
37-
"WHERE s.user.id = :userId " +
38-
"AND s.decisionLine.baseLine.id = :baseLineId " +
39-
"AND s.status = :status " +
40-
"AND s.id != (SELECT MIN(s2.id) FROM Scenario s2 " +
41-
"WHERE s2.decisionLine.baseLine.id = :baseLineId " +
42-
"AND s2.status = :status) " +
43-
"ORDER BY s.createdDate DESC")
44-
Page<Scenario> findUserNonBaseScenariosByBaseLineId(@Param("userId") Long userId,
45-
@Param("baseLineId") Long baseLineId,
46-
@Param("status") ScenarioStatus status,
47-
Pageable pageable);
33+
// 내 완료된 선택 시나리오 목록 조회 (베이스 시나리오 제외)
34+
Page<Scenario> findByUserIdAndDecisionLineIsNotNullAndStatusOrderByCreatedDateDesc(
35+
Long userId,
36+
ScenarioStatus status,
37+
Pageable pageable
38+
);
4839

4940
@Query("SELECT COALESCE(SUM(s.total), 0) FROM Scenario s WHERE s.user.id = :userId")
5041
int sumTotalByUserId(Long userId);
5142

5243
int countByUserId(Long userId);
44+
45+
Optional<Scenario> findByUserIdAndRepresentativeTrue(Long userId);
5346
}

back/src/main/java/com/back/domain/scenario/repository/SceneTypeRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.back.domain.scenario.entity.SceneType;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
57
import org.springframework.stereotype.Repository;
68

79
import java.util.List;
@@ -14,4 +16,9 @@ public interface SceneTypeRepository extends JpaRepository<SceneType, Long> {
1416

1517
// 특정 시나리오의 지표들 조회 (타입 순서대로)
1618
List<SceneType> findByScenarioIdOrderByTypeAsc(Long scenarioId);
19+
20+
@Query("SELECT st FROM SceneType st WHERE st.scenario.id IN :scenarioIds")
21+
List<SceneType> findByScenarioIdIn(@Param("scenarioIds") List<Long> scenarioIds);
22+
23+
List<SceneType> findByScenarioId(Long scenarioId);
1724
}
Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,90 @@
11
package com.back.domain.user.controller;
22

3-
import com.back.domain.user.dto.UserInfoRequest;
4-
import com.back.domain.user.dto.UserInfoResponse;
5-
import com.back.domain.user.dto.UserStatsResponse;
3+
import com.back.domain.user.dto.*;
64
import com.back.domain.user.service.UserInfoService;
5+
import com.back.global.common.PageResponse;
76
import com.back.global.security.CustomUserDetails;
87
import jakarta.validation.Valid;
98
import lombok.RequiredArgsConstructor;
9+
import org.springframework.data.domain.Pageable;
10+
import org.springframework.data.web.PageableDefault;
1011
import org.springframework.http.ResponseEntity;
1112
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1213
import org.springframework.web.bind.annotation.*;
1314

15+
/**
16+
* 사용자 정보 관리 컨트롤러 (마이 페이지)
17+
* 사용자 정보 조회/수정, 통계, 작성 게시글/댓글 목록, 시나리오 목록 조회, 대표프로필 선택/조회 API 제공
18+
*/
1419
@RestController
15-
@RequestMapping("/api/v1/users-info")
20+
@RequestMapping("/api/v1")
1621
@RequiredArgsConstructor
1722
public class UserInfoController {
1823
private final UserInfoService userInfoService;
1924

20-
@GetMapping("/stats")
25+
// 사용자 통계 정보 조회
26+
@GetMapping("/users/use-log")
2127
public ResponseEntity<UserStatsResponse> getMyStats(@AuthenticationPrincipal CustomUserDetails principal) {
2228
return ResponseEntity.ok(userInfoService.getMyStats(principal.getId()));
2329
}
2430

25-
@GetMapping
31+
// 사용자 정보 조회
32+
@GetMapping("/users-info")
2633
public ResponseEntity<UserInfoResponse> getMyInfo(@AuthenticationPrincipal CustomUserDetails principal) {
2734
return ResponseEntity.ok(userInfoService.getMyInfo(principal.getId()));
2835
}
2936

30-
@PostMapping
37+
// 사용자 정보 생성
38+
@PostMapping("/users-info")
3139
public ResponseEntity<UserInfoResponse> createMyInfo(@AuthenticationPrincipal CustomUserDetails principal,
3240
@Valid @RequestBody UserInfoRequest req) {
3341
return ResponseEntity.ok(userInfoService.createMyInfo(principal.getId(), req));
3442
}
3543

36-
@PutMapping
44+
// 사용자 정보 수정
45+
@PutMapping("/users-info")
3746
public ResponseEntity<UserInfoResponse> updateMyInfo(@AuthenticationPrincipal CustomUserDetails principal,
3847
@Valid @RequestBody UserInfoRequest req) {
3948
return ResponseEntity.ok(userInfoService.updateMyInfo(principal.getId(), req));
4049
}
50+
51+
// 내가 만든 시나리오 목록 조회 (평행우주 목록)
52+
@GetMapping("/users/list")
53+
public ResponseEntity<PageResponse<UserScenarioListResponse>> getMyScenarios(
54+
@AuthenticationPrincipal CustomUserDetails principal,
55+
@PageableDefault(size = 5) Pageable pageable) {
56+
return ResponseEntity.ok(userInfoService.getMyScenarios(principal.getId(), pageable));
57+
}
58+
59+
// 내 게시글 목록 조회
60+
@GetMapping("/users/my-posts")
61+
public ResponseEntity<PageResponse<UserPostListResponse>> getMyPosts(
62+
@AuthenticationPrincipal CustomUserDetails principal,
63+
@PageableDefault(size = 5) Pageable pageable) {
64+
return ResponseEntity.ok(userInfoService.getMyPosts(principal.getId(), pageable));
65+
}
66+
67+
// 내 댓글 목록 조회
68+
@GetMapping("/users/my-comments")
69+
public ResponseEntity<PageResponse<UserCommentListResponse>> getMyComments(
70+
@AuthenticationPrincipal CustomUserDetails principal,
71+
@PageableDefault(size = 5) Pageable pageable) {
72+
return ResponseEntity.ok(userInfoService.getMyComments(principal.getId(), pageable));
73+
}
74+
75+
// 대표 시나리오 설정
76+
@PutMapping("/users/profile-scenario")
77+
public ResponseEntity<Void> setProfileScenario(
78+
@AuthenticationPrincipal CustomUserDetails principal,
79+
@RequestParam Long scenarioId) {
80+
userInfoService.setProfileScenario(principal.getId(), scenarioId);
81+
return ResponseEntity.ok().build();
82+
}
83+
84+
// 대표 프로필 조회
85+
@GetMapping("/users/profile")
86+
public ResponseEntity<UserProfileResponse> getMyProfile(
87+
@AuthenticationPrincipal CustomUserDetails principal) {
88+
return ResponseEntity.ok(userInfoService.getMyProfile(principal.getId()));
89+
}
4190
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.back.domain.user.dto;
2+
3+
import com.back.domain.comment.entity.Comment;
4+
5+
import java.time.LocalDateTime;
6+
7+
public record UserCommentListResponse(
8+
Long commentId,
9+
Long postId,
10+
String postTitle,
11+
String content,
12+
LocalDateTime postCreatedAt,
13+
LocalDateTime commentCreatedAt
14+
) {
15+
public static UserCommentListResponse from(Comment comment) {
16+
return new UserCommentListResponse(
17+
comment.getId(),
18+
comment.getPost().getId(),
19+
comment.getPost().getTitle(),
20+
comment.getContent(),
21+
comment.getPost().getCreatedDate(),
22+
comment.getCreatedDate()
23+
);
24+
}
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.back.domain.user.dto;
2+
3+
import com.back.domain.post.entity.Post;
4+
5+
import java.time.LocalDateTime;
6+
7+
public record UserPostListResponse(
8+
Long postId,
9+
String title,
10+
LocalDateTime createdAt,
11+
long commentCount
12+
) {
13+
public static UserPostListResponse of(Post post, long commentCount) {
14+
return new UserPostListResponse(
15+
post.getId(),
16+
post.getTitle(),
17+
post.getCreatedDate(),
18+
commentCount
19+
);
20+
}
21+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.back.domain.user.dto;
2+
3+
import com.back.domain.scenario.entity.Scenario;
4+
import com.back.domain.scenario.entity.SceneType;
5+
import com.back.domain.scenario.entity.Type;
6+
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.stream.Collectors;
10+
11+
public record UserProfileResponse(
12+
String nickname,
13+
Long representativeScenarioId,
14+
String description,
15+
Map<Type, Integer> sceneTypePoints
16+
) {
17+
public static UserProfileResponse from(String nickname, Scenario scenario, List<SceneType> sceneTypes) {
18+
Map<Type, Integer> pointsMap = sceneTypes.stream()
19+
.collect(Collectors.toMap(
20+
SceneType::getType,
21+
SceneType::getPoint
22+
));
23+
24+
return new UserProfileResponse(
25+
nickname,
26+
scenario.getId(),
27+
scenario.getDescription(),
28+
pointsMap
29+
);
30+
}
31+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.back.domain.user.dto;
2+
3+
import com.back.domain.scenario.entity.Scenario;
4+
import com.back.domain.scenario.entity.SceneType;
5+
import com.back.domain.scenario.entity.Type;
6+
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.stream.Collectors;
10+
11+
public record UserScenarioListResponse(
12+
Long scenarioId,
13+
String job,
14+
Map<Type, Integer> typeScores,
15+
int total,
16+
String summary
17+
) {
18+
public static UserScenarioListResponse from(Scenario scenario, List<SceneType> sceneTypes) {
19+
Map<Type, Integer> typeScores = sceneTypes.stream()
20+
.collect(Collectors.toMap(
21+
SceneType::getType,
22+
SceneType::getPoint
23+
));
24+
25+
return new UserScenarioListResponse(
26+
scenario.getId(),
27+
scenario.getJob(),
28+
typeScores,
29+
scenario.getTotal(),
30+
scenario.getSummary()
31+
);
32+
}
33+
}

0 commit comments

Comments
 (0)