Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.back.domain.myhistory.dto.MyHistoryCommentGoResponseDto;
import com.back.domain.myhistory.dto.MyHistoryCommentListDto;
import com.back.domain.myhistory.dto.MyHistoryPostListDto;
import com.back.domain.myhistory.dto.MyHistoryLikedPostListDto;
import com.back.domain.myhistory.service.MyHistoryService;
import com.back.global.rsData.RsData;
import jakarta.validation.constraints.Max;
Expand Down Expand Up @@ -54,6 +55,17 @@ public RsData<MyHistoryCommentListDto> getMyComments(
return RsData.successOf(body);
}

@GetMapping("/likes")
public RsData<MyHistoryLikedPostListDto> getMyLikedPosts(
@AuthenticationPrincipal(expression = "id") Long userId,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime lastCreatedAt,
@RequestParam(required = false) Long lastId,
@RequestParam(defaultValue = "20") @Min(1) @Max(100) int limit
) {
MyHistoryLikedPostListDto body = myHistoryService.getMyLikedPosts(userId, lastCreatedAt, lastId, limit);
return RsData.successOf(body);
}

@GetMapping("/comments/{id}")
public RsData<MyHistoryCommentGoResponseDto> goFromComment(
@AuthenticationPrincipal(expression = "id") Long userId,
Expand All @@ -62,5 +74,14 @@ public RsData<MyHistoryCommentGoResponseDto> goFromComment(
var body = myHistoryService.getPostLinkFromMyComment(userId, commentId);
return RsData.successOf(body);
}

@GetMapping("/likes/{id}")
public RsData<com.back.domain.myhistory.dto.MyHistoryPostGoResponseDto> goFromLikedPost(
@AuthenticationPrincipal(expression = "id") Long userId,
@PathVariable("id") Long postId
) {
var body = myHistoryService.getPostLinkFromMyLikedPost(userId, postId);
return RsData.successOf(body);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.back.domain.myhistory.dto;

import com.back.domain.post.post.entity.Post;
import com.back.domain.post.post.entity.PostLike;
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class MyHistoryLikedPostItemDto {
private Long id;
private String title;
private String imageUrl;
private LocalDateTime likedAt;
private Integer likeCount;
private Integer commentCount;

public static MyHistoryLikedPostItemDto from(PostLike pl) {
Post p = pl.getPost();
return MyHistoryLikedPostItemDto.builder()
.id(p.getId())
.title(p.getTitle())
.imageUrl(p.getImageUrl())
.likedAt(pl.getCreatedAt())
.likeCount(p.getLikeCount())
.commentCount(p.getCommentCount())
.build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.back.domain.myhistory.dto;

import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class MyHistoryLikedPostListDto {
private List<MyHistoryLikedPostItemDto> items;
private boolean hasNext;
private LocalDateTime nextCreatedAt;
private Long nextId;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.back.domain.myhistory.repository;

import com.back.domain.post.post.entity.PostLike;
import com.back.domain.post.post.enums.PostLikeStatus;
import com.back.domain.post.post.enums.PostStatus;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface MyHistoryLikedPostRepository extends JpaRepository<PostLike, Long> {

@Query("""
select pl from PostLike pl
join fetch pl.post p
where pl.user.id = :userId
and pl.status = :like
and p.status <> :deleted
order by pl.createdAt desc, pl.id desc
""")
List<PostLike> findMyLikedPostsFirstPage(@Param("userId") Long userId,
@Param("like") PostLikeStatus like,
@Param("deleted") PostStatus deleted,
Pageable pageable);

@Query("""
select pl from PostLike pl
join fetch pl.post p
where pl.user.id = :userId
and pl.status = :like
and p.status <> :deleted
and (pl.createdAt < :lastCreatedAt or (pl.createdAt = :lastCreatedAt and pl.id < :lastId))
order by pl.createdAt desc, pl.id desc
""")
List<PostLike> findMyLikedPostsAfter(@Param("userId") Long userId,
@Param("like") PostLikeStatus like,
@Param("deleted") PostStatus deleted,
@Param("lastCreatedAt") LocalDateTime lastCreatedAt,
@Param("lastId") Long lastId,
Pageable pageable);

@Query("""
select pl from PostLike pl
join fetch pl.post p
where p.id = :postId
and pl.user.id = :userId
and pl.status = :like
""")
PostLike findByPostIdAndUserIdLike(@Param("postId") Long postId,
@Param("userId") Long userId,
@Param("like") PostLikeStatus like);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.back.domain.myhistory.dto.*;
import com.back.domain.myhistory.repository.MyHistoryCommentRepository;
import com.back.domain.myhistory.repository.MyHistoryPostRepository;
import com.back.domain.myhistory.repository.MyHistoryLikedPostRepository;
import com.back.domain.post.comment.entity.Comment;
import com.back.domain.post.post.entity.Post;
import com.back.domain.post.post.enums.PostStatus;
Expand All @@ -22,6 +23,7 @@ public class MyHistoryService {

private final MyHistoryPostRepository myHistoryPostRepository;
private final MyHistoryCommentRepository myHistoryCommentRepository;
private final MyHistoryLikedPostRepository myHistoryLikedPostRepository;

@Transactional(readOnly = true)
public MyHistoryPostListDto getMyPosts(Long userId, LocalDateTime lastCreatedAt, Long lastId, int limit) {
Expand Down Expand Up @@ -108,4 +110,63 @@ public MyHistoryPostGoResponseDto getPostLinkFromMyPost(Long userId, Long postId
String apiUrl = "/api/posts/" + p.getId();
return new MyHistoryPostGoResponseDto(p.getId(), apiUrl);
}

@Transactional(readOnly = true)
public MyHistoryLikedPostListDto getMyLikedPosts(Long userId, LocalDateTime lastCreatedAt, Long lastId, int limit) {
int safeLimit = Math.max(1, Math.min(limit, 100));
int fetchSize = safeLimit + 1;

List<com.back.domain.post.post.entity.PostLike> rows;
if (lastCreatedAt == null || lastId == null) {
rows = myHistoryLikedPostRepository.findMyLikedPostsFirstPage(
userId,
com.back.domain.post.post.enums.PostLikeStatus.LIKE,
com.back.domain.post.post.enums.PostStatus.DELETED,
PageRequest.of(0, fetchSize)
);
} else {
rows = myHistoryLikedPostRepository.findMyLikedPostsAfter(
userId,
com.back.domain.post.post.enums.PostLikeStatus.LIKE,
com.back.domain.post.post.enums.PostStatus.DELETED,
lastCreatedAt,
lastId,
PageRequest.of(0, fetchSize)
);
}

boolean hasNext = rows.size() > safeLimit;
if (hasNext) rows = rows.subList(0, safeLimit);

List<MyHistoryLikedPostItemDto> items = new ArrayList<>();
for (com.back.domain.post.post.entity.PostLike postLike : rows) items.add(MyHistoryLikedPostItemDto.from(postLike));

LocalDateTime nextCreatedAt = null;
Long nextId = null;
if (hasNext && !rows.isEmpty()) {
com.back.domain.post.post.entity.PostLike last = rows.get(rows.size() - 1);
nextCreatedAt = last.getCreatedAt();
nextId = last.getId();
}

return new MyHistoryLikedPostListDto(items, hasNext, nextCreatedAt, nextId);
}

@Transactional(readOnly = true)
public MyHistoryPostGoResponseDto getPostLinkFromMyLikedPost(Long userId, Long postId) {
com.back.domain.post.post.entity.PostLike postLike = myHistoryLikedPostRepository.findByPostIdAndUserIdLike(
postId,
userId,
com.back.domain.post.post.enums.PostLikeStatus.LIKE
);
if (postLike == null) {
throw new ServiceException(404, "좋아요한 게시글을 찾을 수 없습니다.");
}
Post post = postLike.getPost();
if (post.getStatus() == PostStatus.DELETED) {
throw new ServiceException(410, "삭제된 게시글입니다.");
}
String apiUrl = "/api/posts/" + post.getId();
return new MyHistoryPostGoResponseDto(post.getId(), apiUrl);
}
}