[ 작업한 내용 ]
# Frontend
1. 리뷰 내역 페이지에서 리뷰 전체 목록 조회 API 연결
// 리뷰 전체 api
const fetchBookReview = async (page, size) => {
setLoading(true);
setError(null);
try {
const response = await axios.get(
`http://localhost:8080/api/v1/user/me/reviews`,
{
params: {
page: page,
size: size,
},
withCredentials: true,
headers: {
Accept: "application/json",
}
}
);
console.log(response.data.data);
setData(response.data.data.content);
} catch (error) {
console.log("Error: ", error.response);
setError(error.response);
} finally {
console.log("리뷰 전체 목록 조회 완료");
setLoading(false);
}
}
{/* 대출 내역 items */}
{!loading && !error && (
<>
{data.map((review) => (
<div
key={review.id}
className="flex flex-col w-full border border-gray-200 p-3 mb-2"
>
<div className="flex flex-row w-full overflow-hidden">
{/* 썸네일 */}
<div className="flex w-[100px] min-w-[100px] items-start shrink-0">
<img src="https://placehold.co/420x600" alt="" className="w-auto block h-auto" />
</div>
{/* 텍스트 */}
<div className="flex flex-col justify-start self-start w-full min-w-0 leading-6 text-[15px] ml-2 text-gray-700">
<div className="font-bold text-black">{review.bookTitle}</div>
<div>작성일: {review.createdDate.split('T').join(" ")}</div>
<div className="flex flex-row w-full mt-2 leading-6 overflow-hidden items-center">
<div className="min-w-0 px-2 py-1 h-[82px] border border-gray-300 line-clamp-3">
{review.content}
</div>
<div className="flex flex-col self-end ml-2">
<button className="mb-2 px-3 py-2 border border-gray-300 leading-none whitespace-nowrap">수정</button>
<button className="px-3 py-2 border border-gray-300 leading-none whitespace-nowrap">삭제</button>
</div>
</div>
</div>
{/* <div className="border flex-1 text-[15px]">
<button className="border border-gray-500 px-2 py-3 leading-none">수정</button>
<button className="border border-gray-500 px-2 py-3 leading-none">삭제</button>
</div> */}
</div>
</div>
))}
</>
)}
2. 리뷰내역 정보 ui 작업 및 페이징 기능 추가
// 이전 페이지
const handlePrev = () => {
if (page > 0) {
setPage(page - 1);
fetchBookReview(currentFilter, page - 1);
}
}
// 다음 페이지
const handleNext = () => {
if (page < totalPages - 1) {
setPage(page + 1);
fetchBookReview(currentFilter, page + 1);
}
}
// 페이지 번호
const handlePageClick = (pageNumber) => {
setPage(pageNumber);
}
{/* 페이징 */}
<div className="mt-2">
<button
onClick={ handlePrev }
disabled={page === 0 || totalPages === 0}
className="px-3 py-1 cursor-pointer disabled:opacity-50"
>이전</button>
{[...Array(totalPages)].map((_, i) => (
<button
key={i}
onClick={() => handlePageClick(i)}
className={`px-[10px] py-[6px] mx-[3px] text-base cursor-pointer ${
i === page ? "text-teal-600 font-bold" : ""
}`}
>{i + 1}</button>
))}
<button
onClick={ handleNext }
disabled={page === totalPages - 1 || totalPages === 0}
className="px-3 py-1 cursor-pointer disabled:opacity-50"
>이후</button>
</div>
3. 특정 리뷰 클릭 시 모달창으로 상세내용 처리
- tailwind에서 제공하는 modal 사용
<div class="flex flex-col w-full mt-3 text-center sm:mt-0 sm:text-left">
<h3 id="dialog-title" class="text-base font-semibold text-gray-900">리뷰 상세</h3>
{/* 내용 */}
<div class="flex flex-col items-start mt-2">
{/* 도서정보 */}
<div class="flex flex-row items-start text-sm text-gray-500">
{/* 썸네일 */}
<div className="flex w-[100px] min-w-[100px] items-start shrink-0">
<img src="https://placehold.co/420x600" alt="" className="w-auto block h-auto" />
</div>
<div className="flex flex-col justify-start self-start w-full min-w-0 leading-6 text-[15px] ml-2 text-gray-700">
<div className="font-bold text-black">책제목</div>
<div className="text-black">저자</div>
<div className="text-black">출판사</div>
<div className="text-black">출판일</div>
<div className="text-black">ISBN</div>
</div>
</div>
{/* 리뷰내용 */}
<div className="flex flex-row w-full mt-2 leading-6 overflow-hidden items-center">
<div className="w-full min-w-0 px-2 py-1 h-[82px] border border-gray-200 rounded line-clamp-3">
리뷰내용
</div>
</div>
</div>
</div>
<div class="px-4 pb-7 sm:pb-5 sm:flex sm:flex-row-reverse sm:px-6">
<button
type="button" command="close" commandfor={id}
class="
inline-flex w-full justify-center rounded-md
bg-teal-600 hover:bg-teal-700
text-sm font-semibold text-white shadow-xs
px-3 py-2 sm:ml-3 sm:w-auto
"
>변경</button>
<button type="button" command="close" commandfor={id} class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto">취소</button>
</div>
4. 본인 작성 리뷰 전체 목록과 상세 조회 시 응답 DTO 필드 수정
- 리뷰 전체 목록 응답 DTO
public class UserReviewListResDTO {
private Long id;
private String bookTitle;
private String content;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
public UserReviewListResDTO(Review review) {
this.id = review.getId();
this.bookTitle = review.getBook().getTitle();
this.content = review.getContent();
this.createdDate = review.getCreatedDate();
this.updatedDate = review.getUpdatedDate();
}
}
- 리뷰 상세 응답 DTO
public class UserReviewDetailResDTO {
private Long id;
private String bookTitle;
private String author;
private String publisher;
private LocalDate publishedDate;
private String isbn;
private String content;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
public UserReviewDetailResDTO(Review review) {
this.id = review.getId();
this.bookTitle = review.getBook().getTitle();
this.author = review.getBook().getAuthor();
this.publisher = review.getBook().getPublisher();
this.publishedDate = review.getBook().getPublishedDate();
this.isbn = review.getBook().getIsbn();
this.content = review.getContent();
this.createdDate = review.getCreatedDate();
this.updatedDate = review.getUpdatedDate();
}
}
5. 리뷰내역 수정 API 연결
- 리뷰 수정 API
// 리뷰 수정 api
const fetchUpdateReview = async () => {
try {
const response = await axios.patch(
`http://localhost:8080/api/v1/user/me/reviews/${reviewId}`,
{ content: updateReview, },
{ withCredentials: true, }
);
console.log("리뷰 수정 성공");
alert("리뷰 수정 성공했습니다.");
return response;
} catch (error) {
console.log("Error: ", error.response);
setError(error.response);
} finally {
console.log("리뷰 수정 완료");
}
}
- 닫기 버튼 클릭 시 리뷰 이전 내용 저장
// 닫기 버튼
const handleClose = () => {
setUpdateReview(originReview);
}
- 리뷰 후 수정 버튼 클릭 시 DB에 내용 저장 및 리뷰 전체 목록 새로고침
// 리뷰 수정 버튼
const handleUpdateReview = async () => {
await fetchUpdateReview();
await fetchBookReview();
document.getElementById(id)?.close();
}
