디즈니샵
https://www.shopdisney.com/
제품 카테고리를 줄이고 기능적인 측면을 구현하는데에 집중하기로 하였으며, 자세한 내용은 하기와 같습니다.
7개 카테고리와 3개 브랜드로 축소 구현기획전 배너 2개, 추천상품 영역 1개제품탐색(필터링,검색) - 찜하기 - 장바구니 넣기 - 결제의사결정록 notion 도입

특정 안건 열람이 어려운 standing회의록의 단점 보완하고자 의사결정록 도입.
이슈를 한눈에 열람하고 구성원간 공유 원활히 할 수 있도록 함.
trello + BigPicture
트렐로 카드는 개별 업무단위를, BigPicture는 전체 진도율 관리.

크게 3가지 단위와 추가구현기능으로 업무를 나누었고,
붉은 테두리의 영역을 맡아 구현하기로 함.
제품데이터를 사전에 픽스함으로써 기능의 범위가 명확해졌으며, Backend와의 소통 원활해짐. 아울러 프로젝트 막바지에 신경쓰기 어려운 이미지작업을 사전에 마쳐놓음으로써 팀원들이 개발에만 전념할 수 있는 환경 조성GIT : https://github.com/JaySurplusYoon/31-1st-kidsney-frontend

필터, 가격순정렬, 검색, 페이지네이션 4가지로 구분.
useLocation에서 url을 받아 렌더링하는 방법 사용할 수 없음.state에 저장하여 렌더링의 대상이 되는 queryString으로 만들어 렌더링하는 방식으로 구현함.(1) Product List에서는 Filter, Sorter, Search, Pagination에 필요한 state와 이를 수정할 수 있는 function을 만들어 각각의 컴포넌트로 전달.
const handleFilter = (name, attr) => {
const filterArr = [...filters];
filterArr.includes(`${name},${attr}`)
? filterArr.splice(filterArr.indexOf(`${name},${attr}`), 1)
: filterArr.push(`${name},${attr}`);
setFilters(filterArr);
setQueryStrings(filterArr);
};
※필터의 경우 1회 클릭시 적용, 중복 클릭시 적용이 해제되므로, Splice로 중복된 인덱스의 필터배열을 제거하도록 함.
(2)각각의 컴포넌트에서는 onClick, onChange 등을 통해 내려받은 function으로 부모의 state를 수정하고 끌어올림.
<li
key={categoryAttr}
className="categoryAttr"
onClick={() => handleFilter(categoryName, categoryAttr)}
>
(3)끌어올린 state값으로 queryParameter를 만들고 이에 의존성에 있는 useEffect내부의 fetch함수로 화면을 렌더링.
switch (splittedFilter[0]) {
case 'sub':
addParamFilters.push(`&sub=${param}-${splittedFilter[1]}`);
break;
case 'size':
addParamFilters.push(`&size=${splittedFilter[1]}`);
break;
case 'character':
addParamFilters.push(`&character=${splittedFilter[1]}`);
break;
default:
}


(1)배송정보 유효성 검사 후, 고객이 입력한 주소를 기본배송지로 업데이트하겠다는 의사를 확인하고 이에 따라 결제대금 차감 및 주소 업데이트 진행.
const submitOrder = () => {
if (orderNecessaryInfo) {
if (orderInfo.updateAddress) {
postBalance();
patchAddress();
} else {
postBalance();
}
} else alert('정보를 모두 입력해주세요');
};
(2)결제는 POST방식으로 서버와 통신하여 진행하며 처리결과는 alert로 안내.
const postBalance = () => {
fetch(`${BASE_URL}/orders`, {
method: 'POST',
headers: {
Authorization: localStorage.getItem('token'),
},
body: JSON.stringify({
total_price: subtotal,
}),
})
.then(response => {
if (response.ok) {
alert('주문이 완료되었습니다.');
} else if (response.message === 'moneyless') {
alert('잔액이 부족합니다.');
} else if (response.message === 'stockless') {
alert('재고가 부족합니다.');
} else {
throw new Error('Unexpected Error');
}
})
.catch(error => {
// eslint-disable-next-line no-console
console.log(error.message);
});
};
(3)주소 업데이트는 PATCH방식으로 서버와 통신하여 진행하며 처리결과는 alert로 안내.
const patchAddress = () => {
fetch(`${BASE_URL}/users/`, {
method: 'PATCH',
headers: {
Authorization: localStorage.getItem('token'),
},
body: JSON.stringify({
zip_code: orderInfo.zipCode,
location: orderInfo.addressMain,
datail_address: orderInfo.addressDetail,
}),
})
.then(response => {
if (response.ok) {
alert('주소변경이 완료되었습니다.');
} else {
throw new Error('Unexpected Error');
}
})
.catch(error => {
// eslint-disable-next-line no-console
console.log(error.message);
});
};