대시보드 기능 보완

SuweonPark·2024년 2월 5일
0

대시보드

목록 보기
5/5

사이드바 on/off 기능

사이드바 on

사이드바 off

사이드바 on/off 기능은 SideBar 컴포넌트에서

 const [toggle, setToggle] = useRecoilState(sidebarToggle);

<button
  type="button"
  className={`side_toggle ${!toggle && 'close'}`}
  onClick={() => setToggle(!toggle)}
  >

간단하게 toggle 불리언값에 따라 조건부 렌더링으로 구현하였습니다.
이 sidebarToggle state는 다른 컴포넌트에서도 사용하기 때문에
Recoil을 사용해 전역관리 하였습니다.

sidebar가 생기거나 사라질 때 위젯들이 차지하는 레이아웃의 크기가 달라지기 때문에
WidgetLayout 컴포넌트에서 sidebarToggle state를 위젯들의 크기를 조정하는데 사용하였습니다.

const sidebarToggleState = useRecoilValue(sidebarToggle);

const [dynamicWidth, setDynamicWidth] = useState(
  Math.max(windowWidth - 330, 1600)
);

useEffect(() => {
  if (sidebarToggleState) {
    setDynamicWidth(Math.max(windowWidth - 330, 1600));
  } else {
    setDynamicWidth(Math.max(windowWidth - 35, 1600));
  }
}, [sidebarToggleState]);

탑바 on/off

탑바 on

탑바 off

탑바가 활성화된 상태 비활성화된 상태로 나뉘며 탑바 on/off에 따라 위젯들의
높이가 달라집니다. 마찬가지로 WidgetLayout 컴포넌트에서 관리하였습니다.

const [topSummaryOpen, setTopSummaryOpen] = useRecoilState(isTopModalState);
const [toggle, setToggle] = useState(topSummaryOpen);
const [dynamicHeight, setDynamicHeight] = useState(
  Math.max((windowHeight - 118) / 4, 206.69)
);

// 탑바 토클 버튼 이벤트 핸들러
const handleTopSummary = () => {
  setTopSummaryOpen(!topSummaryOpen);
  if (topSummaryOpen) {
    setDynamicHeight(Math.max((windowHeight - 118) / 4, 206.69));
  } else {
    setDynamicHeight(Math.max((windowHeight - 185) / 4, 206.69));
  }
};

탑바 데이터가 달라질 때 애니메이션

<div key={currentIndexState}>탑바 코드</div>

탑바 최상위 요소에 key값을 부여해서 데이터가 바뀔때마다 리액트에서 요소룰 다시 생성하는 방법으로 애니메이션 적용을 하였습니다.

탑바 안에 있는 요소의 데이터가 바뀔경우

  const [animationStates, setAnimationStates] = useState({
    ani03state: true,
    ani04state: true,
    ani05state: true,
  });
  const aniHandler = (key) => {
    setAnimationStates((prevStates) => ({
      ...prevStates,
      [key]: false,
    }));
    setTimeout(() => {
      setAnimationStates((prevStates) => ({
        ...prevStates,
        [key]: true,
      }));
    }, 300);
  };

// 현장 코드 데이터와 날씨, 디데이, 공정률 위젯 데이터
const { data: widgetData } = useQuery(
  ['WidgetList', userInfo.userId, selectedSiteCode],
  () =>
  getWidgetInfo(
    userInfo.userId,
    [selectedSiteCode],
    ['weather', 'dday', 'processrate']
  ),
  {
    onSuccess: (data) => {
      if (
        (topbarDataInit && pageInfo.pageType === 'site') ||
        (topbarDataInit &&
         pageInfo.pageType === 'region' &&
         !circulationState)
      ) {
        if (
          data.siteList[0].widgetList[0].data.temperature !==
          widgetListState[0]?.data?.temperature ||
          data.siteList[0].widgetList[0].data.sky !==
          widgetListState[0]?.data?.sky
        ) {
          aniHandler('ani03state');
        }
        if (
          data.siteList[0].widgetList[0].data.maxTemp !==
          widgetListState[0]?.data?.maxTemp ||
          data.siteList[0].widgetList[0].data.minTemp !==
          widgetListState[0]?.data?.minTemp
        ) {
          aniHandler('ani04state');
        }
        if (
          data.siteList[0].widgetList[0].data.pm25Value !==
          widgetListState[0]?.data?.pm25Value ||
          data.siteList[0].widgetList[0].data.pm10Value !==
          widgetListState[0]?.data?.pm10Value
        ) {
          aniHandler('ani05state');
        }
      }
      setTopbarDataInit(true);
    },
    refetchInterval: 30 * 60 * 1000,
    // cacheTime: 6000 * 1000
    // refetchInterval: 6000 * 1000,
  }
);

{animationStates.ani04state ? (
  <div className="temp ani ani04">
    <div>
      <strong>
        {widgetListState && widgetListState[0]?.data?.maxTemp}</strong>
      <span className="high">최고</span>
    </div>
    <div>
      <strong>
        {widgetListState && widgetListState[0]?.data?.minTemp}</strong>
      <span className="low">최저</span>
    </div>
  </div>
) : (
  <div className="temp">
    <div>
      <strong>
        {widgetListState && widgetListState[0]?.data?.maxTemp}</strong>
      <span className="high">최고</span>
    </div>
    <div>
      <strong>
        {widgetListState && widgetListState[0]?.data?.minTemp}</strong>
      <span className="low">최저</span>
    </div>
  </div>
)}

리액트 쿼리를 사용해 30분 마다 데이터를 받아올 때 이전값과 받아온 데이터 값을 비교해 해당 컴포넌트에 조건부 렌더링을 걸어서 애니메이션 효과가 다시 적용되도록 구현하였습니다.

profile
프론트엔드 개발자

0개의 댓글