- {/* 경매 아이템 제목 & 시작가 */}
- {auctionDetails && (
-
-
-
-
- {auctionDetails?.sellerNickname || ''}
-
-
-
- {auctionDetails?.productName || ''}
-
-
-
-
-
-
- 시작가
-
- {formatCurrencyWithWon(auctionDetails?.minPrice || 0)}
-
-
-
-
- )}
- {/* 나의 참여 금액 & 경매 참여인원 */}
-
-
-
-
-
- 나의 참여 금액
-
-
- {auctionDetails?.isParticipated
- ? `${formatCurrencyWithWon(auctionDetails?.bidAmount || 0)}원`
- : '참여 전'}
-
-
-
-
-
-
-
참여 인원
-
-
- {auctionDetails?.participantCount
- ? `${auctionDetails?.participantCount}명`
- : '0명'}
-
-
+
+
+
+
+
나의 참여 금액
+
+ {isParticipated
+ ? `${formatCurrencyWithWon(bidAmount)}`
+ : (isCancelled ? '참여 취소' : '참여 전')}
+
-
-
- {/* 상품 설명 */}
-
-
{auctionDetails?.description || ''}
-
-
- {/* 화면 하단에 고정된 Footer */}
-
- {auctionDetails && auctionDetails.isSeller ? (
-
- ) : (
-
- )}
-
- {/* 백드롭 */}
- {isMenuOpen && (
- <>
-
- {/* 메뉴 (아코디언) */}
-
-
-
+
+
+
+
참여 인원
+
+
+ {`${participantCount} 명`}
+
- >
- )}
-
+
+
+ {description}
+
+
+
+
);
};
diff --git a/src/pages/Heart.tsx b/src/pages/Heart.tsx
index 0832646b..ea956392 100644
--- a/src/pages/Heart.tsx
+++ b/src/pages/Heart.tsx
@@ -22,7 +22,7 @@ const Heart = () => {
-
diff --git a/src/pages/Notification.tsx b/src/pages/Notification.tsx
index 8de6cf54..920e8586 100644
--- a/src/pages/Notification.tsx
+++ b/src/pages/Notification.tsx
@@ -1,4 +1,4 @@
-import { useDeleteNotification, useGetNotificationsWithSuspense, useReadNotification } from '@/components/notification/queries';
+import { useGetNotificationsWithSuspense } from '@/components/notification/queries';
import EmptyBoundary from '@/components/common/boundary/EmptyBoundary';
import NotificationItem from '@/components/notification/NotificationItem';
@@ -6,17 +6,12 @@ import type { INotification } from 'Notification';
const Notification = () => {
const { notifications } = useGetNotificationsWithSuspense();
- const { mutate: deleteNotification } = useDeleteNotification();
- const { mutate: readNotification } = useReadNotification();
-
- const clickDelete = (id: number) => deleteNotification(id);
- const clickRead = (id: number) => readNotification(id);
return (
{notifications.map((item: INotification) => (
-
+
))}
diff --git a/src/pages/PreAuctionDetails.tsx b/src/pages/PreAuctionDetails.tsx
index 060e23c0..09a261e2 100644
--- a/src/pages/PreAuctionDetails.tsx
+++ b/src/pages/PreAuctionDetails.tsx
@@ -1,166 +1,116 @@
+import DeleteIcon from '@/assets/icons/modal_cancel.svg';
+import EditIcon from '@/assets/icons/modal_edit.svg';
import {
useDeletePreAuction,
useGetPreAuctionDetailsWithSuspense
} from '@/components/details/queries';
import { LoaderFunction, useLoaderData, useNavigate } from 'react-router-dom';
-import Price from '@/assets/icons/price.svg';
-import LocalAPIAsyncBoundary from '@/components/common/boundary/LocalAPIAsyncBoundary';
-import BuyersFooter from '@/components/details/BuyersFooter';
-import ConfirmationModal from '@/components/details/ConfirmationModal';
-import ImageList from '@/components/details/ImageList';
-import SellersFooter from '@/components/details/SellersFooter';
-import SuccessModal from '@/components/details/SuccessModal';
+import BoxEditIcon from '@/assets/icons/in_box_edit_time.svg';
+import BoxLikeIcon from '@/assets/icons/in_box_like.svg';
+import Button from '@/components/common/Button';
+import ConfirmModal from '@/components/common/ConfirmModal';
+import CustomCarousel from '@/components/common/CustomCarousel';
+import DetailsBasic from '@/components/details/DetailsBasic';
+import PreAuctionDetailsFooter from '@/components/details/PreAuctionDetailsFooter';
import Layout from '@/components/layout/Layout';
-import { formatCurrencyWithWon } from '@/utils/formatCurrencyWithWon';
-/* eslint-disable prettier/prettier */
+import { CarouselItem } from '@/components/ui/carousel';
+import { getTimeAgo } from '@/utils/getTimeAgo';
import { useState } from 'react';
-const PreAuction = () => {
+const PreAuctionDetails = () => {
+ const navigate = useNavigate();
const preAuctionId = useLoaderData() as number;
const { preAuctionDetails } = useGetPreAuctionDetailsWithSuspense(preAuctionId);
-
+ const { images, productName, productId, likeCount, sellerNickname, minPrice, isSeller, description, category, sellerProfileImageUrl, updatedAt } = preAuctionDetails
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false);
- const [isDeleteSuccessOpen, setIsDeleteSuccessOpen] = useState(false);
-
- const navigate = useNavigate();
- const { mutate: deletePreAuction } = useDeletePreAuction();
-
- const toggleMenu = () => setIsMenuOpen(!isMenuOpen);
- const closeMenu = () => setIsMenuOpen(false);
-
- // Delete button click handler
- const onDeleteButtonClickHandler = () => {
- setIsDeleteConfirmOpen(true);
- closeMenu();
- };
-
- const onEditButtonClickHandler = () => {
- navigate(`/auctions/pre-auction/edit/${preAuctionDetails.productId}`);
- };
+ const { mutate: deletePreAuction, isPending } = useDeletePreAuction();
- const handleConfirmDelete = () => {
- deletePreAuction(preAuctionId, {
- onSuccess: () => {
- setIsDeleteConfirmOpen(false);
- setIsDeleteSuccessOpen(true);
- },
- });
- };
+ const updatedTime = getTimeAgo(updatedAt)
- const handleCloseSuccessModal = () => {
- setIsDeleteSuccessOpen(false);
- navigate('/');
- };
+ const toggleMenu = () => setIsMenuOpen((prev) => !prev);
+ const toggleConfirm = () => setIsDeleteConfirmOpen((prev) => !prev)
+ const clickDelete = () => {
+ toggleMenu()
+ toggleConfirm()
+ }
+ const clickEdit = () => navigate(`/auctions/pre-auction/edit/${productId}`);
+ const confirmDelete = () => deletePreAuction(preAuctionId);
return (
-
-
-
-
-
-
-
-
- {preAuctionDetails && (
-
-
-
-
- {preAuctionDetails?.sellerNickname || ''}
-
-
-
- {preAuctionDetails.productName}
-
-
-
-
-
-
- 시작가
-
- {formatCurrencyWithWon(preAuctionDetails.minPrice)}원
-
-
-
+
+
+
+ {images.map((img) => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+
수정 시간
+
+
+ {updatedTime}
+
+
+
+
+
+
좋아요
- )}
-
-
-
{preAuctionDetails?.description}
-
-
-
- {preAuctionDetails.isSeller ? (
-
- ) : (
-
- )}
-
- {isMenuOpen && (
- <>
-
-
-
- 수정하기
+
+ {`${likeCount} 명`}
+
+
+
+
+ {description}
+
+
+
+
+ {
+ isMenuOpen && (
+
+
e.stopPropagation()} className='absolute flex flex-col w-1/5 bg-white rounded-lg sm:text-body1 text-body2 top-3 right-3'>
+
+ 수정하기
+
-
- 삭제하기
+
+ 삭제하기
+
- >
- )}
-
- {isDeleteConfirmOpen && (
-
setIsDeleteConfirmOpen(false)}
- />
- )}
- {isDeleteSuccessOpen && (
-
- )}
-
- );
-};
+ )
+ }
+ {
+ isDeleteConfirmOpen &&
+
+
+ 삭제
+
+
+ }
+ )
+
+}
-export default PreAuction;
+export default PreAuctionDetails;
export const loader: LoaderFunction
= async ({ params }) => {
const { preAuctionId } = params;
diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx
index 34b80502..9772f8ac 100644
--- a/src/pages/Register.tsx
+++ b/src/pages/Register.tsx
@@ -63,7 +63,10 @@ const Register = () => {
const finalButton = caution === 'REGISTER' ? '바로 등록하기' : '사전 등록하기';
const toggleCheckBox = () => setCheck((state) => !state);
- const clickBack = () => (caution === '' ? navigate(-1) : setCaution(''));
+ const clickBack = () => {
+ (caution === '' ? navigate(-1) : setCaution(''));
+ toggleCheckBox()
+ }
const handleProceed = (proceedType: 'PRE_REGISTER' | 'REGISTER') => {
handleSubmit(() => setCaution(proceedType))();
};
diff --git a/src/provider/queryProvider.tsx b/src/provider/queryProvider.tsx
index 73f73943..d30bbe6f 100644
--- a/src/provider/queryProvider.tsx
+++ b/src/provider/queryProvider.tsx
@@ -25,8 +25,8 @@ const ReactQueryProvider = ({ showDevTools = false, children }: ReactQueryProvid
throwOnError: false,
onError: (error) => {
if (error instanceof AxiosError) {
- const { title } = getErrorByCode(error)
- toast.error(title);
+ const { description } = getErrorByCode(error)
+ toast.error(description);
}
},
},
diff --git a/src/utils/dataURLToFile.ts b/src/utils/dataURLToFile.ts
index 0f939888..29d1b3df 100644
--- a/src/utils/dataURLToFile.ts
+++ b/src/utils/dataURLToFile.ts
@@ -1,3 +1,5 @@
+import { toast } from 'sonner';
+
export const dataURLtoFile = (dataURL: string): File => {
// DataURL에서 Base64와 MIME 타입 추출
const arr = dataURL.split(',');
@@ -18,11 +20,15 @@ export const dataURLtoFile = (dataURL: string): File => {
const mimeToExtensionMap: { [key: string]: string } = {
'image/jpeg': 'jpg',
'image/png': 'png',
+ 'image/webp': 'webp',
};
// MIME 타입이 지도된 확장자가 있는 경우에만 파일 생성
const extension = mimeToExtensionMap[mime];
- if (!extension) throw new Error(`${mime}은 지원되지 않는 MIME 타입입니다.`);
+ if (!extension) {
+ toast.error(`${mime}은 지원되지 않는 MIME 타입입니다.`);
+ throw new Error(`${mime}은 지원되지 않는 MIME 타입입니다.`);
+ }
const fileName = `image.${extension}`; // idx를 사용한 파일 이름