본문 바로가기
원티드 프리온보딩

원티드 프리온보딩 과제 - 견적 요청서 페이지

by 도현위키 2022. 2. 12.

 

 

내가 맡은 역할

- figma 명세에 따라 반응형 디자인 구현

- 필터링 기능 구현

 

반응형 세팅

Breakpoints는 크게 PC(xlarge), Tablet(medium), Mobile(small)로 나누고, 중간 pc -> tablet으로 가는 과정 중에 필요한 사이즈인 1130px도 추가했다.

 

enum Breakpoints {
  xlarge = 1440,
  large = 1130,
  medium = 748,
  small = 360,
}

export default Breakpoints;

 

방금 만든 Breakpoints를 기반으로 아래와 같이 mediaQuery 함수를 만들었다. 

import Breakpoints from "./breakpoints";

const mediaQuery = (maxWidth: number) => `@media (max-width: ${maxWidth}px)`;

const { xlarge, large, medium, small } = Breakpoints;

const media = {
  xlarge: mediaQuery(xlarge),
  large: mediaQuery(large),
  medium: mediaQuery(medium),
  small: mediaQuery(small),
  custom: mediaQuery,
};

export default media;

 

mediaQuery 함수의 사용법은 아래와 같다.

 ${media.large} {
    background-color: green;
 }
 
 ${media.medium} {
    background-color: blue;
 }

 

 

필터링 기능

필터링의 요구 사항을 분석하면 아래 사진과 같이 3단(가공 방식, 재료, 상담)으로 이뤄진 필터를 구현해야 한다.

3단 필터링 요소

 

데이터 형식은 아래처럼 주어지는데 

{
    "requests": [
        {
          "id": 1,
          "title": "자동차 시제품 제작",
          "client": "A 고객사",
          "due": "2020.12.14",
          "count": 2,
          "amount": 100,
          "method": ["밀링", "선반"],
          "material": ["알루미늄"],
          "status": "대기중"
        },
        {
          "id": 2,
          "title": "비행기 시제품 제작",
          "client": "B 고객사",
          "due": "2020.12.13",
          "count": 2,
          "amount": 100,
          "method": ["선반"],
          "material": ["탄소강", "강철"],
          "status": "상담중"
        },
        {
          "id": 3,
          "title": "기차 시제품 제작",
          "client": "C 고객사",
          "due": "2020.12.12",
          "count": 1,
          "amount": 20,
          "method": ["선반"],
          "material": ["구리"],
          "status": "대기중"
        },
        {
          "id": 4,
          "title": "자전거 시제품 제작",
          "client": "D 고객사",
          "due": "2020.12.11",
          "count": 1,
          "amount": 45,
          "method": ["선반"],
          "material": ["스테인리스강"],
          "status": "대기중"
        },
		...
    ]
 }

 

데이터에 있는 method, material, status 세 가지의 필터링이 작동해야 한다.

 

가공 방식 메뉴에서 밀링을 고르게 되면 아래 처럼 밀링을 포함하고 있는 요소들이 나오고

 

 

추가적으로 재료메뉴에서 알루미늄을 누르게 되면 가공방식의 밀링과 재료의 알루미늄을 포함하는 요소들이 나오게 된다

 

 

또한 상담 중의 옵션도 가공방식 + 재료 메뉴와 같이 필터링이 적용된다.

상담 중 On

 

 

처음에 생각했던 방식은 각 데이터를 돌면서 선택된 가공방식을 포함하는지 체크하고, 선택된 재료를 포함하는지 체크하고, 상담 중 상태와 동일한 요소들을 반환하도록 구현하였지만, 이렇게 되면 데이터가 많아지게 되면 시간 복잡도가 n^3이 된다.

 

어떻게 하면 시간 복잡도를 줄일 수 있을까? 하고 고민을 하다가, 선택된 요소가 포함되는지 안되는지만 체크하는데 굳이 3단으로 나눌 필요가 있을까? 하는 생각이 떠올랐다.

 

한번 모든 필터 요소를 한 곳에 모아두기로 하고 각 데이터에 filters라는 속성을 추가해서 필터 요소들을 모아 봤다.

  useEffect(() => {
    if (!data) return;
    
    setRequestList(data.map((request) => ({
      ...request,
      filters: [...request.method, ...request.material, request.status],
    })));
    
  }, [data]);

 

데이터 형식은 다음과 같아진다.

{
    "requests": [
        {
          "id": 1,
          "title": "자동차 시제품 제작",
          "client": "A 고객사",
          "due": "2020.12.14",
          "count": 2,
          "amount": 100,
          "method": ["밀링", "선반"],
          "material": ["알루미늄"],
          "status": "대기중",
          "filters": ["밀링", "선반", "알루미늄", "대기중"]
        },
        {
          "id": 2,
          "title": "비행기 시제품 제작",
          "client": "B 고객사",
          "due": "2020.12.13",
          "count": 2,
          "amount": 100,
          "method": ["선반"],
          "material": ["탄소강", "강철"],
          "status": "상담중",
          "filters": ["선반", "탄소강", "강철", "상담중"]
        },
        ....

    ]
 }

 

이렇게 filters 속성 한 곳에 다 모아두었더니, 굳이 3번이나 걸쳐 확인을 하지 않고 filters 속성만 체크를 하면 돼서 간단히 필터링을 할 수 있게 되었다.

const onFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name } = e.target;
    
    const selectedFilterList = selectedFilters.includes(name)
      ? selectedFilters.filter((filter) => filter !== name)
      : [...selectedFilters, name];
    setSelectedFilters(selectedFilterList);

    setRequestList(
      originalData.current.filter((request) =>
        selectedFilterList.every((item) => request.filters.includes(item))
      )
    );
 }

 

 

 

 

마무리

2주차라 그런지 1주 차 때에 비해 팀워크가 너무 잘 맞았다. 프로젝트를 하는 동안 조금 친해졌기도 하고, 1주 차 때 열심히 코드 컨벤션, 폴더 구조, 스타일 코드들을 맞췄더니 이번 주에는 과제에만 집중을 할 수 있었다. 남은 과제도 팀원분들이랑 잘 해결했으면 좋겠다! 원티드 프리온 보딩 8팀 파이팅!

 

 

 

 

댓글