From 74cf1f41b7bfe20cf42a96bc2e89c4270a098f3b Mon Sep 17 00:00:00 2001 From: howooking Date: Wed, 28 Jun 2023 21:37:40 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 1 + README.md | 18 +++---- src/components/product/ProductCard.tsx | 2 +- src/lib/ceilPrice.ts | 5 ++ src/lib/time.ts | 36 +++++++++++++ src/routes/Login.tsx | 2 +- src/routes/ProductDetail.tsx | 71 ++++++++++++++++++-------- src/routes/ProtectedRoute.tsx | 4 +- src/routes/admin/AllTransactions.tsx | 2 +- src/routes/myAccount/OrderDetail.tsx | 2 +- src/routes/myAccount/OrderList.tsx | 5 +- 11 files changed, 107 insertions(+), 41 deletions(-) create mode 100644 src/lib/ceilPrice.ts create mode 100644 src/lib/time.ts 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 (
{isLoading ? ( @@ -166,25 +179,39 @@ export default function ProductDetail() { options={accountOptions} value={selectedAccount} /> -
) : (