diff --git a/src/components/organisms/CommentItem/index.tsx b/src/components/organisms/CommentItem/index.tsx index 65d2b5c1..9dedf91a 100644 --- a/src/components/organisms/CommentItem/index.tsx +++ b/src/components/organisms/CommentItem/index.tsx @@ -3,6 +3,9 @@ import { KebabIcon, ReplyIcon } from "components/atoms/Icon"; import { InputWithButton, KebabMenu } from "components/molecules"; import { getRelativeTime } from "utils"; import { useCommentWriter, useDetailModal, useKebabMenu } from "hooks"; +import { useUserStore } from "stores"; +import type { CommentStatus, IComment, IWriteCommentData } from "types"; +import { LOGO_PATH } from "constants/imgPath"; import { CommentContentWrapper, CommentItemContainer, @@ -15,8 +18,6 @@ import { WriterInformationWrapper, WriterBadgeWrapper, } from "./styled"; -import type { CommentStatus, IComment, IWriteCommentData } from "types"; -import { useUserStore } from "stores"; import { DeletedComment } from "./deleted"; export interface ICommentItemProps { @@ -132,7 +133,7 @@ export const CommentItem = ({ {status !== "DELETED" && ( - + diff --git a/src/constants/modalMessage.ts b/src/constants/modalMessage.ts index b6e14953..9a428240 100644 --- a/src/constants/modalMessage.ts +++ b/src/constants/modalMessage.ts @@ -25,6 +25,7 @@ export const modalMessage = { early: "조기 마감을 적용해서 마감시간을 2시간으로 앞당길 수 있어요! 조기 마감하시겠어요?", remove: { + DEFAULT: "삭제하시겠습니까?", hasBuyer: "입찰자가 존재하는 게시글입니다. \n" + "정말 삭제하시겠습니까? \n" + diff --git a/src/hooks/useDetailModal.ts b/src/hooks/useDetailModal.ts index 56763c1b..12f34d61 100644 --- a/src/hooks/useDetailModal.ts +++ b/src/hooks/useDetailModal.ts @@ -15,6 +15,8 @@ export const useDetailModal = () => { // 판매자 const earlyClosing = (onEarlyClosing: () => void) => confirm(modalMessage.product.seller.early, onEarlyClosing); + const removeNoBuyer = (onRemove: () => void) => + confirm(modalMessage.product.seller.remove.DEFAULT, onRemove); const removeHasBuyer = (onRemove: () => void) => confirm(modalMessage.product.seller.remove.hasBuyer, onRemove); @@ -27,6 +29,7 @@ export const useDetailModal = () => { editEarly, bid, earlyClosing, + removeNoBuyer, removeHasBuyer, todo, }; diff --git a/src/hooks/useFetchProduct.ts b/src/hooks/useFetchProduct.ts index 0fad35b8..c3aabf34 100644 --- a/src/hooks/useFetchProduct.ts +++ b/src/hooks/useFetchProduct.ts @@ -1,14 +1,35 @@ import { useQuery } from "@tanstack/react-query"; import { queries } from "constants/queryKeys"; import { getProduct } from "services/apis"; +import { useEffect } from "react"; +import { AxiosError } from "axios"; +import { useNavigate } from "react-router-dom"; export const useFetchProduct = (productId: string) => { - const { data, isLoading, refetch } = useQuery({ + const navigate = useNavigate(); + const { data, isLoading, refetch, isError, error } = useQuery({ queryKey: queries.product.detail(productId), queryFn: () => getProduct(productId), select: (data) => data.result, + retry: false, }); + useEffect(() => { + if (isError) { + if (error instanceof AxiosError) { + const { code } = error.response?.data; + if (code === "PRODUCT410") { + // PRODUCT410 삭제된 게시물 + navigate("/", { replace: true }); + } + if (code === "PRODUCT404") { + // PRODUCT404 조회 실패 + navigate("/error", { replace: true }); + } + } + } + }, [isError]); + return { product: data, isProductLoading: isLoading, diff --git a/src/pages/DetailPage/index.tsx b/src/pages/DetailPage/index.tsx index 46db5c62..0dc530ee 100644 --- a/src/pages/DetailPage/index.tsx +++ b/src/pages/DetailPage/index.tsx @@ -1,5 +1,5 @@ import { Suspense, useEffect } from "react"; -import { Navigate, useNavigate, useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { DetailTemplate } from "components/templates"; import { KebabMenu } from "components/molecules"; import { KebabIcon } from "components/atoms/Icon"; @@ -25,7 +25,9 @@ import { Toast } from "components/atoms"; export const DetailPage = () => { const navigate = useNavigate(); const { productId } = useParams<{ productId: string }>(); - const { product, isProductLoading } = useFetchProduct(productId!); + const { product, isProductLoading, productRefetch } = useFetchProduct( + productId!, + ); const { comments, isCommentLoading } = useFetchComment(productId!); const { actions: { closeModal }, @@ -38,7 +40,7 @@ export const DetailPage = () => { const { setFormData, setProductId } = useFormDataStore(); const { open, handleOpen, handleClose, menuRef } = useKebabMenu(); const { handleCancel } = useBid(parseInt(productId!)); - const { todo } = useDetailModal(); + const { todo, removeNoBuyer, removeHasBuyer } = useDetailModal(); /** * 거래 희망 장소 클릭 @@ -95,6 +97,7 @@ export const DetailPage = () => { earlyClose(productId!) .then((data) => { console.log(data); + productRefetch().catch(console.error); Toast.show("조기 종료가 적용되었습니다.", 2000); closeModal(); }) @@ -139,24 +142,28 @@ export const DetailPage = () => { /** * (판매자) 삭제하기 */ + const handleDeleteProduct = () => { + deleteProduct(productId!) + .then((data) => { + console.log(data); + Toast.show("삭제되었습니다.", 2000); + navigate("/", { replace: true }); + closeModal(); + }) + .catch(console.error); + }; const handleDelete = () => { if (!product) { return; } if (product.hasBuyer) { - // TODO 구매자 있는 게시글은 삭제할 수 없습니다. 모달 - Toast.show("구매자가 있는 게시물은 삭제할 수 없습니다.", 2000); + removeHasBuyer(handleDeleteProduct); handleClose(); return; } if (!product.hasBuyer) { - // TODO 삭제 처리 (내일 확인 ㅠ) - deleteProduct(productId!) - .then((data) => { - console.log(data); - navigate("/", { replace: true }); - }) - .catch(console.error); + removeNoBuyer(handleDeleteProduct); + handleClose(); return; } }; @@ -181,8 +188,7 @@ export const DetailPage = () => { } if (!product) { - // 에러페이지로 이동 - return ; + return null; } return (