Skip to content

Commit

Permalink
제출
Browse files Browse the repository at this point in the history
  • Loading branch information
howooking committed Jun 28, 2023
1 parent dcee1d0 commit 74cf1f4
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 41 deletions.
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ module.exports = {
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': 'warn',
'no-console': ['warn'],
},
};
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

> 본 프로젝트는 패스트캠퍼스 부트캠프 프론트앤드 5기, 5차 과제입니다.
> 저희 1조는 주어진 API를 활용하여 축구화 온라인 쇼핑몰을 제작하였습니다.
> 참고 한 사이트: [크레이지11](https://crazy11.co.kr/) <br>
> 개발 기간 : 2023. 5. 31 ~ 2023. 6. 21
<br>
Expand Down Expand Up @@ -47,7 +48,7 @@ $ npm run dev
## Environment

<img src="https://img.shields.io/badge/VISUAL STUDIO CODE-007ACC?style=flat&logo=visualstudiocode&logoColor=white"/><br>
<img src="https://img.shields.io/badge/Git-F05032?style=flat&logo=git&logoColor=white"/><br>
<img src="https://img.shields.io/badge/GIT-F05032?style=flat&logo=git&logoColor=white"/><br>
<img src="https://img.shields.io/badge/GIT HUB-181717?style=flat&logo=github&logoColor=white"/><br>

## Config
Expand All @@ -57,15 +58,13 @@ $ npm run dev

## Development

<img src="https://img.shields.io/badge/React-61DAFB?style=flat&logo=React&logoColor=white"/><br>
<img src="https://img.shields.io/badge/Typescript-3178C6?style=flat&logo=typescript&logoColor=white"/><br>
<img src="https://img.shields.io/badge/Tailwind CSS-06B6D4?style=flat&logo=tailwindcss&logoColor=white"/><br>
<img src="https://img.shields.io/badge/React Router-CA4245?style=flat&logo=reactrouter&logoColor=white"/> <br>
<img src="https://img.shields.io/badge/REACT-61DAFB?style=flat&logo=React&logoColor=white"/><br>
<img src="https://img.shields.io/badge/TYPESCRIPT-3178C6?style=flat&logo=typescript&logoColor=white"/><br>
<img src="https://img.shields.io/badge/TAILWIND-06B6D4?style=flat&logo=tailwindcss&logoColor=white"/><br>
<img src="https://img.shields.io/badge/REACT ROUTER-CA4245?style=flat&logo=reactrouter&logoColor=white"/> <br>
<img src="https://img.shields.io/badge/ZUSTAND-443E38?style=flat&logo=&logoColor=white"/> : 전역 상태관리 <br>
<img src="https://img.shields.io/badge/REACT HOT TOAST-FFF7E2?style=flat&logo=&logoColor=black"/> : 팝업 안내 메시지
<br>
<img src="https://img.shields.io/badge/REACT HOT TOAST-FFF7E2?style=flat&logo=&logoColor=black"/> : 팝업 안내 메시지<br>
<img src="https://img.shields.io/badge/NUKA CAROUSEL-8D428D?style=flat&logo=&logoColor=black"/> : 이미지 슬라이더<br>
<br>

# 화면 구성

Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -285,6 +284,7 @@ $ npm run dev
- 상품
- 상품 상세 페이지 하단에 해당 상품과 같은 카테고리에 있는 제품 10개를 랜덤으로 추천한다.
- 상품이 매진인 경우 "SOLD OUT" 이미지를 상품 이미지 위에 표시한다.
- 상품이 매진인 경우 "입고 알림" 버튼이 보인다.
<br><br>
- 첫 협업 프로젝트
- 첫 팀프로젝트다 보니 진행과정에서 아쉬웠던 부분이 많았음
Expand Down
2 changes: 1 addition & 1 deletion src/components/product/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { priceBeforeDiscount } from '@/constants/library';
import { priceBeforeDiscount } from '@/lib/ceilPrice';

interface ProductCardProps {
title: string;
Expand Down
5 changes: 5 additions & 0 deletions src/lib/ceilPrice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function priceBeforeDiscount(price: number, discountRate: number) {
return (
Math.ceil((price * 100) / (100 - discountRate) / 1000) * 1000
).toLocaleString('ko-KR');
}
36 changes: 36 additions & 0 deletions src/lib/time.ts
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion src/routes/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function Login() {

// 로그인 실패
const errorMessage = res.message;
toast.error(errorMessage, { id: 'login' });
toast.error(errorMessage, { id: 'login' }); //토스트 메세지
setIsSending(false);
};

Expand Down
71 changes: 49 additions & 22 deletions src/routes/ProductDetail.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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();
Expand All @@ -41,7 +41,6 @@ export default function ProductDetail() {
}
fetchData();
}, [productId]);
console.log(product);

useEffect(() => {
async function fetchData() {
Expand All @@ -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,
})),
]
Expand All @@ -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(
Expand All @@ -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 (
<div className="my-10">
{isLoading ? (
Expand Down Expand Up @@ -166,25 +179,39 @@ export default function ProductDetail() {
options={accountOptions}
value={selectedAccount}
/>
<Button
onClick={
accounts.length > 0
? handlePurchase
: () => navigate('/myaccount/connectAccount')
}
text={
isPurchasing ? (
<LoadingSpinner color="white" />
) : (
`${
accounts.length > 0
? '원클릭 간편 결제'
: '계좌 등록하러 가기'
}`
)
}
disabled={isPurchasing}
/>
{product?.isSoldOut ? (
<Button
text={
isPurchasing ? (
<LoadingSpinner color="white" />
) : (
'입고 알림'
)
}
onClick={handleAlarm}
disabled={isPurchasing}
/>
) : (
<Button
onClick={
accounts.length > 0
? handlePurchase
: () => navigate('/myaccount/connectAccount')
}
text={
isPurchasing ? (
<LoadingSpinner color="white" />
) : (
`${
accounts.length > 0
? '원클릭 간편 결제'
: '계좌 등록하러 가기'
}`
)
}
disabled={isPurchasing}
/>
)}
</div>
) : (
<Button
Expand Down
4 changes: 2 additions & 2 deletions src/routes/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Navigate } from 'react-router-dom';
import { userStore } from '@/store';

type ProtectedRouteProps = {
interface ProtectedRouteProps {
element: React.ReactNode;
adminRequired?: boolean;
};
}

export default function ProtectedRoute({
element,
Expand Down
2 changes: 1 addition & 1 deletion src/routes/admin/AllTransactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react';
import { getAllTransactions } from '@/api/adminApi';
import toast from 'react-hot-toast';
import CrazyLoading from '@/components/ui/CrazyLoading';
import { convertToHumanReadable } from '@/constants/library';
import { convertToHumanReadable } from '@/lib/time';
import SectionTitle from '@/components/ui/SectionTitle';

export default function TransactionsPage() {
Expand Down
2 changes: 1 addition & 1 deletion src/routes/myAccount/OrderDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { getOrderDetail } from '@/api/transactionApi';
import { userStore } from '@/store';
import { convertToHumanReadable } from '@/constants/library';
import { convertToHumanReadable } from '@/lib/time';
import CrazyLoading from '@/components/ui/CrazyLoading';
import SectionTitle from '@/components/ui/SectionTitle';
import toast from 'react-hot-toast';
Expand Down
5 changes: 1 addition & 4 deletions src/routes/myAccount/OrderList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { confirmOrder, getOrderList, cancelOrder } from '@/api/transactionApi';
import Button from '@/components/ui/Button';
import CrazyLoading from '@/components/ui/CrazyLoading';
import SectionTitle from '@/components/ui/SectionTitle';
import {
convertToHumanReadable,
convertToMilliseconds,
} from '@/constants/library';
import { convertToHumanReadable, convertToMilliseconds } from '@/lib/time';
import { userStore } from '@/store';
import { useEffect, useState } from 'react';
import { toast } from 'react-hot-toast';
Expand Down

0 comments on commit 74cf1f4

Please sign in to comment.