git clone // this repository
cd this file location
npm install
npm run dev
1. 초기설계 (데이터 구조 및 폴더구조)를 확실히 했다.
2. 단일 책임 원칙과 개방 폐쇄 원칙을 지키는 클린 코드를 사용하려 노력
3. 페이지와 재사용 가능한 컴포넌트의 역할 분리 - 가독성 증가
4. 기능별 구현 후 PR을 통해 코드 리뷰 후 merge 진행
a. Redux slice 관심사 분리
- trip과 reservation 두개로 나눔
a. 여행 상품 정보 노출
- 확장성을 고려하여 axios를 이용해 mock JSON 받아오는 api 작성
- redux thunk를 이용해 비동기 처리
b. 필터
- 필터 로직 재사용을 위해 지역별, 가격별 필터링 함수 별개로 작성
c. 모달
- chakra ui내의 모달 컴포넌트를 불러와서 예약 상품 컴포넌트에서 호출
a. localStorage를 활용한 persistence 유지
b. 구매수량 변경 가능 및 리스트 삭제 가능
c. 여행 상품의 총 결제액 계산
pages => a. page 의 전체적인 레이아웃 설정
b.각 컴포넌트들의 집합용도
components => a. 재사용 가능성이 존재하는 컴포넌트들의 모듈화된 집합
b. 실제 화면에 구현되는 컴포넌트
store => a. 상태관리가 필요한 데이터들의 저장
b. selector 내에 데이터 전처리 로직 생성
utils => a. 앱 전반적으로 공통사용할 로직
export const searchedTripLists = createSelector([selectCartReducer], trips => {
const { searchCategory, tripList } = trips
const { priceRange, selectSpace } = searchCategory
const spacesortedTripList = tripList.filter(trip => {
return selectSpace.length ? selectSpace.includes(trip.spaceCategory) : trip
})
return spacesortedTripList.filter(
list => list.price >= priceRange[0] && list.price <= priceRange[1]
)
})
const reservationSlice = createSlice({
name: 'reservation',
initialState,
reducers: {
addReservationList: (state, action: PayloadAction<ITripInfo>) => {
const newReservationItems = addReservationItem(
state.reservationItems,
action.payload
)
setLocalStorageItem('reservation', newReservationItems)
state.reservationItems = newReservationItems
},
//... 중략
}
}
// 총 결제액
export const selectReservationTotal = createSelector(
[selectReservationItems],
reservationItems =>
reservationItems.reduce(
(total, reservationItem) =>
total + reservationItem.quantity * reservationItem.price,
0
)
)
// 예약 상품 수량 계산
export const selectReservationCount = createSelector(
[selectReservationItems],
reservationItems =>
reservationItems.reduce(
(total, reservationItem) => total + reservationItem.quantity,
0
)
)
강명훈 | 김진영 | 백유리 | 김유신 |
---|---|---|---|
최명식 | 안윤경 | 구본아 | 김재욱 |
idx, name, mainImage, price, spaceCategory
idx, name, mainImage, description, spaceCategory, price, maximumPurchases, registrationDate
0~1000
, 1500~3000
📦src
┣ 📂api
┃ ┗ 📜tripApi.tsx
┣ 📂components
┃ ┣ 📂filter
┃ ┃ ┗ 📜SelectBox.tsx
┃ ┣ 📂modal
┃ ┃ ┗ 📜CardModal.tsx
┃ ┣ 📂reservation
┃ ┃ ┣ 📜CheckoutItem.tsx
┃ ┃ ┗ 📜ReservationList.tsx
┃ ┣ 📂trip
┃ ┃ ┣ 📜TripCard.tsx
┃ ┃ ┗ 📜TripList.tsx
┃ ┗ 📂ui
┃ ┃ ┗ 📜logo.tsx
┣ 📂data
┃ ┗ 📜mock_data.json
┣ 📂pages
┃ ┣ 📜MainPage.tsx
┃ ┣ 📜NavigationPage.tsx
┃ ┣ 📜NotFoundPage.tsx
┃ ┗ 📜ReservationPage.tsx
┣ 📂store
┃ ┣ 📂reservation
┃ ┃ ┣ 📜reservationSelector.ts
┃ ┃ ┗ 📜reservationSlice.ts
┃ ┣ 📂trip
┃ ┃ ┣ 📜tripSelector.ts
┃ ┃ ┗ 📜tripSlice.ts
┃ ┗ 📜store.ts
┣ 📂utils
┃ ┣ 📜dateConvertor.ts
┃ ┗ 📜localStorage.ts
┣ 📜App.css
┣ 📜App.tsx
┣ 📜Type.ts
┣ 📜index.css
┣ 📜main.tsx
┣ 📜setupTests.ts
┗ 📜vite-env.d.ts