LogChart 핸들링(10 minute chart 만들기)

2022. 1. 4. 16:51
반응형

토글 & 로그차트 프로토타입

토글 아래 보이는 것 처럼 시간을 기록하면 차트에 막대 그래프 처럼 채워지는 10 minute chart를 구현해야 한다.

처음 구상한 로직은 하루를 분으로 계산하면 1440분 이니까 차트를 144개 박스로 나눠서 시간 정보를 받으면 분으로 환산해서 10으로 나누면 144개 박스에 대한 index로 해당하는 박스에 막대를 채워주면 될 것이라 생각했다.

그 결과는?

Uncaught RangeError: Maximum call stack size exceeded

144개의 빈 배열에 시간 정보가 있으면 그것에 해당하는 색깔을 값으로 넣어주고, 없으면 빈 문자열을 넣어줘서 한칸 한칸 채워주는 식으로 로직을 짜다보니, 매번 시간 정보를 받아올 때 마다 144번의 계산이 이루어지고, 쓸데없는 작업을 시켜주고 있었다.

그래서 144개의 칸으로 나누지 않고 해줄 수 있는 방법을 고민했다.

그래서 미리 칸을 나누지 않고 그냥 받아오는 정보를 가지고 막대를 만들어주는 로직을 구현해 보았다.

// 막대가 될 styled-component
const Log = styled.div`
  margin-top: 1%;
  position: absolute;
  height: 3%;
  top: ${(props) => props.top}%;
  width: ${(props) => props.width}%;
  left: ${(props) => props.left}%;
  background-color: ${(props) => `var(--color-${props.color})`};
`;

// API 요청 보낼때 필요한 date, offset 값을 상위 컴포넌트에서 전달받고 있다.
function LogChart({ date, offset }) {
  const { isLogin } = useSelector(({ userReducer }) => userReducer);
  const [log, setLog] = useState([]);

  const fillLog = (loglist) => {
    const newLog = [];
    for (let i = 0; i < loglist.length; i++) {
      const studylog = [...loglist][i];
      const start = studylog.startedAt;
      const finish = studylog.finishedAt;
      const startTime = Math.floor(start / 60);
      const finishTime = Math.floor(finish / 60);

      for (let i = startTime; i <= finishTime; i++) {
        if (i === startTime) {
          newLog.push({
            name: studylog.name,
            color: studylog.color,
            top: i * (100 / 24),
            left: (start % 60) * (5 / 3),
            width: (finish - start) * (5 / 3),
            hour: Math.floor((finish - start) / 60),
            minute: (finish - start) % 60,
          });
        } else if (i > startTime && i !== finishTime) {
          newLog.push({
            name: studylog.name,
            color: studylog.color,
            top: i * (100 / 24),
            left: 0,
            width: 100,
            hour: Math.floor((finish - start) / 60),
            minute: (finish - start) % 60,
          });
        } else if (i === finishTime) {
          newLog.push({
            name: studylog.name,
            color: studylog.color,
            top: i * (100 / 24),
            left: 0,
            width: (finish - 60 * i) * (5 / 3),
            hour: Math.floor((finish - start) / 60),
            minute: (finish - start) % 60,
          });
        }
      }
      setLog([...newLog]);
    }
  };

  const getLogsHandler = () => {
    logAPI
      .getLogs(date, offset)
      .then((res) => {
        const studylogList = res.data.studylogList.map((list) => {
          const start =
            new Date(
              date.slice(0, 4),
              Number(date.slice(4, 6)) - 1,
              date.slice(6, 8)
            ).getTime() / 60000;
          const startedAt = list.startedAt - start;
          const finishedAt = list.finishedAt - start;
          const newList = { ...list, startedAt, finishedAt };
          return newList;
        });
        fillLog(studylogList);
      })
      .catch(() => {
        dispatch(loginStateChange(false));
        dispatch(sideLogOpen(false));
        dispatch(modalOff());
        navigate("/home");
        dispatch(signinModalOpen(true));
      });
  };

  useEffect(() => {
    if (isLogin) getLogsHandler();
    // eslint-disable-next-line
  }, []);

top은 시간, width는 분, left는 막대가 채워지는 지점이라고 생각하고 로직을 만들었고, 이것을 가공해서 나온 값들을 props로 전달해서 막대가 채워지도록 10 minute chart를 완성할 수 있었다.

완성된 결과

반응형
LIST

'코드스테이츠 수강 TIL > Final Project' 카테고리의 다른 글

final_project DAY+10  (0) 2022.01.04
final_project DAY+9  (0) 2022.01.04
final_project DAY+8  (0) 2022.01.04
final_project DAY+7  (0) 2022.01.04
final_project DAY+6  (0) 2022.01.03

BELATED ARTICLES

more