-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[FEAT] 홈 화면 즐겨찾기 API 구현
- Loading branch information
Showing
12 changed files
with
230 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/main/java/org/sopt/lequuServer/domain/favorite/controller/FavoriteApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.sopt.lequuServer.domain.favorite.controller; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.media.ArraySchema; | ||
import io.swagger.v3.oas.annotations.media.Content; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import org.sopt.lequuServer.domain.favorite.dto.request.FavoriteCreateRequestDto; | ||
import org.sopt.lequuServer.domain.favorite.dto.response.FavoriteBookResponseDto; | ||
import org.sopt.lequuServer.global.common.dto.ApiResponse; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
|
||
import java.security.Principal; | ||
import java.util.List; | ||
|
||
@Tag(name = "Favorite", description = "즐겨찾기 API") | ||
public interface FavoriteApi { | ||
|
||
@SecurityRequirement(name = "JWT Authorization") | ||
@io.swagger.v3.oas.annotations.responses.ApiResponse( | ||
responseCode = "201", | ||
description = "즐겨찾기 레큐북 등록을 성공했습니다." | ||
) | ||
@Operation(summary = "즐겨찾기 레큐북 생성") | ||
public ResponseEntity<ApiResponse<?>> createFavorite(Principal principal, @RequestBody FavoriteCreateRequestDto request); | ||
|
||
@SecurityRequirement(name = "JWT Authorization") | ||
@io.swagger.v3.oas.annotations.responses.ApiResponse( | ||
responseCode = "200", | ||
description = "즐겨찾는 레큐북 조회에 성공했습니다.", | ||
content = @Content(array = @ArraySchema(schema = @Schema(implementation = FavoriteBookResponseDto.class))) | ||
) | ||
@Operation(summary = "즐겨찾는 레큐북 조회") | ||
public ResponseEntity<ApiResponse<List<FavoriteBookResponseDto>>> getFavorite(Principal principal); | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/org/sopt/lequuServer/domain/favorite/controller/FavoriteController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.sopt.lequuServer.domain.favorite.controller; | ||
|
||
import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
import lombok.RequiredArgsConstructor; | ||
import org.sopt.lequuServer.domain.favorite.dto.request.FavoriteCreateRequestDto; | ||
import org.sopt.lequuServer.domain.favorite.dto.response.FavoriteBookResponseDto; | ||
import org.sopt.lequuServer.domain.favorite.facade.FavoriteFacade; | ||
import org.sopt.lequuServer.global.auth.jwt.JwtProvider; | ||
import org.sopt.lequuServer.global.common.dto.ApiResponse; | ||
import org.sopt.lequuServer.global.exception.enums.SuccessType; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.security.Principal; | ||
import java.util.List; | ||
|
||
@SecurityRequirement(name = "JWT Authorization") | ||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/favorite") | ||
public class FavoriteController implements FavoriteApi { | ||
|
||
private final FavoriteFacade favoriteFacade; | ||
|
||
@PostMapping | ||
public ResponseEntity<ApiResponse<?>> createFavorite(Principal principal, @RequestBody FavoriteCreateRequestDto request) { | ||
favoriteFacade.createFavorite(JwtProvider.getUserFromPrincial(principal), request); | ||
return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.success(SuccessType.CREATE_FAVORITE_SUCCESS)); | ||
} | ||
|
||
@GetMapping | ||
public ResponseEntity<ApiResponse<List<FavoriteBookResponseDto>>> getFavorite(Principal principal) { | ||
return ResponseEntity.ok(ApiResponse.success(SuccessType.GET_FAVORITE_SUCCESS, favoriteFacade.getFavorite(JwtProvider.getUserFromPrincial(principal)))); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/org/sopt/lequuServer/domain/favorite/dto/request/FavoriteCreateRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.sopt.lequuServer.domain.favorite.dto.request; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
|
||
public record FavoriteCreateRequestDto( | ||
@Schema(example = "1") | ||
Long bookId | ||
) { | ||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/org/sopt/lequuServer/domain/favorite/dto/response/FavoriteBookResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.sopt.lequuServer.domain.favorite.dto.response; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import org.sopt.lequuServer.domain.book.model.Book; | ||
|
||
public record FavoriteBookResponseDto( | ||
|
||
@Schema(description = "레큐북 고유 id", example = "1") | ||
Long bookId, | ||
|
||
@Schema(description = "레큐북 UUID", example = "ee4f66f9-9cf4-4b28-90f4-f71d0ecba021") | ||
String bookUuid, | ||
|
||
@Schema(description = "최애 이름", example = "LeoJ") | ||
String favoriteName, | ||
|
||
@Schema(description = "최애 사진", example = "https://dzfv99wxq6tx0.cloudfront.net/books/favorite_image/b4006561-382b-479e-ae1d-e841922e883f.jpg") | ||
String favoriteImage | ||
) { | ||
public static FavoriteBookResponseDto of(Book book) { | ||
return new FavoriteBookResponseDto(book.getId(), book.getUuid(), book.getFavoriteName(), | ||
book.getFavoriteImage()); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/org/sopt/lequuServer/domain/favorite/facade/FavoriteFacade.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package org.sopt.lequuServer.domain.favorite.facade; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.sopt.lequuServer.domain.book.model.Book; | ||
import org.sopt.lequuServer.domain.book.repository.BookRepository; | ||
import org.sopt.lequuServer.domain.favorite.dto.request.FavoriteCreateRequestDto; | ||
import org.sopt.lequuServer.domain.favorite.dto.response.FavoriteBookResponseDto; | ||
import org.sopt.lequuServer.domain.favorite.model.Favorite; | ||
import org.sopt.lequuServer.domain.favorite.repository.FavoriteRepository; | ||
import org.sopt.lequuServer.domain.member.model.Member; | ||
import org.sopt.lequuServer.domain.member.repository.MemberRepository; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class FavoriteFacade { | ||
|
||
private final FavoriteRepository favoriteRepository; | ||
private final MemberRepository memberRepository; | ||
private final BookRepository bookRepository; | ||
|
||
@Transactional | ||
public void createFavorite(Long memberId, FavoriteCreateRequestDto request) { | ||
Member member = memberRepository.findByIdOrThrow(memberId); | ||
Book book = bookRepository.findByIdOrThrow(request.bookId()); | ||
|
||
Favorite favorite = Favorite.of(member, book); | ||
favoriteRepository.save(favorite); | ||
} // memberId와 bookId를 favorite 에 저장하는 로직 | ||
|
||
public List<FavoriteBookResponseDto> getFavorite(Long memberId) { | ||
Member member = memberRepository.findByIdOrThrow(memberId); | ||
List<Favorite> favorites = favoriteRepository.findByMemberOrderByCreatedAtDesc(member); | ||
|
||
return favorites.stream() | ||
.limit(3) // 최신순 3개만 가져오기 | ||
.map(favorite -> FavoriteBookResponseDto.of(favorite.getBook())) | ||
.collect(Collectors.toList()); | ||
} // memberId를 이용해 그 멤버가 즐겨찾기 해놓은 레큐북 목록들을 반환하는 로직 | ||
} |
40 changes: 40 additions & 0 deletions
40
src/main/java/org/sopt/lequuServer/domain/favorite/model/Favorite.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.sopt.lequuServer.domain.favorite.model; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import org.sopt.lequuServer.domain.book.model.Book; | ||
import org.sopt.lequuServer.domain.member.model.Member; | ||
import org.sopt.lequuServer.global.common.model.BaseTimeEntity; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Table(name = "favorite") | ||
public class Favorite extends BaseTimeEntity { | ||
|
||
@Id | ||
@Column(name = "favorite_id") | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "member_id") | ||
private Member member; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "book_id") | ||
private Book book; | ||
|
||
@Builder | ||
public Favorite(Member member, Book book) { | ||
this.member = member; | ||
this.book = book; | ||
} | ||
|
||
public static Favorite of(Member member, Book book) { | ||
Favorite favorite = new Favorite(member, book); | ||
book.addFavorite(favorite); | ||
member.addFavorite(favorite); | ||
return favorite; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/org/sopt/lequuServer/domain/favorite/repository/FavoriteRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.sopt.lequuServer.domain.favorite.repository; | ||
|
||
import org.sopt.lequuServer.domain.favorite.model.Favorite; | ||
import org.sopt.lequuServer.domain.member.model.Member; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import java.util.List; | ||
|
||
public interface FavoriteRepository extends JpaRepository<Favorite, Long> { | ||
List<Favorite> findByMemberOrderByCreatedAtDesc(Member member); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters