From 32b11944b2da74dc60c87f7991679f136dc6405f Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 17:10:59 +0900 Subject: [PATCH 01/18] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20api=20=EC=B6=94=EA=B0=80=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/api/review.ts | 5 +++++ src/features/reviews/api/reviewDev.ts | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/features/reviews/api/review.ts b/src/features/reviews/api/review.ts index 3cc62062..df8ac092 100644 --- a/src/features/reviews/api/review.ts +++ b/src/features/reviews/api/review.ts @@ -30,6 +30,11 @@ export default class ReviewApi { return post("/short-reviews", review); } + /** @description 리뷰 수정 요청 */ + async updateReview(reviewId: number, review: AddReviewDto) { + return patch(`/short-reviews/${reviewId}`, review); + } + /** @description 한 애니의 리뷰 목록 요청 */ async getAnimeReviews( animeId: number, diff --git a/src/features/reviews/api/reviewDev.ts b/src/features/reviews/api/reviewDev.ts index 3766ea5b..eccb84a8 100644 --- a/src/features/reviews/api/reviewDev.ts +++ b/src/features/reviews/api/reviewDev.ts @@ -18,6 +18,11 @@ export default class ReviewDevApi { return post("/short-reviews", review); } + /** @description 리뷰 수정 요청 */ + async updateReview(reviewId: number, review: AddReviewDto) { + return patch(`/short-reviews/${reviewId}`, review); + } + /** @description 한 애니의 리뷰 목록 요청*/ async getAnimeReviews( animeId: number, From f3692c75c1c09f178f0a83c7d454e9bcd5eb2816 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 17:18:07 +0900 Subject: [PATCH 02/18] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=9D=84=20=EC=9C=84=ED=95=B4=20ActionBar,=20MoreButt?= =?UTF-8?q?on=EC=97=90=20=EB=A6=AC=EB=B7=B0=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20props=20=EC=B6=94=EA=B0=80=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../animes/routes/Detail/Reviews/index.tsx | 5 +++++ .../components/ReviewCard/ActionBar.tsx | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/features/animes/routes/Detail/Reviews/index.tsx b/src/features/animes/routes/Detail/Reviews/index.tsx index 6cdfcd61..15a616c1 100644 --- a/src/features/animes/routes/Detail/Reviews/index.tsx +++ b/src/features/animes/routes/Detail/Reviews/index.tsx @@ -72,6 +72,11 @@ export default function Reviews({ isLike={review.isLike} likeCount={review.likeCount} createdAt={review.createdAt} + reviewId={review.reviewId} + animeId={review.animeId} + isSpoiler={review.isSpoiler} + content={review.content} + score={review.score} /> diff --git a/src/features/reviews/components/ReviewCard/ActionBar.tsx b/src/features/reviews/components/ReviewCard/ActionBar.tsx index df5bdd90..6032bb4b 100644 --- a/src/features/reviews/components/ReviewCard/ActionBar.tsx +++ b/src/features/reviews/components/ReviewCard/ActionBar.tsx @@ -10,6 +10,11 @@ export interface ActionBarProps { likeCount: number; createdAt?: string; isTimeAgo?: boolean; + reviewId: number; + animeId: number; + content: string; + isSpoiler: boolean; + score: number; } export default function ActionBar({ isMine, @@ -17,6 +22,11 @@ export default function ActionBar({ likeCount, createdAt, isTimeAgo, + reviewId, + animeId, + content, + isSpoiler, + score, }: ActionBarProps) { const date = isTimeAgo ? timeAgo(createdAt) : dateWithDots(createdAt); @@ -29,7 +39,14 @@ export default function ActionBar({ count={compactNumber(likeCount, "ko-KR")} onClick={() => {}} /> - + ); From f1b5bf68785cf027281a61fca0a1b49612e13ab4 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 17:19:53 +0900 Subject: [PATCH 03/18] =?UTF-8?q?feat:=20ShortReviewModal=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=95=84=EC=9D=B4=EB=94=94=20props=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reviews/components/ReviewRating/ShortReviewModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/reviews/components/ReviewRating/ShortReviewModal.tsx b/src/features/reviews/components/ReviewRating/ShortReviewModal.tsx index 596ebfbd..9a8843dc 100644 --- a/src/features/reviews/components/ReviewRating/ShortReviewModal.tsx +++ b/src/features/reviews/components/ReviewRating/ShortReviewModal.tsx @@ -16,7 +16,7 @@ import { import SpoilerCheckBox from "./SpoilerCheckBox"; export interface MOCK_USER_REVIEW_DATA { - id: number; + reviewId: number; animeId: number; content: string; isSpoiler: boolean; From bb92d977b1e778f2960850407836048fe8f89fe3 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 17:21:54 +0900 Subject: [PATCH 04/18] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20mutation=20=EC=B6=94=EA=B0=80=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/hook/useAddReview.ts | 24 --------- src/features/reviews/hook/useReview.ts | 61 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 24 deletions(-) delete mode 100644 src/features/reviews/hook/useAddReview.ts create mode 100644 src/features/reviews/hook/useReview.ts diff --git a/src/features/reviews/hook/useAddReview.ts b/src/features/reviews/hook/useAddReview.ts deleted file mode 100644 index 9bdd61f8..00000000 --- a/src/features/reviews/hook/useAddReview.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useMutation, useQueryClient } from "@tanstack/react-query"; - -import useAuth from "@/features/auth/hooks/useAuth"; -import { useApi } from "@/hooks/useApi"; - -import { AddReviewDto } from "../api/review"; - -export default function useAddReview(animeId: number, onReview: () => void) { - const queryClient = useQueryClient(); - const { reviewApi } = useApi(); - const { user } = useAuth(); - - return useMutation({ - mutationFn: (review: AddReviewDto) => reviewApi.addReview(review), - onSuccess: () => { - queryClient.invalidateQueries(["profile", user?.name]); - queryClient.invalidateQueries(["profile", user?.memberId, "review"]); - queryClient.invalidateQueries(["review", animeId, user?.memberId]); - queryClient.invalidateQueries(["anime", animeId, user?.memberId]); - // TODO: 최신 리뷰 목록 query 무효화 - onReview(); - }, - }); -} diff --git a/src/features/reviews/hook/useReview.ts b/src/features/reviews/hook/useReview.ts new file mode 100644 index 00000000..cc84e813 --- /dev/null +++ b/src/features/reviews/hook/useReview.ts @@ -0,0 +1,61 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { AxiosError } from "axios"; + +import useAuth from "@/features/auth/hooks/useAuth"; +import { useApi } from "@/hooks/useApi"; +import { useCommonToastError } from "@/libs/error"; + +import { AddReviewDto } from "../api/review"; + +export default function useReview(animeId: number, onReview: () => void) { + const queryClient = useQueryClient(); + const { reviewApi } = useApi(); + const { user } = useAuth(); + + const { toastAuthError, toastDefaultError } = useCommonToastError(); + + const handleError = (error: unknown) => { + if (error instanceof AxiosError && error.response?.status) { + const status = error.response.status; + if ([401, 403].includes(status)) { + toastAuthError(); + } else if (status >= 500) { + toastDefaultError(); + } + } + }; + + // 리뷰 추가 + const addReview = useMutation({ + mutationFn: (review: AddReviewDto) => reviewApi.addReview(review), + onSuccess: () => { + queryClient.invalidateQueries(["profile", user?.name]); + queryClient.invalidateQueries(["profile", user?.memberId, "review"]); + queryClient.invalidateQueries(["review", animeId, user?.memberId]); + queryClient.invalidateQueries(["anime", animeId, user?.memberId]); + // TODO: 최신 리뷰 목록 query 무효화 + onReview(); + }, + onError: (error) => handleError(error), + }); + + // 리뷰 수정 + const updateReview = useMutation({ + mutationFn: ({ + reviewId, + review, + }: { + reviewId: number; + review: AddReviewDto; + }) => reviewApi.updateReview(reviewId, review), + onSuccess: () => { + queryClient.invalidateQueries(["profile", user?.memberId, "review"]); + queryClient.invalidateQueries(["review", animeId, user?.memberId]); + // TODO: 최신 리뷰 목록 query 무효화 + onReview(); + }, + onError: (error) => handleError(error), + }); + + return { addReview, updateReview }; +} From 571fc509196d2e45c57a52a5ccefaa2676e00013 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 17:22:25 +0900 Subject: [PATCH 05/18] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B5=AC=ED=98=84=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReviewCard/ReviewMoreButton.tsx | 63 ++++++++++----- src/features/reviews/hook/useReviewForm.tsx | 81 +++++++++++-------- 2 files changed, 91 insertions(+), 53 deletions(-) diff --git a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx index ceaa1b49..9fa69abe 100644 --- a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx +++ b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx @@ -6,9 +6,11 @@ import { useState } from "react"; import BackdropPortal from "@/components/Backdrop/BackdropPortal"; import Rating from "@/components/Rating"; import useSnackBar from "@/components/SnackBar/useSnackBar"; +import useToast from "@/components/Toast/useToast"; import DropDownModal from "@/features/users/components/DropDownModal"; import useDropDownModal from "@/features/users/components/DropDownModal/useDropDownModal"; +import useEvaluation from "../../hook/useEvaluation"; import ShortReviewModal from "../ReviewRating/ShortReviewModal"; import { @@ -17,12 +19,8 @@ import { RatingContainer, } from "./ReviewMoreButton.style"; -const USER_MOCK_REVIEW_DATA = { - id: 1, - animeId: 1, - score: 7, - content: "유저가 생성한 짧은 리뷰입니다.", - isSpoiler: true, +// TODO: 서버에서 가져오기 +const USER_MOCK_ATTRACTION = { character: true, art: true, story: false, @@ -32,37 +30,58 @@ const USER_MOCK_REVIEW_DATA = { interface ReviewMoreButtonProps { isMine: boolean; + reviewId: number; + animeId: number; + content: string; + isSpoiler: boolean; + score: number; } -export default function ReviewMoreButton({ isMine }: ReviewMoreButtonProps) { +export default function ReviewMoreButton({ + isMine, + reviewId, + animeId, + content, + score, + isSpoiler, +}: ReviewMoreButtonProps) { const theme = useTheme(); const { isDropDownModalOpen, handleDropDownModalToggle } = useDropDownModal(); const snackBar = useSnackBar(); const [isReviewModalVisible, setIsReviewModalVisible] = useState(false); + + const { evaluationMutation } = useEvaluation(animeId); + + const toast = useToast(); + const handleReviewModalToggle = () => setIsReviewModalVisible((prev) => !prev); + const handleReviewEditClick = () => { handleDropDownModalToggle(); handleReviewModalToggle(); - // setIsReviewModalVisible(true); }; + const handleRate = (value: number) => { - // if (!user) { - // setIsLoginModalVisible(true); - // return; - // } - // TODO: 점수 등록 요청하기 + evaluationMutation.mutate(value, { + onSuccess: () => { + toast.success({ message: "별점이 수정되었어요." }); + }, + }); console.log(value); }; + const handleReviewDeleteClick = () => console.log("리뷰삭제"); + const handleReviewSpoilerReport = () => { handleDropDownModalToggle(); - snackBar.open({ message: "신고가 접수되었습니다." }); + snackBar.open({ message: "신고가 접수되었어요." }); }; + const handleReviewEtcReport = () => { handleDropDownModalToggle(); snackBar.open({ - message: "신고가 접수되었습니다.", + message: "신고가 접수되었어요.", }); }; @@ -123,15 +142,17 @@ export default function ReviewMoreButton({ isMine }: ReviewMoreButtonProps) { onClose={() => setIsReviewModalVisible(false)} onReview={() => setIsReviewModalVisible(false)} showBackdrop={false} - userReviewData={USER_MOCK_REVIEW_DATA} + userReviewData={{ + reviewId, + animeId, + content, + isSpoiler, + ...USER_MOCK_ATTRACTION, + }} > 내 별점 - + )} diff --git a/src/features/reviews/hook/useReviewForm.tsx b/src/features/reviews/hook/useReviewForm.tsx index cb62c75b..cfa899a2 100644 --- a/src/features/reviews/hook/useReviewForm.tsx +++ b/src/features/reviews/hook/useReviewForm.tsx @@ -1,14 +1,12 @@ -import { AxiosError } from "axios"; import { useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import useToast from "@/components/Toast/useToast"; import useAuth from "@/features/auth/hooks/useAuth"; -import { useCommonToastError } from "@/libs/error"; import { MOCK_USER_REVIEW_DATA } from "../components/ReviewRating/ShortReviewModal"; -import useAddReview from "./useAddReview"; +import useReview from "./useReview"; export default function useReviewForm( onReview: () => void, @@ -19,10 +17,9 @@ export default function useReviewForm( const animeId = userReviewData?.animeId ?? Number(pathname.split("/")[2]); const { user } = useAuth(); - const reviewMutation = useAddReview(animeId, onReview); + const { addReview, updateReview } = useReview(animeId, onReview); const toast = useToast(); - const { toastAuthError, toastDefaultError } = useCommonToastError(); const [form, setForm] = useState({ content: userReviewData?.content ?? "", @@ -60,6 +57,7 @@ export default function useReviewForm( setError(true); return; } + // console.log(form); console.log({ name: user?.name, @@ -67,35 +65,54 @@ export default function useReviewForm( isSpoiler: form.isSpoiler, content: form.content, }); - // TODO: 새 리뷰 작성인지 수정인지 검사 - // 새 리뷰 작성 POST 요청 - reviewMutation.mutate( - { - name: user?.name ?? "", - animeId, - hasSpoiler: form.isSpoiler, - content: form.content, - }, - { - onSuccess: () => { - toast.success({ - message: "리뷰가 등록되었어요.", - buttonText: "내 모든 리뷰 보러 가기", - onClickButton: () => navigate("/profile"), - }); + + // 리뷰 수정 + if (userReviewData) { + // 내용에 변화가 있을 경우에만 요청 + if ( + userReviewData.content !== form.content || + userReviewData.isSpoiler !== form.isSpoiler + ) + updateReview.mutate( + { + reviewId: userReviewData.reviewId, + review: { + name: user?.name ?? "", + animeId, + hasSpoiler: form.isSpoiler, + content: form.content, + }, + }, + { + onSuccess: () => { + toast.success({ + message: "리뷰가 수정되었어요.", + }); + }, + }, + ); + // 모달 닫기 + else onReview(); + } else { + // 리뷰 추가 + addReview.mutate( + { + name: user?.name ?? "", + animeId, + hasSpoiler: form.isSpoiler, + content: form.content, }, - onError: (error) => { - if (error instanceof AxiosError && error.response?.status) { - const status = error.response.status; - if ([401, 403].includes(status)) { - toastAuthError(); - } else if (status >= 500) { - toastDefaultError(); - } - } + { + onSuccess: () => { + toast.success({ + message: "리뷰가 등록되었어요.", + buttonText: "내 모든 리뷰 보러 가기", + onClickButton: () => navigate("/profile"), + }); + }, }, - }, - ); + ); + } }; return { From 86f3af9150c14aa194fa385bd2e938e47ac62a5f Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 18:02:13 +0900 Subject: [PATCH 06/18] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=ED=83=80=EC=9E=85=EC=97=90=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EB=94=94,=20score=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/types/index.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/features/reviews/types/index.d.ts b/src/features/reviews/types/index.d.ts index 35a10d0e..7a72bab6 100644 --- a/src/features/reviews/types/index.d.ts +++ b/src/features/reviews/types/index.d.ts @@ -1,5 +1,7 @@ declare interface Review { + reviewId: number; name: string; + score: number; content: string; isSpoiler: boolean; isLike: boolean; From ca70371c15644c596d575ca3e3ea5e7650c2a33f Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 18:03:14 +0900 Subject: [PATCH 07/18] =?UTF-8?q?refactor:=20review=20mock=20data=EC=97=90?= =?UTF-8?q?=20reviewId,=20score=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reviews/api/mock/recentReview1.json | 20 +++++++++++++++++++ .../reviews/api/mock/recentReview2.json | 20 +++++++++++++++++++ .../reviews/api/mock/recentReview3.json | 20 +++++++++++++++++++ .../reviews/api/mock/recentReviewOnlyOne.json | 2 ++ src/features/users/api/mock/review1.json | 20 +++++++++++++++++++ src/features/users/api/mock/review2.json | 20 +++++++++++++++++++ src/features/users/api/mock/review3.json | 20 +++++++++++++++++++ 7 files changed, 122 insertions(+) diff --git a/src/features/reviews/api/mock/recentReview1.json b/src/features/reviews/api/mock/recentReview1.json index 34958742..a225efbc 100644 --- a/src/features/reviews/api/mock/recentReview1.json +++ b/src/features/reviews/api/mock/recentReview1.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 10, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -15,7 +17,9 @@ } }, { + "reviewId": 9, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 8, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 7, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 6, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 5, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 4, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 3, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 2, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 1, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, diff --git a/src/features/reviews/api/mock/recentReview2.json b/src/features/reviews/api/mock/recentReview2.json index 8cdabf8d..3fe8c601 100644 --- a/src/features/reviews/api/mock/recentReview2.json +++ b/src/features/reviews/api/mock/recentReview2.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 20, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -15,7 +17,9 @@ } }, { + "reviewId": 19, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 18, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 17, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 16, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 15, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 14, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 13, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 12, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 11, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, diff --git a/src/features/reviews/api/mock/recentReview3.json b/src/features/reviews/api/mock/recentReview3.json index f177186e..763a1ec8 100644 --- a/src/features/reviews/api/mock/recentReview3.json +++ b/src/features/reviews/api/mock/recentReview3.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 30, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다. 리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다. 리뷰 입니다. 리뷰 입니다. 리뷰 입니다.", "isSpoiler": true, "isLike": false, @@ -15,7 +17,9 @@ } }, { + "reviewId": 29, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 28, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 27, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 26, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 25, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 24, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 23, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 22, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 21, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, diff --git a/src/features/reviews/api/mock/recentReviewOnlyOne.json b/src/features/reviews/api/mock/recentReviewOnlyOne.json index d125e52b..3f1cb1a3 100644 --- a/src/features/reviews/api/mock/recentReviewOnlyOne.json +++ b/src/features/reviews/api/mock/recentReviewOnlyOne.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 10, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": false, diff --git a/src/features/users/api/mock/review1.json b/src/features/users/api/mock/review1.json index 34958742..a225efbc 100644 --- a/src/features/users/api/mock/review1.json +++ b/src/features/users/api/mock/review1.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 10, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -15,7 +17,9 @@ } }, { + "reviewId": 9, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 8, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 7, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 6, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 5, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 4, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 3, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 2, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 1, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, diff --git a/src/features/users/api/mock/review2.json b/src/features/users/api/mock/review2.json index 8cdabf8d..3fe8c601 100644 --- a/src/features/users/api/mock/review2.json +++ b/src/features/users/api/mock/review2.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 20, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -15,7 +17,9 @@ } }, { + "reviewId": 19, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 18, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 17, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 16, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 15, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 14, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 13, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 12, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 11, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, diff --git a/src/features/users/api/mock/review3.json b/src/features/users/api/mock/review3.json index f177186e..763a1ec8 100644 --- a/src/features/users/api/mock/review3.json +++ b/src/features/users/api/mock/review3.json @@ -1,7 +1,9 @@ { "items": [ { + "reviewId": 30, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다. 리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다.리뷰 입니다. 리뷰 입니다. 리뷰 입니다. 리뷰 입니다.", "isSpoiler": true, "isLike": false, @@ -15,7 +17,9 @@ } }, { + "reviewId": 29, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -29,7 +33,9 @@ } }, { + "reviewId": 28, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -43,7 +49,9 @@ } }, { + "reviewId": 27, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -57,7 +65,9 @@ } }, { + "reviewId": 26, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -71,7 +81,9 @@ } }, { + "reviewId": 25, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -85,7 +97,9 @@ } }, { + "reviewId": 24, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -99,7 +113,9 @@ } }, { + "reviewId": 23, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -113,7 +129,9 @@ } }, { + "reviewId": 22, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, @@ -127,7 +145,9 @@ } }, { + "reviewId": 21, "name": "faberjoo", + "score": 7, "content": "리뷰 입니다.", "isSpoiler": false, "isLike": true, From f7b922e708c0cca6359fcabc8e8f108d17c450ae Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 18:03:57 +0900 Subject: [PATCH 08/18] =?UTF-8?q?refactor:=20ReviewInfo=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/api/review.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/features/reviews/api/review.ts b/src/features/reviews/api/review.ts index df8ac092..57650bf2 100644 --- a/src/features/reviews/api/review.ts +++ b/src/features/reviews/api/review.ts @@ -8,10 +8,8 @@ import recentReviewMock3 from "./mock/recentReview3.json"; import recentReviewOnlyOneMock from "./mock/recentReviewOnlyOne.json"; export type ReviewInfo = Omit & { - reviewId: number; animeId: number; thumbnail: string; - score: number; }; export type AddReviewDto = Pick & { From fa96c5517041b409bb4477c6df56205c6988d27f Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 18:04:57 +0900 Subject: [PATCH 09/18] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=AA=A9=EB=A1=9D,=20=EC=B5=9C=EA=B7=BC?= =?UTF-8?q?=20=ED=95=9C=EC=A4=84=EB=A6=AC=EB=B7=B0=20ActionBar=EC=97=90=20?= =?UTF-8?q?review=20=EA=B4=80=EB=A0=A8=20props=20=EC=B6=94=EA=B0=80=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/common/routes/Home/RecentReview/index.tsx | 5 +++++ src/features/users/routes/Profile/TabMenu/ReviewList.tsx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/features/common/routes/Home/RecentReview/index.tsx b/src/features/common/routes/Home/RecentReview/index.tsx index 11fe27b9..0cbe9318 100644 --- a/src/features/common/routes/Home/RecentReview/index.tsx +++ b/src/features/common/routes/Home/RecentReview/index.tsx @@ -49,6 +49,11 @@ export default function RecentReview() { isLike={data.pages[0].isLike} likeCount={data.pages[0].likeCount} isTimeAgo={true} + reviewId={data.pages[0].reviewId} + animeId={data.pages[0].anime.animeId} + isSpoiler={data.pages[0].isSpoiler} + content={data.pages[0].content} + score={data.pages[0].score} /> )} diff --git a/src/features/users/routes/Profile/TabMenu/ReviewList.tsx b/src/features/users/routes/Profile/TabMenu/ReviewList.tsx index c2b53c4d..942c2327 100644 --- a/src/features/users/routes/Profile/TabMenu/ReviewList.tsx +++ b/src/features/users/routes/Profile/TabMenu/ReviewList.tsx @@ -37,6 +37,11 @@ export default function ReviewList({ isMine, list }: ReviewListProps) { isMine={isMine} isLike={review.isLike} likeCount={review.likeCount} + reviewId={review.reviewId} + animeId={review.anime.animeId} + isSpoiler={review.isSpoiler} + content={review.content} + score={review.score} /> ))} From e8e0460e9dc8d1777f30cc254b31ebb9d97fb05c Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 19:10:15 +0900 Subject: [PATCH 10/18] =?UTF-8?q?refactor:=20=ED=8F=89=EC=A0=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C,=20=ED=8F=89=EC=A0=90=20=EC=B6=94=EA=B0=80/?= =?UTF-8?q?=EC=88=98=EC=A0=95=20hook=20=EB=B6=84=EB=A6=AC=20#286?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불필요한 조회가 일어나지 않도록 분리 --- src/features/reviews/hook/useEvaluation.ts | 27 +++++++------------ src/features/reviews/hook/useGetEvaluation.ts | 20 ++++++++++++++ 2 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 src/features/reviews/hook/useGetEvaluation.ts diff --git a/src/features/reviews/hook/useEvaluation.ts b/src/features/reviews/hook/useEvaluation.ts index 82cdc993..79dbfd0b 100644 --- a/src/features/reviews/hook/useEvaluation.ts +++ b/src/features/reviews/hook/useEvaluation.ts @@ -1,4 +1,4 @@ -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; import { AxiosError } from "axios"; import useAuth from "@/features/auth/hooks/useAuth"; @@ -12,20 +12,15 @@ export default function useEvaluation(animeId: number) { const { toastAuthError, toastDefaultError } = useCommonToastError(); - const { data } = useQuery({ - queryKey: ["evaluation", animeId, user?.memberId], - queryFn: async () => { - try { - return await reviewApi.getEvaluation(animeId); - } catch (e) { - return null; - } - }, - }); - - const evaluationMutation = useMutation({ - mutationFn: (score: number) => { - if (!data) return reviewApi.addEvaluation(animeId, score); + return useMutation({ + mutationFn: ({ + score, + hasPrevData = true, + }: { + score: number; + hasPrevData?: boolean; + }) => { + if (!hasPrevData) return reviewApi.addEvaluation(animeId, score); return reviewApi.updateEvaluation(animeId, score); }, onSuccess: () => { @@ -48,6 +43,4 @@ export default function useEvaluation(animeId: number) { } }, }); - - return { data, evaluationMutation }; } diff --git a/src/features/reviews/hook/useGetEvaluation.ts b/src/features/reviews/hook/useGetEvaluation.ts new file mode 100644 index 00000000..c28a1d97 --- /dev/null +++ b/src/features/reviews/hook/useGetEvaluation.ts @@ -0,0 +1,20 @@ +import { useQuery } from "@tanstack/react-query"; + +import useAuth from "@/features/auth/hooks/useAuth"; +import { useApi } from "@/hooks/useApi"; + +export default function useGetEvaluation(animeId: number) { + const { reviewApi } = useApi(); + const { user } = useAuth(); + + return useQuery({ + queryKey: ["evaluation", animeId, user?.memberId], + queryFn: async () => { + try { + return await reviewApi.getEvaluation(animeId); + } catch (e) { + return null; + } + }, + }); +} From b690ccee355e65c27438960d49816be4803a5bdd Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 19:16:13 +0900 Subject: [PATCH 11/18] =?UTF-8?q?refactor:=20=ED=8F=89=EA=B0=80=20hook=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20#286?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ReviewCard/ReviewMoreButton.tsx | 13 ++++++++----- .../reviews/components/ReviewRating/index.tsx | 10 ++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx index 9fa69abe..fda608db 100644 --- a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx +++ b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx @@ -50,7 +50,7 @@ export default function ReviewMoreButton({ const snackBar = useSnackBar(); const [isReviewModalVisible, setIsReviewModalVisible] = useState(false); - const { evaluationMutation } = useEvaluation(animeId); + const evaluationMutation = useEvaluation(animeId); const toast = useToast(); @@ -63,11 +63,14 @@ export default function ReviewMoreButton({ }; const handleRate = (value: number) => { - evaluationMutation.mutate(value, { - onSuccess: () => { - toast.success({ message: "별점이 수정되었어요." }); + evaluationMutation.mutate( + { score: value }, + { + onSuccess: () => { + toast.success({ message: "별점이 수정되었어요." }); + }, }, - }); + ); console.log(value); }; diff --git a/src/features/reviews/components/ReviewRating/index.tsx b/src/features/reviews/components/ReviewRating/index.tsx index f549a57b..ef48a8a6 100644 --- a/src/features/reviews/components/ReviewRating/index.tsx +++ b/src/features/reviews/components/ReviewRating/index.tsx @@ -7,6 +7,7 @@ import useAuth from "@/features/auth/hooks/useAuth"; import useDebounce from "@/hooks/useDebounce"; import useEvaluation from "../../hook/useEvaluation"; +import useGetEvaluation from "../../hook/useGetEvaluation"; import ShortReviewModal from "./ShortReviewModal"; import { ReviewRecommend } from "./style"; @@ -24,7 +25,8 @@ export default function ReviewRating({ animeId }: ReviewRatingProps) { const [isLoginModalVisible, setIsLoginModalVisible] = useState(false); const [isReviewModalVisible, setIsReviewModalVisible] = useState(false); - const { data: evaluation, evaluationMutation } = useEvaluation(animeId); + const { data: evaluation } = useGetEvaluation(animeId); + const evaluationMutation = useEvaluation(animeId); const handleRate = useDebounce((value: number) => { if (!user) { @@ -32,7 +34,11 @@ export default function ReviewRating({ animeId }: ReviewRatingProps) { return; } // 평가 추가 또는 기존과 다른 점수로 평가 수정 시에만 요청 수행 - if (evaluation?.score !== value) evaluationMutation.mutate(value); + if (evaluation?.score !== value) + evaluationMutation.mutate({ + score: value, + hasPrevData: Boolean(evaluation), + }); }, DEBOUNCE_DELAY); return ( From 6010e23a2ef1a4a0eebb5d956a9bf9580e534e1f Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 19:22:23 +0900 Subject: [PATCH 12/18] =?UTF-8?q?refactor:=20=ED=8F=89=EC=A0=90=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20toast=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20#308?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx index fda608db..21674f90 100644 --- a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx +++ b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx @@ -67,7 +67,7 @@ export default function ReviewMoreButton({ { score: value }, { onSuccess: () => { - toast.success({ message: "별점이 수정되었어요." }); + toast.success({ message: "평점이 수정되었어요." }); }, }, ); From 0c14ab7275a702cc1f7655a497a559036bbc1a8e Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 20:26:15 +0900 Subject: [PATCH 13/18] =?UTF-8?q?refactor:=20=ED=8F=89=EC=A0=90=20->=20?= =?UTF-8?q?=EB=B3=84=EC=A0=90=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/animes/routes/Detail/Ratings/index.tsx | 2 +- src/features/animes/routes/List/index.tsx | 2 +- .../reviews/components/ReviewCard/ReviewMoreButton.tsx | 2 +- src/features/reviews/hook/useGetAnimeReviews.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/features/animes/routes/Detail/Ratings/index.tsx b/src/features/animes/routes/Detail/Ratings/index.tsx index b8cd3340..383043f6 100644 --- a/src/features/animes/routes/Detail/Ratings/index.tsx +++ b/src/features/animes/routes/Detail/Ratings/index.tsx @@ -17,7 +17,7 @@ import { export default function Ratings({ starScoreAvg }: { starScoreAvg: number }) { return (
-

평점

+

별점

diff --git a/src/features/animes/routes/List/index.tsx b/src/features/animes/routes/List/index.tsx index fd3fea5d..146206c4 100644 --- a/src/features/animes/routes/List/index.tsx +++ b/src/features/animes/routes/List/index.tsx @@ -33,7 +33,7 @@ const TabItems: TabItem[] = [ }, { id: "SCORE", - title: "평점순", + title: "별점순", }, ]; diff --git a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx index 21674f90..fda608db 100644 --- a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx +++ b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx @@ -67,7 +67,7 @@ export default function ReviewMoreButton({ { score: value }, { onSuccess: () => { - toast.success({ message: "평점이 수정되었어요." }); + toast.success({ message: "별점이 수정되었어요." }); }, }, ); diff --git a/src/features/reviews/hook/useGetAnimeReviews.ts b/src/features/reviews/hook/useGetAnimeReviews.ts index cec997ee..78dbcc95 100644 --- a/src/features/reviews/hook/useGetAnimeReviews.ts +++ b/src/features/reviews/hook/useGetAnimeReviews.ts @@ -32,12 +32,12 @@ export default function useGetAnimeReviews(animeId: number) { order: "DESC", }, { - label: "평점 높은 순", + label: "별점 높은 순", sort: "score", order: "DESC", }, { - label: "평점 낮은 순", + label: "별점 낮은 순", sort: "score", order: "ASC", }, From e77704bc21e31eb82e2abe766526a2a0ce0bdd51 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 21:11:17 +0900 Subject: [PATCH 14/18] =?UTF-8?q?feat:=20=ED=8F=89=EA=B0=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80/=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EB=A6=AC=EB=B7=B0?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20query=20=EB=AC=B4?= =?UTF-8?q?=ED=9A=A8=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사용자가 해당 애니의 리뷰를 작성한 경우에만 적용 --- src/features/reviews/hook/useEvaluation.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/features/reviews/hook/useEvaluation.ts b/src/features/reviews/hook/useEvaluation.ts index 79dbfd0b..c1b45082 100644 --- a/src/features/reviews/hook/useEvaluation.ts +++ b/src/features/reviews/hook/useEvaluation.ts @@ -5,7 +5,13 @@ import useAuth from "@/features/auth/hooks/useAuth"; import { useApi } from "@/hooks/useApi"; import { useCommonToastError } from "@/libs/error"; -export default function useEvaluation(animeId: number) { +export default function useEvaluation({ + animeId, + hasReview = true, +}: { + animeId: number; + hasReview?: boolean; +}) { const queryClient = useQueryClient(); const { reviewApi } = useApi(); const { user } = useAuth(); @@ -28,6 +34,14 @@ export default function useEvaluation(animeId: number) { queryClient.invalidateQueries(["evaluation", animeId, user?.memberId]); // 애니 평균 평점 조회 query 무효화 queryClient.invalidateQueries(["averageRating", animeId, user?.memberId]); + + // 별점 수정 대상 애니에 대한 사용자의 리뷰가 존재하는 경우에만 리뷰 목록 조회 무효화 + if (hasReview) { + queryClient.invalidateQueries(["profile", user?.memberId, "review"]); + queryClient.invalidateQueries(["review", animeId, user?.memberId]); + queryClient.invalidateQueries(["anime", animeId, user?.memberId]); + // TODO: 최신 리뷰 목록 조회 무효화 + } }, onError: (error) => { if (error instanceof AxiosError && error.response?.status) { From 451ec3c5500e149db3b38bf6c2e7b030cacfd636 Mon Sep 17 00:00:00 2001 From: mihee Date: Mon, 20 Nov 2023 21:12:09 +0900 Subject: [PATCH 15/18] =?UTF-8?q?refactor:=20useEvaluation=20props=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reviews/components/ReviewCard/ReviewMoreButton.tsx | 2 +- src/features/reviews/components/ReviewRating/index.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx index fda608db..db6ca630 100644 --- a/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx +++ b/src/features/reviews/components/ReviewCard/ReviewMoreButton.tsx @@ -50,7 +50,7 @@ export default function ReviewMoreButton({ const snackBar = useSnackBar(); const [isReviewModalVisible, setIsReviewModalVisible] = useState(false); - const evaluationMutation = useEvaluation(animeId); + const evaluationMutation = useEvaluation({ animeId }); const toast = useToast(); diff --git a/src/features/reviews/components/ReviewRating/index.tsx b/src/features/reviews/components/ReviewRating/index.tsx index ef48a8a6..ca3648c7 100644 --- a/src/features/reviews/components/ReviewRating/index.tsx +++ b/src/features/reviews/components/ReviewRating/index.tsx @@ -19,14 +19,14 @@ interface ReviewRatingProps { const DEBOUNCE_DELAY = 200; export default function ReviewRating({ animeId }: ReviewRatingProps) { - const hasReviewed = true; // dev용 변수 + const hasReview = true; // dev용 변수 const { user } = useAuth(); const [isLoginModalVisible, setIsLoginModalVisible] = useState(false); const [isReviewModalVisible, setIsReviewModalVisible] = useState(false); const { data: evaluation } = useGetEvaluation(animeId); - const evaluationMutation = useEvaluation(animeId); + const evaluationMutation = useEvaluation({ animeId, hasReview }); const handleRate = useDebounce((value: number) => { if (!user) { @@ -55,7 +55,7 @@ export default function ReviewRating({ animeId }: ReviewRatingProps) { )} - {hasReviewed && "TODO: 사용자 리뷰 렌더링 "} + {hasReview && "TODO: 사용자 리뷰 렌더링 "} {isReviewModalVisible && ( From f5ee76f6eb314d668be249c56534d12935a3fba9 Mon Sep 17 00:00:00 2001 From: mihee Date: Tue, 21 Nov 2023 17:10:42 +0900 Subject: [PATCH 16/18] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EA=B0=9C=EC=88=98,=20=EB=B6=81=EB=A7=88=ED=81=AC?= =?UTF-8?q?=20=EA=B0=9C=EC=88=98=20=EC=A1=B0=ED=9A=8C=20query=20key=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/users/routes/Profile/TabMenu/SortBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/users/routes/Profile/TabMenu/SortBar.tsx b/src/features/users/routes/Profile/TabMenu/SortBar.tsx index 681bc468..099ca89e 100644 --- a/src/features/users/routes/Profile/TabMenu/SortBar.tsx +++ b/src/features/users/routes/Profile/TabMenu/SortBar.tsx @@ -43,8 +43,8 @@ export default function SortBar({ queryKey: [ "profile", user?.memberId, - selectedMenu === "입덕애니" ? "bookmark" : "review", "count", + selectedMenu === "입덕애니" ? "bookmark" : "review", ], queryFn: () => profile.getTabListCount(user?.memberId, selectedMenu), }); From 71dcda05e05830d0fdc591a0e4bda1b2bd0c1557 Mon Sep 17 00:00:00 2001 From: mihee Date: Tue, 21 Nov 2023 17:11:39 +0900 Subject: [PATCH 17/18] =?UTF-8?q?refactor:=20=EB=B6=81=EB=A7=88=ED=81=AC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80/=EC=82=AD=EC=A0=9C=20=EB=AC=B4=ED=9A=A8?= =?UTF-8?q?=ED=99=94=20query=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 개수 조회 query 추가 --- src/features/bookmarks/hooks/useToggleBookmark.ts | 6 ++++++ .../users/routes/Profile/TabMenu/BookmarkDeleteModal.tsx | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/features/bookmarks/hooks/useToggleBookmark.ts b/src/features/bookmarks/hooks/useToggleBookmark.ts index 1a003e21..6e4652fc 100644 --- a/src/features/bookmarks/hooks/useToggleBookmark.ts +++ b/src/features/bookmarks/hooks/useToggleBookmark.ts @@ -17,6 +17,12 @@ export default function useToggleBookmark(animeId: number) { onSuccess: () => { queryClient.invalidateQueries(["profile", user?.name]); queryClient.invalidateQueries(["profile", user?.memberId, "bookmark"]); + queryClient.invalidateQueries([ + "profile", + user?.memberId, + "count", + "bookmark", + ]); queryClient.invalidateQueries(["bookmark", user?.memberId, animeId]); queryClient.invalidateQueries(["anime", animeId, user?.memberId]); }, diff --git a/src/features/users/routes/Profile/TabMenu/BookmarkDeleteModal.tsx b/src/features/users/routes/Profile/TabMenu/BookmarkDeleteModal.tsx index 6abf5d44..5158c884 100644 --- a/src/features/users/routes/Profile/TabMenu/BookmarkDeleteModal.tsx +++ b/src/features/users/routes/Profile/TabMenu/BookmarkDeleteModal.tsx @@ -41,6 +41,12 @@ export default function BookmarkDeleteModal({ onSuccess: () => { queryClient.invalidateQueries(["profile", user?.name]); queryClient.invalidateQueries(["profile", user?.memberId, "bookmark"]); + queryClient.invalidateQueries([ + "profile", + user?.memberId, + "count", + "bookmark", + ]); queryClient.invalidateQueries(["bookmark", user?.memberId, animeId]); queryClient.invalidateQueries(["anime", animeId, user?.memberId]); From 1d6da7a2d5227ec00d4192bbc89b4d5247420952 Mon Sep 17 00:00:00 2001 From: mihee Date: Tue, 21 Nov 2023 17:12:20 +0900 Subject: [PATCH 18/18] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=AC=B4=ED=9A=A8=ED=99=94=20query=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reviews/hook/useReview.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/features/reviews/hook/useReview.ts b/src/features/reviews/hook/useReview.ts index cc84e813..f1151adf 100644 --- a/src/features/reviews/hook/useReview.ts +++ b/src/features/reviews/hook/useReview.ts @@ -31,6 +31,12 @@ export default function useReview(animeId: number, onReview: () => void) { onSuccess: () => { queryClient.invalidateQueries(["profile", user?.name]); queryClient.invalidateQueries(["profile", user?.memberId, "review"]); + queryClient.invalidateQueries([ + "profile", + user?.memberId, + "count", + "review", + ]); queryClient.invalidateQueries(["review", animeId, user?.memberId]); queryClient.invalidateQueries(["anime", animeId, user?.memberId]); // TODO: 최신 리뷰 목록 query 무효화