[Project] Pre-onboarding: Sir.Loin

🏃🏻‍♀️ 프로젝트 기간 및 인원

📆 2022년 1월 27일 ~ 1월 29일 / Front-end 4명

👀 Repository

배포주소
깃헙주소

🍕 기술 스텍

Front-end

  • React
  • Styled-components

Common

  • Github
  • Slack

✏️ 과제 개요

상품과 관련된 기본 정보, 등록, 주문, 배송, 프로모션 등 여러 옵션을 관리할 수 있는 사이트를 구현한 프로젝트. 필터 함수와 커스텀 토글 버튼을 활용하여 상품의 노출을 변경하는 것이 주된 기능이다.

💻 과제 구현 목록

노출 및 판매기간 설정

  • Material-UI 라이브러리 활용하여 달력 및 시간 지정 컴포넌트.
  • 설정한 기간이 만료되었을 경우, 자동으로 state 변경되는 기능.
  • 설정한 기간내 날짜 선택 비활성화 기능.
  • 한 버튼이 활성화되면 다른 버튼이 비활성화되는 기능.

상품 기본 정보(본인 담당)

  • 체크박스 선택 및 해제를 통해 상품에 카테고리 지정 및 해제 기능.
  • 썸네일 이미지 하나의 이미지만 업로드 가능.
  • 상품명 선택시 해당 상품코드 화면 출력.

상품 옵션

  • 추가 및 삭제 버튼 눌렀을 때 컴포넌트가 추가로 생성 및 삭제되는 기능.

상품 소개이미지, 구매자 추천 이미지

  • 사용자에게 이미지 업로드 영역 제공 및 업로드된 이미지 파일명 노출 기능.
  • 업로드된 이미지 삭제 버튼을 통해 업로드 상태에서 삭제.

상품 배송 설정

  • 커스텀 토글 버튼

상품 혜책 허용 설정, 기타 설정

  • 커스텀 토글 버튼

🙋🏻‍♀️ 구현 내용

카테고리 지정

  • 체크박스 선택을 통해 해당 상품에 카테고리를 지정할 수 있음
  • '체크박스 지정 해제' 또는 카테고리 X버튼을 통해 카테고리 지정을 해제할 수 있음

카테고리 리스트와 상품명 상수데이터로 관리하기

함수 안에 있으면 리렌더 될때마다 데이터가 불러와지는데, 상수데이터는 변하지 않는 데이터이므로 메모리 누수를 하면서 함수 안에 위치시킬 필요가 없다.

const CATEGORY_LIST = [
  { id: 0, data: '구이용' },
  { id: 1, data: '안심' },
  { id: 2, data: '등심' },
  { id: 3, data: '채끝' },
  { id: 4, data: '특수' },
  { id: 5, data: '양념' },
  { id: 6, data: 'Bone' },
  { id: 7, data: '선물제안' },
  { id: 8, data: '이벤트' },
  { id: 9, data: '요리용' },
  { id: 10, data: '무료배송' },
  { id: 11, data: '세트' },
];

체크박스, 카테고리 선택 및 해제를 통한 상품 기본 정보 노출

  • 자세한 설명은 주석처리
function ProdBasicInfo() {
  
  // 카테고리를 클릭했을 때 값을 바꿔주는 state. 초기값은 빈배열.
  const [checkedList, setCheckedList] = useState([]);
 
  // onChange이벤트를 통해서 checked(Boolean)값, item(value)값을 받아온다.
  const onCheckedElement = (checked, item) => {
    // check되었을때 check된 value값을 빈배열인 checkedList에 업데이트를 해준다
    if (checked) {
      setCheckedList([...checkedList, item]);
    } 
   /* filter함수는 반환값이 true인것만 구성된 새로운 배열을 반환한다.
    클릭된값이 item이고 item이 el랑 다른 경우가 true, 즉 클릭된 요소가 빠진 배열을 반환하는 것임. */
    else if (!checked) {
      setCheckedList(checkedList.filter(el => el !== item));
    }
  };
  
  /*체크박스가 아닌 카테고리 배너의 x를 클릭했을 때 해제되는 기능.
  위에있는 체크박스 해제하는 원리와 동일하게 동작함!*/
  const onRemove = item => {
    setCheckedList(checkedList.filter(el => el !== item));
  };
  
return (
      <S.CategoryContainer>
        <S.SubTitle>카테고리 *</S.SubTitle>
        <S.SelectContainer>
          <S.CheckBox>
  // 상수데이터 카테고리 리스트에 맵을 활용하여 렌더링 함
            {CATEGORY_LIST.map(item => {
              return (
             /* 고유 key값 부여. 
             배열을 렌더링 했을 때 key값을 통해 배열의 어떤 원소에 변화가 있었는지를 알아낸다.*/
                <S.Label key={item.id}>
  /*여기서 Check는 Input태그. type을 체크박스로 지정하고 
  value값은 CATEGORT_LIST의 data값으로 지정*/
                  <S.Check
                    type="checkbox"
                    value={item.data}
// onChange이벤트를 통해 변화를 감지하고 onCheckedElement함수에 check여부와 check된 value값을 전달해준다.
                    onChange={e => {
                      onCheckedElement(e.target.checked, e.target.value);
                    }}
                    // 선택된 상태를 말하는 것. checkeList에 요소가 있으면 true, 없으면 false.
                    checked={checkedList.includes(item.data) ? true : false}
                  />
// 체크박스 리스트에 출력될 data값.
                  <S.Type>{item.data}</S.Type>
                </S.Label>
              );
            })}
          </S.CheckBox>
          <S.SelectedBox>
            /* 카테고리란
           checkedList의 길이가 0이라면 빈배열이란 뜻으로 기본값이 '카테고리를 지정해 주세요' 문구를 출력한다.*/
            {checkedList.length === 0 && (
              <S.AlertMessage>카테고리를 지정해 주세요.</S.AlertMessage>
            )}
            // 선택된 값들을 관리하는 것이므로 checkedList에 map을 활용한다.
            {checkedList.map(item => {
              return (
                <S.SelectedCategory key={item}>
                  <S.Selected>{item}</S.Selected>
                  <S.CancelChecked onClick={() => onRemove(item)}>
                    X
                  </S.CancelChecked>
                </S.SelectedCategory>
              );
            })}
          </S.SelectedBox>
        </S.SelectContainer>
      </S.CategoryContainer>
 );
}

상품명 선택 시 해당 상품 코드 화면에 출력

마찬가지로 상품 리스트는 상수데이터로 관리하기

const PRODUCT_DATA = [
  { id: null, value: '상품을 선택하세요.' },
  { id: '0001', value: '알꼬리 300g' },
  { id: '0002', value: '미니샤토 150g' },
  { id: '0003', value: '안심추리 150g' },
  { id: '0004', value: '안심슬라이스 150g' },
  { id: '0005', value: '립아이' },
  { id: '0006', value: '로스 등심 200g' },
  { id: '0007', value: '꽃등심 200g' },
  { id: '0008', value: '채끝 등심 200g' },
];

드롭다운 메뉴에서 선택되는 상품의 상품코드 가져오기 & 출력

  • 위와 마찬가지로 filter함수를 써서 데이터에 접근한다(자세한 내용은 주석으로 작성)
function ProdBasicInfo() {
  
  // 상품명, 상품코드 출력을 위한 state
  const [selectedDropValue, setSelectedDropValue] =
    useState('상품을 선택하세요.');

const handleDropProduct = e => {
  // e.target.value. 구조분해로 e.target에서 타겟팅 된 요소의 value를 가져옴. 즉, 선택된 요소!
    const { value } = e.target;
  // PRODUCT_DATA는 id(상품코드)와 value(상품명)로 구성된 객체들로 구성된 배열. filter함수를 써서 선택된 상품명과 PRODUCT_DATA 에 있는 상품명이 일치하는 배열을 반환. 인덱스 0과 id를 사용하여 배열 안에 있는 객체에 접근하여 id값을 추출한다. id값이 상품코드. 이 id값을 selectedDropValue에 업데이트.
    setSelectedDropValue(PRODUCT_DATA.filter(el => PRODUCT_DATA.filter(el => el.value === value)[0].id));
  };

return (
<S.ProductNameContainer>
        <S.SubTitle>상품명 *</S.SubTitle>
        <S.ProductBar>
  // select태그와 option태그를 사용하여 드롭다운 메뉴를 만들었다.
          <S.ProductSearch onChange={handleDropProduct}>
            {PRODUCT_DATA.map(el => {
              return (
                <option key={el.id}>
                  {el.value}
                </option>
              );
            })}
          </S.ProductSearch>
        </S.ProductBar>
        <S.ProductCode>
          <S.Code>상품 코드</S.Code>
// 상품코드 출력
          <S.ShowingCode>{selectedDropValue}</S.ShowingCode>
        </S.ProductCode>
      </S.ProductNameContainer>
 );
}

좋은 웹페이지 즐겨찾기