(8) Time tracking dashboard

쥬롬의 코드착즙기·2022년 7월 15일
0

Frontend Mentor Challenge

목록 보기
8/11
post-custom-banner

Frontend Mentor - Time tracking dashboard solution

이 솔루션은 Time tracking dashboard challenge on Frontend Mentor 챌린지 참여 결과물입니다.

차례

소개

챌린지

시간 관리 웹페이지를 만들었다.
react component로 화면을 구성했고,
json 파일을 읽어들여서
클릭한 버튼에 따라 화면이 바뀌도록 했다.

화면-스크린샷

링크

배운-점

사용-tool

  • CSS
  • REACT <<< new!

새롭게-배운-것

삽질포인트가 두 개 있었다.

  1. 컴포넌트 for문으로 반복 호출하기

가장 어려웠던 것은 TrackedTime 컴포넌트 6개를 for문으로 호출해내는 것이었다.
(그냥 return 문 안에서



...
이런 식으로 복붙하는게 제일 쉽고 어쩌면 더 깔끔했을 것 같지만
연습을 위해서 어떻게든 복붙은 피해보려고 했다.)

시도해본 오답들은 아래와 같다.

(1) return문 안에서 for문 쓰기

function App{
  //unrelated codes...
  return (
    for(let i=0; i<timedata.length(); i++){
        <TrackedTime title={timedata[i].title} timeframes={Timeframe} current={timedata[i].current} previous={timedata[i].previous}  />
    }
  )
}

(timedata[i].current, timedata[i].previous도 안된다. 해결방법은 후술한다.)
구글링해본 결과 이건 그냥 문법적으로 안된다. jsx return문 안에는 for문이 있을 수 없다.

(2) return문 안에서 map

function App{
  //unrelated codes...
  return (
    timedata.map((time, idx)=>
    <TrackedTime title={timedata[i].title} timeframes={Timeframe} current={timedata[i].current} previous={timedata[i].previous>  />
)
  )
}

이렇게 했더니 에러는 따로 없었지만 컴포넌트가 화면에서 보이지 않았다.
(혹시 왜인지 아시는 분 댓글 남겨주시면 감사하겠습니다.)

(3) return문 밖에서 map, 변수로 전달해주기

function App{
  //unrelated codes...
   const timeComponents = timedata.map((time, idx)=>
    <TrackedTime title={time.title} timeframes={Timeframe} current={updatecurrentTime(idx, Timeframe)} previous={updatepreviousTime(idx, Timeframe)}/> 
  );

  return (
    {timeComponents}
  )
}

왜 (2)는 안되고 (3)은 되는지 모르겠다.
이렇게 하면 가독성이 엄청 별로였다.
다른 방법을 찾게 되면 꼭 업데이트하겠다.

  1. json 파일 참조하기
    daily, monthly, weekly 에 따라서
    TrackedTime 컴포넌트 안에 들어가는 텍스트가
    변화하도록 만들어 주어야 했다.

json 파일은 아래와 같았다.

{
    "title": "Work",
    "timeframes": {
      "daily": {
        "current": 5,
        "previous": 7
      },
      "weekly": {
        "current": 32,
        "previous": 36
      },
      "monthly": {
        "current": 103,
        "previous": 128
      }
    }
  },
  {
    "title": "Play",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 2
      },
      "weekly": {
        "current": 10,
        "previous": 8
      },
      "monthly": {
        "current": 23,
        "previous": 29
      }
    }
  },
  //이하 생략

그래서 for문을 돌면서 object.timeframes.[daily/weekly/monthly].[current/previous]를
상황에 맞게 바꾸어 주어야만 했다.

우선, profile 영역에서 Timeframe를 state로 선언하고 클릭에 따라 바뀔 수 있게 해 주었다.

function App(){
  let [Timeframe, setTimeframe] = useState("day"); //기본값을 day로 주었다.
  return (
        <div className="time">
          <button className="daily" onClick={()=>setTimeframe("day")}>Daily</button>
          <button className="weekly" onClick={()=>setTimeframe("week")}>Weekly</button>
          <button className="monthly" onClick={()=>setTimeframe("month")} >Monthly</button>
        </div>    
  )
}

그 다음으로, profile 영역에서 변한 Timeframe를 TrackedTime 컴포넌트의 props로 주었다.

  const timeComponents = timedata.map((time, idx)=>
    <TrackedTime title={time.title} timeframes={Timeframe} current={} previous={}/> 
  )

그리고 이 Timeframe에 맞게 current와 previous를 업데이트해주는 함수를 만들었다.

  function updatecurrentTime(idx, Timeframe){
    if(Timeframe==="day") return timedata[idx].timeframes.daily.current;
    else if(Timeframe==="week") return timedata[idx].timeframes.weekly.current;
    else if(Timeframe==="month") return timedata[idx].timeframes.monthly.current;
  }

  function updatepreviousTime(idx, Timeframe){
    if(Timeframe==="day") return timedata[idx].timeframes.daily.previous;
    else if(Timeframe==="week") return timedata[idx].timeframes.weekly.previous;
    else if(Timeframe==="month") return timedata[idx].timeframes.monthly.previous;
  }

마지막으로 TrackedTime props로 함수를 호출해 주었다.

  const timeComponents = timedata.map((time, idx)=>
      <TrackedTime title={time.title} timeframes={Timeframe} current={updatecurrentTime(idx, Timeframe)} previous={updatepreviousTime(idx, Timeframe)}/>
  )

jsx 전체 코드는 아래와 같다.

function App() {

  let [Timeframe, setTimeframe] = useState("day");

  function updatecurrentTime(idx, Timeframe){
    if(Timeframe==="day") return timedata[idx].timeframes.daily.current;
    else if(Timeframe==="week") return timedata[idx].timeframes.weekly.current;
    else if(Timeframe==="month") return timedata[idx].timeframes.monthly.current;
  }

  function updatepreviousTime(idx, Timeframe){
    if(Timeframe==="day") return timedata[idx].timeframes.daily.previous;
    else if(Timeframe==="week") return timedata[idx].timeframes.weekly.previous;
    else if(Timeframe==="month") return timedata[idx].timeframes.monthly.previous;
  }

  const timeComponents = timedata.map((time, idx)=>
    <TrackedTime title={time.title} timeframes={Timeframe} current={updatecurrentTime(idx, Timeframe)} previous={updatepreviousTime(idx, Timeframe)}/> 
  );

  return (
    <>
    <div className="wrapper">
      <div className="profile">
        <div className="user">
          <div className="pic"></div>
          <div className="repfor">Report for</div>
          <div className="name">Jeremy Robson</div>
        </div>

        <div className="time">
          <button className="daily" onClick={()=>setTimeframe("day")}>Daily</button>
          <button className="weekly" onClick={()=>setTimeframe("week")}>Weekly</button>
          <button className="monthly" onClick={()=>setTimeframe("month")} >Monthly</button>
        </div>
      </div>
      
      {timeComponents}
      
      

  </div>
  
  <Attribution />
  </>
  );
}



function TrackedTime(props){
  return(
    <div className={"tracktime " + props.title}>
    <div className={"top " + props.title}>
      <div className="title">{props.title}</div>
      <div className="showntime">
        <div className="current">
          {props.current}hrs
        </div>
        <div className="previous">
          Last {props.timeframes} - {props.previous}hrs
        </div>
      </div>
    </div>
  </div>
  )
}

앞으로-배울-것

처음으로 리액트를 활용해서 무에서 유를 창조해 보았다(?)
컴포넌트를 언제 어떻게 만들어야 하며
props와 state가 어떻게 쓰이는지 연습해 볼 수 있었다.
하지만 여전히 코드가 깔끔하지 않은 것 같아 스스로 매우 불만족스럽다...
강의 몇개 더 듣고 와야겠다.

참고-사이트

제작자

기타사항

이런... 공부하면 할수록 할 게 더 많아지는 것 같다.
방학동안에 많이 배워둬야지.

profile
코드를 짭니다...
post-custom-banner

0개의 댓글