Skip to content

Commit aca118d

Browse files
yeji0214keemsebin
andauthored
[1단계 - 장바구니 미션] 에리얼(정예지) 미션 제출합니다. (#327)
* chore: 프로젝트 eslint, prettierrc 셋팅 Co-Authored-By: YEJI <[email protected]> * chore: emotion 셋팅 Co-Authored-By: YEJI <[email protected]> * chore: 폴더 구조 정의 Co-Authored-By: YEJI <[email protected]> * chore: react-router-dom install Co-Authored-By: YEJI <[email protected]> * docs: readme 작성 Co-Authored-By: YEJI <[email protected]> * feat: Header 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: Flex 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: Text 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: Button 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: AppLayout 구현 Co-Authored-By: YEJI <[email protected]> * feat: CartPage 구현 Co-Authored-By: YEJI <[email protected]> * feat: CartListContainer 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: CartItemDetail 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * chore: 불필요한 파일 삭제 Co-Authored-By: YEJI <[email protected]> * chore: emotion 라이브러리 install Co-Authored-By: YEJI <[email protected]> * chore: font 추가 Co-Authored-By: YEJI <[email protected]> * docs: readme 업데이트 Co-Authored-By: YEJI <[email protected]> * feat: QuantitySelector 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: 체크박스 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: Cart, Product type 정의 Co-Authored-By: YEJI <[email protected]> * chore: cart mock data 추가 Co-Authored-By: YEJI <[email protected]> * chore: tsconfig jsxImportSource 설정 Co-Authored-By: YEJI <[email protected]> * refactor: Button 컴포넌트 isLoading 삭제 Co-Authored-By: YEJI <[email protected]> * style: StyledCartListContainer padding 값 수정 Co-Authored-By: YEJI <[email protected]> * refactor: CartItemDetail 컴포넌트 체크박스 컴포넌트 추가 Co-Authored-By: YEJI <[email protected]> * chore: index.css에 font 추가 Co-Authored-By: YEJI <[email protected]> * feat: App.tsx에 CartPage import Co-Authored-By: YEJI <[email protected]> * chore: 불필요한 파일 정리 Co-Authored-By: YEJI <[email protected]> * feat: PriceSummary 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * style: CartListContainer max height 설정 Co-Authored-By: YEJI <[email protected]> * style: Spacing border, margin 수정 Co-Authored-By: YEJI <[email protected]> * chore: gitignore 설정 Co-Authored-By: YEJI <[email protected]> * feat: ENV 파일 설정 Co-Authored-By: YEJI <[email protected]> * feat: fetcher 함수 구현 Co-Authored-By: YEJI <[email protected]> * feat: cart api 호출 함수 구현 Co-Authored-By: YEJI <[email protected]> * refactor: CartItem type에 isChecked 속성 추가 Co-Authored-By: YEJI <[email protected]> * refactor: CheckBox 컴포넌트에 type, props 설정 추가 Co-Authored-By: YEJI <[email protected]> * feat: cart 데이터 패치 hook 구현 Co-Authored-By: YEJI <[email protected]> * feat: useFetchData hook 구현 Co-Authored-By: YEJI <[email protected]> * feat: CartPage에 cartItems ,PriceSummary, Button 연결 Co-Authored-By: YEJI <[email protected]> * feat: useScrollStatus hook 구현 Co-Authored-By: YEJI <[email protected]> * refactor: useCart 데이터 패치 함수 추가 Co-Authored-By: YEJI <[email protected]> * style: CartListContainer 컴포넌트에 Overlay 추가 Co-Authored-By: YEJI <[email protected]> * feat: CartItemDetail 컴포넌트에 삭제 함수 추가 Co-Authored-By: YEJI <[email protected]> * chore: prettier 적용 Co-Authored-By: YEJI <[email protected]> * feat: 수량 업데이트 함수 구현 Co-Authored-By: YEJI <[email protected]> * style: 장바구니 리스트 높이 변경 Co-Authored-By: YEJI <[email protected]> * feat: 동적으로 결제 금액, 배송비 계산 및 렌더링 Co-Authored-By: YEJI <[email protected]> * feat: 체크박스 이벤트 핸들러 등록 Co-Authored-By: YEJI <[email protected]> * docs: 기능 요구 사항 업데이트 Co-Authored-By: YEJI <[email protected]> * chore: eslint 설정 Co-Authored-By: YEJI <[email protected]> * style: eslint 적용으로 인한 스타일 변경 Co-Authored-By: YEJI <[email protected]> * feat: 체크박스 전체 선택/해제 기능 구현 Co-Authored-By: YEJI <[email protected]> * feat: CartInfo 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: OrderConfirm 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * chore: eslint 적용 Co-Authored-By: YEJI <[email protected]> * feat: useFunnel 구현 Co-Authored-By: YEJI <[email protected]> * fear: shoppingContext 전역 도구 추가 Co-Authored-By: YEJI <[email protected]> * refactor: CartPage 컴포넌트에 funnel 추가 Co-Authored-By: YEJI <[email protected]> * chore: Back png 추가 Co-Authored-By: YEJI <[email protected]> * feat: App.tsx에 AppLayout 추가 Co-Authored-By: YEJI <[email protected]> * refactor: useCart 커스텀 훅에 useCartContext 적용 Co-Authored-By: YEJI <[email protected]> * chore: 불필요한 파일 정리 Co-Authored-By: YEJI <[email protected]> * chore: vitest config, jest config 설정 Co-Authored-By: YEJI <[email protected]> * refactor: `cartItems?.length === 0` 일 경우 조건문 추가 Co-Authored-By: YEJI <[email protected]> * refactor: StyledCartItemImg alt 문구 수정 Co-Authored-By: YEJI <[email protected]> * chore: 불필요한 코드 정리 Co-Authored-By: YEJI <[email protected]> * test: 장바구니에 상품이 존재하는 경우 목록, 페이지에 진입했을 경우 메시지 노출 테스트 작성 Co-Authored-By: YEJI <[email protected]> * docs: 테스트 readme 업데이트 Co-Authored-By: YEJI <[email protected]> * docs: readme 업데이트 Co-Authored-By: YEJI <[email protected]> * chore: test를 위한 mock 데이터 정의 Co-Authored-By: YEJI <[email protected]> * refactor: 장바구니 속성 props 전달 Co-Authored-By: YEJI <[email protected]> * feat: 컴포넌트 role 속성 추가 Co-Authored-By: YEJI <[email protected]> * feat: Progress 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * test: 장바구니 금액에 따른 배송비 측정 테스트 구현 Co-Authored-By: YEJI <[email protected]> * test: + 버튼을 통한 수량 증가 테스트 작선 Co-Authored-By: YEJI <[email protected]> * test: 전체 체크박스 해제시 구매 금액 테스트 작성 Co-Authored-By: YEJI <[email protected]> * test: 체크박스 선택시 상태 변경 테스트 작성 Co-Authored-By: YEJI <[email protected]> * test: 삭제 버튼 클릭시 해당 상품이 정상적으로 삭제되는지에 대한 테스트 작성 Co-Authored-By: YEJI <[email protected]> * chore: mock 데이터 Object.freeze 적용 Co-Authored-By: YEJI <[email protected]> * test: 주문 확인 버튼 클릭시 주문 정보 표시 테스트 작성 Co-Authored-By: YEJI <[email protected]> * chore: 사용하지 않는 코드 제거 Co-Authored-By: YEJI <[email protected]> * feat: Toast 컴포넌트 구현 Co-Authored-By: YEJI <[email protected]> * feat: isError 타입가드 구현 Co-Authored-By: YEJI <[email protected]> * refactor: isError(e) 타입 가드 적용 Co-Authored-By: YEJI <[email protected]> * chore: 사용하지 않는 파일 제거 Co-Authored-By: YEJI <[email protected]> * feat: ToastProvider 적용 Co-Authored-By: YEJI <[email protected]> * feat: 이미지 경로가 잘못되거나 엑박이뜨는 경우 NoImage 보여줌 Co-Authored-By: YEJI <[email protected]> * docs: pr template 추가 Co-Authored-By: YEJI <[email protected]> * refactor: shoppingContext 제거 * chore: eslint 설치로 인한 설정 파일 수정 * refactor: cart 관련 api를 features/Cart 내부로 이동하여 응집도 향상 * refactor: 쿼리 문자열 생성을 buildQueryParams 유틸로 분리 * refactor: CartInfo의 파생값 계산을 useCartInfo 커스텀 훅으로 추출 * refactor: 주문 정보 계산 로직을 useOrderInfo 훅으로 분리 * refactor: 가격 요약 계산 로직을 usePriceInfo 훅으로 분리 * refactor: 공통 fetch 헤더 DEFAULT_HEADER 상수로 관리 * refactor: shared/components 하위 index.tsx 파일명을 컴포넌트명으로 통일 * refactor: Toast 컴포넌트의 message prop을 children으로 변경 * refactor: STEPS 타입을 CartPage 내부로 이동하고 setStep 파일 제거 * feat: fetcher에서 실패 응답 시 HttpError로 명확하게 예외 처리 * refactor: CheckBox 컴포넌트에 input 요소 추가 * refactor: 불필요한 컴포넌트 props 주석 제거 * refactor: Header 컴포넌트의 justifyContent를 prop으로 제어하도록 변경 * refactor: Toast 컴포넌트의 렌더링 타겟을 parent prop으로 주입 가능하도록 수정 * refactor: Toast 유지 시간을 showToast의 duration 파라미터로 조절 가능하도록 수정 * refactor: refetchFn을 직접 호출하여 mutate 흐름 단순화 * refactor: ToastContext value를 useMemo로 최적화 * refactor: 장바구니 로직 CartContext로 이동 * refactor: useState 초기값에서 불필요한 제네릭 제거 * chore: 불필요한 jest 코드 및 파일 제거 * refactor: import 경로 alias(@) 기반으로 통일 * feat: 배송비 무료 기준 금액을 상수로 분리하여 관리 * test: 통합 테스트에 실패 케이스 추가 * test: 단위 테스트 작성 * style: 포맷팅 prettier로 통일 --------- Co-authored-by: keemsebeen <[email protected]>
1 parent e227607 commit aca118d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+5919
-569
lines changed

.eslintrc.cjs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,59 @@ module.exports = {
55
'eslint:recommended',
66
'plugin:@typescript-eslint/recommended',
77
'plugin:react-hooks/recommended',
8+
'plugin:import/typescript',
9+
'plugin:import/recommended',
10+
'prettier',
811
],
912
ignorePatterns: ['dist', '.eslintrc.cjs'],
1013
parser: '@typescript-eslint/parser',
11-
plugins: ['react-refresh'],
14+
plugins: ['react-refresh', 'react'],
1215
rules: {
13-
'react-refresh/only-export-components': [
16+
'@typescript-eslint/no-unused-vars': 'warn',
17+
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
18+
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
19+
'react/destructuring-assignment': ['warn', 'always', { destructureInSignature: 'always' }],
20+
'react/jsx-curly-brace-presence': [
1421
'warn',
15-
{ allowConstantExport: true },
22+
{ props: 'never', children: 'never', propElementValues: 'always' },
23+
],
24+
'react/function-component-definition': [
25+
'error',
26+
{
27+
namedComponents: 'arrow-function',
28+
unnamedComponents: 'arrow-function',
29+
},
30+
],
31+
'react/jsx-tag-spacing': 1,
32+
'no-restricted-exports': ['error', { restrictDefaultExports: { direct: true } }],
33+
'import/no-unresolved': 'off',
34+
'import/order': [
35+
'error',
36+
{
37+
groups: ['builtin', 'external', 'internal', 'sibling'],
38+
pathGroups: [
39+
{
40+
pattern: 'react',
41+
group: 'external',
42+
position: 'before',
43+
},
44+
{
45+
pattern: '@/**',
46+
group: 'internal',
47+
},
48+
{
49+
pattern: './*',
50+
group: 'sibling',
51+
},
52+
],
53+
distinctGroup: false,
54+
pathGroupsExcludedImportTypes: ['builtin'],
55+
alphabetize: {
56+
order: 'asc',
57+
caseInsensitive: true,
58+
},
59+
'newlines-between': 'always',
60+
},
1661
],
1762
},
18-
}
63+
};

.github/pull_request_template.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
## 📦 장바구니 미션
2+
3+
이번 미션을 통해 다음과 같은 학습 경험들을 쌓는 것을 목표로 합니다.
4+
5+
### 1단계
6+
7+
- 클라이언트 상태를 효과적으로 모델링하고 관리할 수 있다.
8+
- Jest, React Testing Library(RTL)를 활용하여 주요 기능에 대한 테스트를 작성할 수 있다.
9+
10+
## 🕵️ 셀프 리뷰(Self-Review)
11+
12+
### 제출 전 체크 리스트
13+
14+
- [ ] 기능 요구 사항을 모두 구현했고, 정상적으로 동작하는지 확인했나요?
15+
- [ ] RTL 테스트 케이스를 모두 작성했나요?
16+
- [ ] 배포한 데모 페이지에 정상적으로 접근할 수 있나요?
17+
18+
- 배포 링크 기입: **\_\_**
19+
20+
- [ ] 리뷰어가 장바구니 추가를 쉽게 할 수 있도록 Curl 명령어를 전달해주세요. (토큰을 채워주세요)
21+
22+
```
23+
curl -X 'POST' \
24+
'http://techcourse-lv2-alb-974870821.ap-northeast-2.elb.amazonaws.com/cart-items' \
25+
-H 'accept: */*' \
26+
-H 'Authorization: Basic <토큰>' \
27+
-H 'Content-Type: application/json' \
28+
-d '{
29+
"productId": 1,
30+
"quantity": 1
31+
}'
32+
```
33+
34+
### 리뷰 요청 & 논의하고 싶은 내용
35+
36+
### 1) 상태 설계 의도
37+
38+
### 2) 이번 단계에서 가장 많이 고민했던 문제와 해결 과정에서 배운 점
39+
40+
### 3) 이번 리뷰를 통해 논의하고 싶은 부분
41+
42+
---
43+
44+
## ✅ 리뷰어 체크 포인트
45+
46+
<!-- 리뷰어가 이 PR을 검토할 때 중점적으로 확인할 사항입니다.
47+
코드의 완성도뿐만 아니라, 리뷰이가 구현 과정에서 어떤 고민과 결정을 하며 학습했는지도 함께 고려해 주세요. -->
48+
49+
### 1. 클라이언트 상태관리
50+
51+
- 원본상태/파생상태를 적절히 구분하여 선언하였나요?
52+
- React state 를 불필요하게 선언한 부분은 없나요?
53+
- 상태 관리 로직의 책임이 적절히 응집/분리되었나요? (ex. reducer, hook, Context)
54+
55+
### 2. MSW/Test
56+
57+
- 주요 기능을 적절히 정의하였나요?
58+
- 주요 기능/예외에 대한 테스트가 충분히 이루어졌나요?

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ dist-ssr
2222
*.njsproj
2323
*.sln
2424
*.sw?
25+
26+
.env

.prettierrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"printWidth": 100,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": true,
6+
"singleQuote": true,
7+
"trailingComma": "es5",
8+
"bracketSpacing": true,
9+
"arrowParens": "always",
10+
"endOfLine": "auto"
11+
}

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
11
# react-shopping-cart
2+
3+
**기능 요구 사항**
4+
5+
- [x] **`/cart-items`** API를 호출하여 장바구니 상품 데이터를 불러온다.
6+
- [x] 개별 상품의 선택 여부, 결제 금액, 배송비 등의 상태를 관리한다.
7+
- [x] 상품 선택에 따른 주문 금액, 배송비 등의 동적인 변경 사항을 처리한다.
8+
- [x] 진입 시, 전체 선택 되어 있는 것이 디폴트이다.
9+
- [x] 상품 선택/해제 시 주문 금액을 동적으로 변경한다.
10+
- [x] 결제 금액이 10만원 이상일 경우 배송비는 무료이다.
11+
- [x] 장바구니 상품의 수량을 변경할 수 있다.
12+
- [x] 장바구니에 담긴 상품을 제거할 수 있다.
13+
- [x] 장바구니에 담긴 상품이 없는 경우 헬퍼문구를 보여준다.
14+
- [x] 주문 확인버튼을 클릭할 경우 페이지 이동과 함께 선택정보들과 결제금액을 보여준다.
15+
16+
**컴포넌트**
17+
18+
- [x] AppLayout
19+
- [x] Header
20+
- [x] CartItem
21+
- [x] CartItemList
22+
- [x] Text
23+
- [x] Flex
24+
- [x] Checkbox
25+
- [x] Button
26+
- [x] PriceSummary
27+
- [x] QuantityController
28+
29+
**테스트**
30+
31+
- [x] 장바구니 목록을 렌더링한다.
32+
- [x] 수량 조절 기능이 가능하다. (-/+)
33+
- [x] 주문 금액이 10만원 이상인 경우 배송비가 0원이 된다.
34+
- [x] 주문 금액이 10만원 이하인 경우 배송비가 3000원이 된다.
35+
- [x] 체크박스 선택 시 주문 금액에 변동이 생긴다.
36+
- [x] 장바구니에 담긴 상품 개수를 문구로 보여준다.
37+
- [x] 장바구니에 담긴 상품이 없는 경우 `장바구니에 담은 상품이 없다`라는 메세지를 보여준다.
38+
- [x] 삭제 버튼 클릭 시 장바구니에서 해당 상품이 삭제된다.
39+
- [x] 주문 확인 버튼을 클릭했을 때, 정보를 집약해서 보여준다.

eslint.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import js from '@eslint/js';
2+
import globals from 'globals';
3+
import tseslint from 'typescript-eslint';
4+
import pluginReact from 'eslint-plugin-react';
5+
import { defineConfig } from 'eslint/config';
6+
7+
export default defineConfig([
8+
{ files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], plugins: { js }, extends: ['js/recommended'] },
9+
{
10+
files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
11+
languageOptions: { globals: { ...globals.browser, ...globals.node } },
12+
},
13+
tseslint.configs.recommended,
14+
pluginReact.configs.flat.recommended,
15+
]);

index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<!DOCTYPE html>
2-
<html lang="en">
1+
<!doctype html>
2+
<html lang="ko">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
5+
<link rel="icon" type="image/svg+xml" href="./public/favicon.png" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>React Shopping Cart</title>
88
</head>

jest.config.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

jest.setup.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)