ARCHIVE/TOY_PROJECT

[React] Dashboard (TypeScript + Redux-toolkit)

man_on 2022. 2. 26. 20:04
반응형

 

https://github.com/manonkim/A_team_test

 

GitHub - manonkim/A_team_test

Contribute to manonkim/A_team_test development by creating an account on GitHub.

github.com

 

 

     


    Filtering 기능이 있는 Dashboard

     

    필터링 기능

      1. dropdown menu 클릭 시 checkbox 생성 (toggle + menu 바깥영역 클릭 시 close)
      2. checkbox 클릭
        : 견적 요청 카드 필터링 + dropdown menu에 클릭한 checkbox 카운팅 + Reset button 노출
      3. '필터링 리셋' 클릭 시 filtering 초기화
      4. '상담 중인 요청만 보기' Toggle button 클릭 시 status가 상담중인 카드만 필터링
      5. 조건에 맞는 카드가 없을 시 '조건에 맞는 견적 요청이 없습니다' 화면 노출

     

     

     

     

     

     

    GNB

      1. 로고, 가공업체, 로그아웃 버튼
      2. mobile 반응형 레이아웃 구현
        (메뉴버튼 클릭 시 슬라이드메뉴 : 백그라운드 영역음영 + 클릭 시 close)

     

     

     

     

     

     


     

     

     

     

     

    checkbox - filtering 기능

     

     

    •  toggle 버튼 클릭 시 status가 '상담중'인 카드만 보이기
    • checkbox에서 클릭한 재료만 렌더링

     

    toggle 기능은 간단하게 구현했는데 checkbox 필터링 기능은 왜인지 정말 오랫동안 되지가 않았다.

    하나만 필터링하는건 쉽게됬는데 중복선택할 때가 필터링이 되지않았는데

    문제의 해결은 useEffect에서 의존성배열에 어떤것을 넣는지에서 찾게되었다.

    상상치못한 전개,, 계속 filter 로직을 잘못짠줄알고 자바스크립트부터 다시 공부해야하나! 했는데..

    덕분에 삽질을 오래했다.

     

    //토글버튼
      useEffect(() => {
        toggle.checked === true
          ? setFilterData(data.filter((item: any) => item.status !== '대기중'))
          : setFilterData(data);
      }, [toggle.checked, data]);
    
    //checkbox filtering
      useEffect(() => {
        let datasave: datatype[] = data;
        filtering.methodItems.forEach((method) => {
          datasave = datasave.filter((item: datatype) =>
            item.method.includes(method)
          );
        });
        filtering.materialItems.forEach((material) => {
          datasave = datasave.filter((item: datatype) =>
            item.material.includes(material)
          );
        });
        setFilterData(datasave);
      }, [data, filtering.methodItems, filtering.materialItems]);

     

     

     

     

     


     

    ref - 외부영역 클릭 시 modal 창 닫기

     

     

     

      const [dropdown, setDropdown] = useState(false);    //기본 false시 닫기
      const modal = useRef();
    
      const dropdownHandler = () => {     //dropdown menu 영역 클릭시 열고닫기
        setDropdown(!dropdown);
      };
    
      const outsideClickHandler = (e: MouseEvent) => {       //외부영역 클릭시 닫기
        if (dropdown && !modal.current.contains(e.target)) {    
          setDropdown(false);      //ref지정영역(dropdoown menu) 밖 클릭 시 닫기
        }
      };
    
      useEffect(() => {
         //mousedown 클릭이벤트 발생 시 outsideClickHandler함수 호출
        document.addEventListener('mousedown', outsideClickHandler);
        return () => {
          //cleanup함수처리
          document.removeEventListener('mousedown', outsideClickHandler);
        };
      });
      
    
        //모달창 제일 상단에 ref위치
        <div className="Container" ref={modal}>   
          <div className="filterBox">
            <div className="filterWrap" onClick={dropdownHandler}>
              <p className="filterTitle">{title}</p>
               ...

     

     

     

     

     

    [참고사이트]

     

    https://velog.io/@miyoni/TIL37

     

    TIL37 | React | ref를 이용한 outside click 외부 클릭 감지

    Modal 창을 구현하다가 갑자기 공부하게 된..👀 ref와 JS의 EventListener를 사용하여 외부 클릭을 감지하기

    velog.io

     

     

     

     

     

     


     

     

     

     

     

     

     

    sidemenu 

     

     

    • navbar에서 메뉴버튼 누르면 sidemenu 왼쪽에서 open
    • 사이드메뉴 open시 백그라운드 영역 음영처리
    • background 클릭 시 menu close

     

     

    import SideMenu from './SideMenu';
    import { useState } from 'react';
    import './Nav.scss';
    
    const Nav = () => {
      const [onMenu, setOnMenu] = useState(false);
      const openMenu = () => {
        setOnMenu(!onMenu);
      };
      const closeMenu = () => {
        setOnMenu(false);
      };
    
     // return (
    
          {onMenu && <SideMenu close={closeMenu} />}
          <div className="navWrap">
            <img
              className="mobilemenu"
              src="../../img/menu.png"
              alt="menu"
              onClick={openMenu}
            />
            ...
    
      );
    };
    
    export default Nav;
    import './SideMenu.scss';
    
    export default function SideMenu(props: any) {
      //return (
        <div className="backdrop" onClick={props.close}>
          <div className="modal">
            <header className="sideMenuHeader">
              <img
                className="sidemenulogo"
                src="../../img/sidemenulogo.png"
                alt="sidemenulogo"
              />
            </header>
            <div className="sideMenuWrap">
              <img
                className="sideMenuIcon"
                src="../../img/sideMenu.png"
                alt="sidemenu"
              />
              <span className="sideMenu">파트너정밀가공</span>
            </div>
            <div className="sideMenulogout">로그아웃</div>
          </div>
        </div>
      );
    }
    .backdrop {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100vh;
      z-index: 10;
      background: rgba(0, 0, 0, 0.5);
    }
    ...

     

     

     

     

     


     

    TIL

     

     

     

    - Redux와 typescript를 개인적으로 공부하기는 했지만 강의를 보면서 따라해보고 정리하고 한게 전부였는데,

       프로젝트에 (프로젝트라고 하기에는 소박하지만) 스스로 사용해보는 것이 처음이라 스스로의 발전에 아주 도움이 되었던 제작이었다.

     

    - Redux toolkit을 쓸 정도의 규모가 아니었지만, 사용해보고 싶었다...

       

    - Typescript는 내가 코드 한줄 치려고하면 '안돼!!!안된다고!!!!'  난리법석이어서 당최 진도를 못나가게 하는 걸림돌이었다.

       쓰다가 열받는 상황이 이어져서 any를 남발했지만,

       어느정도 기능을 구현하고 typescript만 따로 찾아보면서 any를 바꿔가는 작업을 진행해보니까

       왜, 무엇을 type으로 지정해줘야 하는지 조금은 감이 잡혔다. 

        (아직 해결하지못한 any가 몇개있지만...)

        typescript는 따로 정리!

     

    반응형