BookService ( getLikeStatus 수정)
public int getLikeStatus(int bookId,int userId) {
Map<String, Object> map = new HashMap<>();
map.put("bookId", bookId);
map.put("userId", userId);
return bookRepository.getLikeStatus(map);
}
BookController (getLikeStatus 메서드 추가)
@GetMapping("/book/{bookId}/like/status")
public ResponseEntity<?> getLikeStatus(@PathVariable int bookId, @RequestParam int userId){
return ResponseEntity.ok().body(bookService.getLikeStatus(bookId,userId));
}
BookDetail.js (getLikeStatus 추가)
const getLikeStatus = useQuery(["getLikeStatus"], async() => {
const option = {
params: {
userId: queryClient.getQueryData("principal").data.userId
},
headers:{
Authorization: localStorage.getItem("accessToken")
}
}
const response = await axios.get(`http://localhost:8080/book/${bookId}/like/status`, option);
return response;
});
좋아요, 좋아요 해제 메서드
BookRepository (추가)
public int setLike(Map<String, Object> map);
public int disLike(Map<String, Object> map);
BookMapper ( insert(좋아요 추가), delete(좋아요 해제) )
<insert id="setLike">
insert into book_like_tb
values (0, #{bookId}, #{userId})
</insert>
<insert id="disLike">
delete
from
book_like_tb
where
book_id = #{bookId}
and user_id + #{userId}
</insert>
BookService (좋아요, 좋아요 해제 메서드 추가)
public int setLike(int bookId,int userId) {
Map<String, Object> map = new HashMap<>();
map.put("bookId", bookId);
map.put("userId", userId);
return bookRepository.setLike(map);
}
public int disLike(int bookId,int userId) {
Map<String, Object> map = new HashMap<>();
map.put("bookId", bookId);
map.put("userId", userId);
return bookRepository.disLike(map);
}
BookController PostMapping(좋아요), deleteMapping(좋아요 해제) 추가
@PostMapping("/book/{bookId}/like")
public ResponseEntity<?> setLike(@RequestBody int bookId,Map<String, Integer> requestMap){
return ResponseEntity.ok().body(bookService.setLike(bookId, requestMap.get("userId")));
}
@DeleteMapping("/book/{bookId}/like")
public ResponseEntity<?> disLike(@RequestBody int bookId,@RequestParam int userId){
return ResponseEntity.ok().body(bookService.disLike(bookId, userId));
}
BookDetail.js (좋아요, 좋아요 취소 기능 구현)
const setLike = useMutation(async() => {
const option = {
headers:{
"Content-Type": "application/json",
Authorization: localStorage.getItem("accessToken")
}
}
// axios.post (url, data, option);
return await axios.post(`http://localhost:8080/book/${bookId}/like`, JSON.stringify({
userId: queryClient.getQueryData("principal").data.userId
}), option);
},{
onSuccess: () => { //delete cash
queryClient.invalidateQueries(["getLikeCount"]);
queryClient.invalidateQueries(["getLikeStatus"]);
}
}); //react to mutation exceptions get requset
const disLike = useMutation(async() => {
const option = {
params: {
userId: queryClient.getQueryData("principal").data.userId
},
headers:{
Authorization: localStorage.getItem("accessToken")
}
}
// axios.post (url, data, option);
return await axios.delete(`http://localhost:8080/book/${bookId}/like`, option);
},{
onSuccess: () => { //delete cash
queryClient.invalidateQueries(["getLikeCount"]);
queryClient.invalidateQueries(["getLikeStatus"]);
}
});
<div>
{getLikeStatus.isLoading
? ""
: getLikeStatus.data.data === 0
// Call the mutate above
? (<button onClick={()=>{setLike.mutate()}}>추천하기</button>)
: (<button onClick={()=>{disLike.mutate()}}>추천취소</button>)}
</div>
components > UI > BookDetail > Rental
RentalList.js
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import React from 'react';
const table = css`
border: 1px solid #dbdbdb;
`;
const thAndTd = css`
border: 1px solid #dbdbdb;
padding: 5px 10px;
text-align: center;
`;
const RentalList = ( { bookId }) => {
return (
<>
<table css={table}>
<tr>
<th css={thAndTd}>도서번호</th>
<th css={thAndTd}>도서명</th>
<th css={thAndTd}>상태</th>
</tr>
</table>
</>
);
};
export default RentalList;
DB 테이블 생성
book_retal_tb 생성
BookDetail.js (컴포넌트 렌더링 추가)
<div>
<RentalList bookId={bookId} />
</div>
Query문 작성
select
blt.book_list_id,
bt.book_name,
brt.user_id
from
book_list_tb blt
left outer join book_tb bt on(bt.book_id = blt.book_id)
left outer join book_rental_tb brt on(brt.book_list_id = blt.book_list_id)
BookRepository (getRentalListByBookId 메서드 추가)
public List<RentalList> getRentalListByBookId(int bookId);
entity
RentalList (entity 생성)
package com.toyproject.bookmanagement.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class RentalList {
private int bookListId;
private String bookName;
private int userId;
}
BookMapper.xml (getRentalListByBookId select문 추가)
<select id="getRentalListByBookId" parameterType="Integer" resultType="com.toyproject.bookmanagement.entity.RentalList" >
select
blt.book_list_id as bookListId,
bt.book_name as bookName,
brt.user_id as userId
from
book_list_tb blt
left outer join book_tb bt on(bt.book_id = blt.book_id)
left outer join book_rental_tb brt on(brt.book_list_id = blt.book_list_id)
where
bt.book_id = #{bookId}
</select>
dto > book
RentalListRespDto (생성)
package com.toyproject.bookmanagement.dto.book;
import lombok.Builder;
import lombok.Data;
@Builder
@Data
public class RentalListRespDto {
private int bookListId;
private String bookName;
private int userId;
private boolean rentalStatus;
}
BookService ( getRentalListByBookId 메서드 추가)
public List<RentalListRespDto> getRentalListByBookId(int bookId){
List<RentalListRespDto> list = new ArrayList<>();
bookRepository.getRentalListByBookId(bookId).forEach(rentalData -> {
list.add(rentalData.toDto());
});
return list;
}
RentalList toDto 메서드 추가
public RentalListRespDto toDto() {
return RentalListRespDto.builder()
.bookListId(bookListId)
.bookName(bookName)
.userId(userId)
.rentalStatus(userId == 0)
.build();
}
BookController (getRentalListByBookId 메서드 추가)
@GetMapping("/book/{bookId}/rental/list")
public ResponseEntity<?> getRentalListByBookId(@PathVariable int bookId){
return ResponseEntity.ok().body(bookService.getRentalListByBookId(bookId));
}
RentalList.js (getRentalList 변수 추가)
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import axios from 'axios';
import React from 'react';
import { useQuery } from 'react-query';
const table = css`
border: 1px solid #dbdbdb;
`;
const thAndTd = css`
border: 1px solid #dbdbdb;
padding: 5px 10px;
text-align: center;
`;
const RentalList = ( { bookId }) => {
const getRentalList = useQuery(["getRentalList"], async()=> {
const option = {
headers: {
Authorization: localStorage.getItem("accessToken")
}
}
return await axios.get(`http://localhost:8080/book/${bookId}/rental/list`,option);
});
if(getRentalList.isLoading) {
return <div>불러오는 중...</div>
}
return (
<>
<table css={table}>
<thead>
<tr>
<th css={thAndTd}>도서번호</th>
<th css={thAndTd}>도서명</th>
<th css={thAndTd}>상태</th>
</tr>
</thead>
<tbody>
{getRentalList.data.data.map(rentalData => {
// Compare key values and Rerendering
return (<tr key={rentalData.bookListId}>
<td css={thAndTd}>{rentalData.bookListId}</td>
<td css={thAndTd}>{rentalData.bookName}</td>
{rentalData.rentalStatus
? (<td css={thAndTd}>대여가능</td>)
: (<td css={thAndTd}>대여중</td>)}
</tr>)
})}
</tbody>
</table>
</>
);
};
export default RentalList;
RentalList.js
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import axios from 'axios';
import React from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
const table = css`
border: 1px solid #dbdbdb;
`;
const thAndTd = css`
border: 1px solid #dbdbdb;
padding: 5px 10px;
text-align: center;
`;
const RentalList = ( { bookId }) => {
const queryClient = useQueryClient();
const getRentalList = useQuery(["getRentalList"], async()=> {
const option = {
headers: {
Authorization: localStorage.getItem("accessToken")
}
}
return await axios.get(`http://localhost:8080/book/${bookId}/rental/list`,option);
});
const rentalBook = useMutation(async(bookListId)=> {
const option = {
headers: {
"Content-Type": "application/json",
Authorization: localStorage.getItem("accessToken")
}
}
return await axios.post(`http://localhost:8080/book/rental/${bookListId}`,JSON.stringify({
userId: queryClient.getQueryData("principal").data.userId
}),option);
},{
onSuccess: () => {
queryClient.invalidateQueries("getRentalList");
}
});
const returnBook = useMutation(async(bookListId)=> {
const option = {
params: {
userId: queryClient.getQueryData("principal").data.userId
},
headers: {
Authorization: localStorage.getItem("accessToken")
}
}
return await axios.delete(`http://localhost:8080/book/rental/${bookListId}`,option);
},{
onSuccess: () => {
queryClient.invalidateQueries("getRentalList");
}
});
if(getRentalList.isLoading) {
return <div>불러오는 중...</div>
}
return (
<>
<table css={table}>
<thead>
<tr>
<th css={thAndTd}>도서번호</th>
<th css={thAndTd}>도서명</th>
<th css={thAndTd}>상태</th>
</tr>
</thead>
<tbody>
{getRentalList.data.data.map(rentalData => {
// Compare key values and Rerendering
return (<tr key={rentalData.bookListId}>
<td css={thAndTd}>{rentalData.bookListId}</td>
<td css={thAndTd}>{rentalData.bookName}</td>
{rentalData.rentalStatus
? (<td css={thAndTd}>대여가능 <button onClick={() => {rentalBook.mutate(rentalData.bookListId)}}>대여</button></td>)
: (<td css={thAndTd}>대여중 {rentalData.userId === queryClient.getQueryData("principal").data.userId
? (<button onClick={()=>{returnBook.mutate(rentalData.bookListId)}}>반납</button>): ""}</td>)}
</tr>)
})}
</tbody>
</table>
</>
);
};
export default RentalList;
BookController
@PostMapping("/book/rental/{bookListId}")
public ResponseEntity<?> rentalBook(@PathVariable int bookListId,@RequestBody Map<String, Integer> requestMap){
return ResponseEntity.ok().body(bookService.rentalBook(bookListId, requestMap.get("userId")));
}
@DeleteMapping("/book/rental/{bookListId}")
public ResponseEntity<?> returnBook(@PathVariable int bookListId, int userId){
return ResponseEntity.ok().body(bookService.returnBook(bookListId, userId));
}
BookRepository (rental, return 추가)
public int rentalBook(Map<String, Object> map);
public int returnBook(Map<String, Object> map);
BookMapper.xml (rental, return 추가)
<insert id="rentalBook">
insert into book_rental_tb
values (0, #{bookListId}, #{userId})
</insert>
<insert id="returnBook">
delete
from
book_rental_tb
where
book_list_id = #{bookListId}
and user_id = #{userId}
</insert>
BookService (rental, return Book 추가)
public int rentalBook(int bookListId,int userId) {
Map<String, Object> map = new HashMap<>();
map.put("bookListId", bookListId);
map.put("userId", userId);
return bookRepository.rentalBook(map);
}
public int returnBook(int bookListId,int userId) {
Map<String, Object> map = new HashMap<>();
map.put("bookListId", bookListId);
map.put("userId", userId);
return bookRepository.returnBook(map);
}