diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 2b4e7a4f..20df948c 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -10,5 +10,6 @@ module.exports = {
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': 'warn',
+ 'no-console': ['warn'],
},
};
diff --git a/README.md b/README.md
index cb8e9d38..f73ccbd0 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@
> 본 프로젝트는 패스트캠퍼스 부트캠프 프론트앤드 5기, 5차 과제입니다.
> 저희 1조는 주어진 API를 활용하여 축구화 온라인 쇼핑몰을 제작하였습니다.
+> 참고 한 사이트: [크레이지11](https://crazy11.co.kr/)
> 개발 기간 : 2023. 5. 31 ~ 2023. 6. 21
@@ -47,7 +48,7 @@ $ npm run dev
## Environment
-
+
## Config
@@ -57,15 +58,13 @@ $ npm run dev
## Development
-
-
-
-
+
+
+
+
: 전역 상태관리
- : 팝업 안내 메시지
-
+ : 팝업 안내 메시지
: 이미지 슬라이더
-
# 화면 구성
@@ -95,7 +94,7 @@ $ npm run dev
- 팀원 내 입문자를 배려하여 상대적으로 사용이 쉬운 [ZUSTAND](https://zustand-demo.pmnd.rs/)를 사용
- context wrapping하는 과정이 필요하지 않음
- - [src/store.ts](https://github.com/howooking/KDT5-M5/blob/0172a31077634c42139005c52c4e62156e3ab2ba/src/store.ts#L1-L64)
+ - [src/store.ts](https://github.com/howooking/KDT5-M5/blob/00c7b69fb881e9e7c8cf781f5b96cfd1c15e7b6b/src/store.ts#L1C1-L69)
```js
import { create } from 'zustand';
@@ -285,6 +284,7 @@ $ npm run dev
- 상품
- 상품 상세 페이지 하단에 해당 상품과 같은 카테고리에 있는 제품 10개를 랜덤으로 추천한다.
- 상품이 매진인 경우 "SOLD OUT" 이미지를 상품 이미지 위에 표시한다.
+ - 상품이 매진인 경우 "입고 알림" 버튼이 보인다.
- 첫 협업 프로젝트
- 첫 팀프로젝트다 보니 진행과정에서 아쉬웠던 부분이 많았음
diff --git a/src/components/product/ProductCard.tsx b/src/components/product/ProductCard.tsx
index 7b09dedb..6ac4db92 100644
--- a/src/components/product/ProductCard.tsx
+++ b/src/components/product/ProductCard.tsx
@@ -1,4 +1,4 @@
-import { priceBeforeDiscount } from '@/constants/library';
+import { priceBeforeDiscount } from '@/lib/ceilPrice';
interface ProductCardProps {
title: string;
diff --git a/src/lib/ceilPrice.ts b/src/lib/ceilPrice.ts
new file mode 100644
index 00000000..63cba31b
--- /dev/null
+++ b/src/lib/ceilPrice.ts
@@ -0,0 +1,5 @@
+export function priceBeforeDiscount(price: number, discountRate: number) {
+ return (
+ Math.ceil((price * 100) / (100 - discountRate) / 1000) * 1000
+ ).toLocaleString('ko-KR');
+}
diff --git a/src/lib/time.ts b/src/lib/time.ts
new file mode 100644
index 00000000..ab470608
--- /dev/null
+++ b/src/lib/time.ts
@@ -0,0 +1,36 @@
+export function convertToMilliseconds(dateString: string) {
+ // Convert string to Date object
+ const date = new Date(dateString);
+
+ // Get timestamp in milliseconds
+ const timestampMs = date.getTime();
+
+ return timestampMs;
+}
+
+export function convertToHumanReadable(dateString: string) {
+ // Convert string to Date object
+ const date = new Date(dateString);
+
+ // Extract date components
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1; // Months are zero-based
+ const day = date.getDate();
+
+ // Extract time components
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+
+ // Format the date and time
+ const formattedDate = `${year}.${month.toString().padStart(2, '0')}.${day
+ .toString()
+ .padStart(2, '0')}`;
+ const formattedTime = `${hours.toString().padStart(2, '0')}:${minutes
+ .toString()
+ .padStart(2, '0')}`;
+
+ // Combine the formatted date and time
+ const humanReadableDateTime = `${formattedDate} / ${formattedTime}`;
+
+ return humanReadableDateTime;
+}
diff --git a/src/routes/Login.tsx b/src/routes/Login.tsx
index 69eaa699..12af5685 100644
--- a/src/routes/Login.tsx
+++ b/src/routes/Login.tsx
@@ -68,7 +68,7 @@ export default function Login() {
// 로그인 실패
const errorMessage = res.message;
- toast.error(errorMessage, { id: 'login' });
+ toast.error(errorMessage, { id: 'login' }); //토스트 메세지
setIsSending(false);
};
diff --git a/src/routes/ProductDetail.tsx b/src/routes/ProductDetail.tsx
index 906c4da4..df042b85 100644
--- a/src/routes/ProductDetail.tsx
+++ b/src/routes/ProductDetail.tsx
@@ -1,7 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { getProductDetail } from '@/api/adminApi';
import SectionTitle from '@/components/ui/SectionTitle';
-import { priceBeforeDiscount } from '@/constants/library';
import { useEffect, useMemo, useState } from 'react';
import { getAccountListAndBalance } from '@/api/bankApi';
import { userStore } from '@/store';
@@ -15,6 +14,7 @@ import Select from '@/components/ui/Select';
import LoadingSpinner from '@/components/ui/LoadingSpinner';
import { AiOutlineEdit } from 'react-icons/ai';
import ProductSection from '@/components/product/ProductSection';
+import { priceBeforeDiscount } from '@/lib/ceilPrice';
export default function ProductDetail() {
const navigate = useNavigate();
@@ -41,7 +41,6 @@ export default function ProductDetail() {
}
fetchData();
}, [productId]);
- console.log(product);
useEffect(() => {
async function fetchData() {
@@ -62,7 +61,9 @@ export default function ProductDetail() {
? [
{ name: '결제할 계좌 선택', value: '' },
...accounts.map((account) => ({
- name: `${account.bankName} / ${account.accountNumber} / 잔액 : ${account.balance}`,
+ name: `${account.bankName} / ${
+ account.accountNumber
+ } / 잔액 : ${account.balance.toLocaleString('ko-KR')}원`,
value: account.id,
})),
]
@@ -71,6 +72,10 @@ export default function ProductDetail() {
);
const handlePurchase = async () => {
+ if (!selectedAccount) {
+ toast.error('계좌를 선택해주세요.', { id: 'buyProduct' });
+ return;
+ }
setIsPurchasing(true);
toast.loading('결제 요청 중...', { id: 'buyProduct' });
const res = await buyProduct(
@@ -93,6 +98,14 @@ export default function ProductDetail() {
navigate('/admin/editproduct', { state: { productId, productTitle } });
};
+ const handleAlarm = () => {
+ setIsPurchasing(true);
+ setTimeout(() => {
+ toast.success(`${product?.title} 입고시 알림문자 발송!`);
+ setIsPurchasing(false);
+ }, 500);
+ };
+
return (