Skip to content

Commit

Permalink
Merge pull request #69 from UMC-Edison/feature/28
Browse files Browse the repository at this point in the history
✨[FEAT] #28: 아트레터 좋아요+취소, 스크랩+취소 기능 구현
  • Loading branch information
Sunho12 authored Jan 23, 2025
2 parents bed8680 + cac7a76 commit f3b2103
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public enum ErrorStatus {
TAG_VALIDATION(HttpStatus.BAD_REQUEST, "LETTER4007", "tag field 관련 오류"),
CATEGORY_VALIDATION(HttpStatus.BAD_REQUEST, "LETTER4008", "category field 관련 오류"),
KEYWORD_IS_EMPTY(HttpStatus.BAD_REQUEST, "LETTER4009", "keyword field 관련 오류"),
LETTERS_NOT_FOUND(HttpStatus.BAD_REQUEST, "LABEL4010", "아트레터를 찾을 수 없습니다."),
LETTERS_NOT_FOUND(HttpStatus.BAD_REQUEST, "LETTER4010", "아트레터를 찾을 수 없습니다."),


// 검색 관련 에러
INVALID_KEYWORD(HttpStatus.BAD_REQUEST, "SEARCH4001", "검색어는 공백일 수 없습니다.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,24 @@ public ResponseEntity<ApiResponse> searchArtletters(
return ApiResponse.onSuccess(SuccessStatus._OK, results.getContent());
}

// 좋아요 기능
@PostMapping("/{letterId}/like")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<ApiResponse> likeArtletter(@PathVariable Long letterId, @AuthenticationPrincipal CustomUserPrincipal userPrincipal) {
ArtletterDTO.LikeResponseDto response = artletterService.likeToggleArtletter(userPrincipal, letterId);

return ApiResponse.onSuccess(SuccessStatus._OK, response);
}

// 스크랩 기능
@PostMapping("/{letterId}/scrap")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<ApiResponse> scrapArtletter(@PathVariable Long letterId, @AuthenticationPrincipal CustomUserPrincipal userPrincipal) {
ArtletterDTO.ScrapResponseDto response = artletterService.scrapToggleArtletter(userPrincipal, letterId);
return ApiResponse.onSuccess(SuccessStatus._OK, response);
}


@GetMapping("/{letterId}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<ApiResponse> getArtletterInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,24 @@ public static class ListResponseDto {
private LocalDateTime updatedAt;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class LikeResponseDto {
private Long artletterId;
private int likesCnt;
private boolean isLiked;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ScrapResponseDto {
private Long artletterId;
private int scrapsCnt;
private boolean isScrapped;
}
}

Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.edison.project.domain.artletter.entity;

import com.edison.project.domain.bubble.entity.Bubble;
import com.edison.project.domain.bubble.entity.BubbleLabel;
import com.edison.project.domain.member.entity.Member;
import com.edison.project.global.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.*;

import java.util.Set;

@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "ArtletterLikes", uniqueConstraints = {
@UniqueConstraint(name = "uq_artletter_member", columnNames = {"artletter_id", "member_id"})
Expand All @@ -28,4 +32,10 @@ public class ArtletterLikes {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
private Member member;

@Builder
public ArtletterLikes(Member member, Artletter artletter) {
this.member = member;
this.artletter = artletter;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.edison.project.domain.artletter.repository;

import com.edison.project.domain.member.entity.Member;
import jakarta.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Repository;
import com.edison.project.domain.artletter.entity.ArtletterLikes;
import com.edison.project.domain.artletter.entity.Artletter;
Expand All @@ -10,4 +12,8 @@
public interface ArtletterLikesRepository extends JpaRepository<ArtletterLikes, Long> {
int countByArtletter(Artletter artletter);
boolean existsByMemberAndArtletter(Member member, Artletter artletter);

@Modifying
@Transactional
void deleteByMemberAndArtletter(Member member, Artletter artletter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public interface ArtletterService {

ArtletterDTO.CreateResponseDto createArtletter(ArtletterDTO.CreateRequestDto request);

ArtletterDTO.LikeResponseDto likeToggleArtletter(CustomUserPrincipal userPrincipal, Long letterId);

ArtletterDTO.ScrapResponseDto scrapToggleArtletter(CustomUserPrincipal userPrincipal, Long letterId);

Page<Artletter> searchArtletters(String keyword, Pageable pageable);

ArtletterDTO.ListResponseDto getArtletter(CustomUserPrincipal userPrincipal, long letterId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
import com.edison.project.common.status.ErrorStatus;
import com.edison.project.domain.artletter.dto.ArtletterDTO;
import com.edison.project.domain.artletter.entity.Artletter;
import com.edison.project.domain.artletter.entity.ArtletterLikes;
import com.edison.project.domain.artletter.repository.ArtletterLikesRepository;
import com.edison.project.domain.artletter.repository.ArtletterRepository;
import com.edison.project.domain.member.entity.Member;
import com.edison.project.domain.member.repository.MemberRepository;
import com.edison.project.domain.scrap.entity.Scrap;
import com.edison.project.domain.scrap.repository.ScrapRepository;
import com.edison.project.global.security.CustomUserPrincipal;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand All @@ -29,9 +30,10 @@
public class ArtletterServiceImpl implements ArtletterService {

private final ArtletterRepository artletterRepository;
private final MemberRepository memberRepository;
private final ArtletterLikesRepository artletterLikesRepository;
private final ScrapRepository scrapRepository;
private final MemberRepository memberRepository;


public Page<Artletter> getAllArtletters(int page, int size) {
// 페이지 요청 생성
Expand Down Expand Up @@ -60,6 +62,77 @@ public ArtletterDTO.CreateResponseDto createArtletter(ArtletterDTO.CreateRequest
.build();
}

@Override
@Transactional
public ArtletterDTO.LikeResponseDto likeToggleArtletter(CustomUserPrincipal userPrincipal, Long letterId) {
if (userPrincipal == null) {
throw new GeneralException(ErrorStatus.LOGIN_REQUIRED);
}

Member member = memberRepository.findById(userPrincipal.getMemberId())
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));

Artletter artletter = artletterRepository.findById(letterId)
.orElseThrow(() -> new GeneralException(ErrorStatus.LETTERS_NOT_FOUND));

boolean alreadyLiked = artletterLikesRepository.existsByMemberAndArtletter(member, artletter);

if (alreadyLiked) {
// 좋아요 취소
artletterLikesRepository.deleteByMemberAndArtletter(member, artletter);
} else {
// 좋아요
ArtletterLikes like = ArtletterLikes.builder()
.member(member)
.artletter(artletter)
.build();

artletterLikesRepository.save(like);
}

int likeCnt = artletterLikesRepository.countByArtletter(artletter);

return ArtletterDTO.LikeResponseDto.builder()
.artletterId(letterId)
.likesCnt(likeCnt)
.isLiked(!alreadyLiked)
.build();
}

@Override
public ArtletterDTO.ScrapResponseDto scrapToggleArtletter(CustomUserPrincipal userPrincipal, Long letterId) {
if (userPrincipal == null) {
throw new GeneralException(ErrorStatus.LOGIN_REQUIRED);
}

Member member = memberRepository.findById(userPrincipal.getMemberId())
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));

Artletter artletter = artletterRepository.findById(letterId)
.orElseThrow(() -> new GeneralException(ErrorStatus.LETTERS_NOT_FOUND));

boolean alreadyScrapped = scrapRepository.existsByMemberAndArtletter(member, artletter);

if (alreadyScrapped) {
scrapRepository.deleteByMemberAndArtletter(member, artletter);
} else {
Scrap scrap = Scrap.builder()
.member(member)
.artletter(artletter)
.build();

scrapRepository.save(scrap);
}

int scrapCnt = scrapRepository.countByArtletter(artletter);

return ArtletterDTO.ScrapResponseDto.builder()
.artletterId(letterId)
.scrapsCnt(scrapCnt)
.isScrapped(!alreadyScrapped)
.build();
}

@Override
public Page<Artletter> searchArtletters(String keyword, Pageable pageable) {
return artletterRepository.searchByKeyword(keyword, pageable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import com.edison.project.domain.artletter.entity.Artletter;
import com.edison.project.domain.member.entity.Member;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.*;

@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "Scrap")
public class Scrap {
Expand All @@ -24,4 +23,10 @@ public class Scrap {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "letter_id", nullable = false)
private Artletter artletter;

@Builder
public Scrap(Member member, Artletter artletter) {
this.member = member;
this.artletter = artletter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
import com.edison.project.domain.artletter.entity.Artletter;
import com.edison.project.domain.member.entity.Member;
import com.edison.project.domain.scrap.entity.Scrap;
import jakarta.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;


public interface ScrapRepository extends JpaRepository<Scrap, Long> {
int countByArtletter(Artletter artletter);
boolean existsByMemberAndArtletter(Member member, Artletter artletter);

@Modifying
@Transactional
void deleteByMemberAndArtletter(Member member, Artletter artletter);
}

0 comments on commit f3b2103

Please sign in to comment.