본문 바로가기

JS/React Project

📆 위클리 플래너 - 홈화면

1. 날짜 세팅하기 : 오늘 날짜를 기준으로 해당 주의 월요일 ~ 일요일

(참고: https://askjavascript.com/how-to-get-first-and-last-day-of-the-current-week-in-javascript/)

// 오늘 날짜 
const currentDate = new Date(); 

// 오늘 요일 일 0 ~ 토 6
const currentDay = currentDate.getDay() 

// 월요일 구하기 (오늘 날짜 - 오늘 요일 + 1)
const monday = new Date(currentDate);  
monday.setDate(currentDate.getDate() - currentDay + 1);

// 일요일 구하기 (오늘 날짜 - 오늘 요일 + 7)
const sunday = new Date(currentDate);
sunday.setDate(currentDate.getDate() - currentDay + 7)

// 참고에 있는 링크는 일요일을 한 주의 시작으로 보기 때문에 거기서 +1씩 해서
// 월요일을 한 주의 시작으로 세팅하였다.

 

 

화살표 버튼을 누르면 주 단위로 앞 뒤로 이동 

const handleWeek = (direction) => { 
    // direction -1 왼쪽 / 1 오른쪽 
    if(direction === -1) {
        // 한 주 감소 
        setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() - 7))
    } else { 
        // 한 주 증가 
        setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() + 7))
    }
}

 

 

2. 날짜별 데이터 가져오기 

월요일 ms ~ 일요일 ms 사이에 writtenDate 값 필터링  

// 선택된 주의 paln
const mondayMs = monday.getTime();
const sundayMs = sunday.getTime();

const thisWeekPlan = filteredWeekPlan.filter(
  (it) => mondayMs <= it.writtenDate && it.writtenDate <= sundayMs
);
const thisWeekDailyPlan = filteredDayPlan.filter(
  (it) => mondayMs <= it.writtenDate && it.writtenDate <= sundayMs
);

 

3. 해당 주의 week plan 세팅 

redux store subject안에 subject별 색상이 정해져 있기 때문에 중간에 subColor를 지정하는 함수를 추가하였다. 

<div className="home_week_area">
        <div>This week's plan</div>

        <div className="week_goals">
          {thisWeekPlan.map((it) =>
            it.goal.map((goal) => {
              // subject 정보에서 이름이 일치하는 정보를 찾아 색상 지정
              let subColor = "";

              filteredSubject.map((sub) => {
                if (sub.subject === goal.weekGoalSubject) {
                  subColor = sub.color;
                }
              });

              return (
                <span className="goal_item" key={goal.weekGoalId}>
                  <span>
                    {goal.weekGoalComplete ? (
                      <FontAwesomeIcon icon={faSquareCheck} />
                    ) : (
                      <FontAwesomeIcon icon={faSquare} />
                    )}
                  </span>
                  <span
                    className="subject"
                    style={{ backgroundColor: `${subColor}` }}
                  >
                    {goal.weekGoalSubject}
                  </span>
                  <span>{goal.weekGoalContent}</span>
                </span>
              );
            })
          )}
        </div>
      </div>

 

 

4. 해당 주의 daily plan 

처음에는 위와 같이 dayPlan 배열을 map으로 돌려서 7개의 item(日칸 하나하나)를 만들려고 하였는데,

생각해보니 저렇게 하면 만약, 데이터가 하루 없다면(ex: 화요일 데이터 없음) 6개의 칸만 만들어지게 되기 때문에 위와 같이는 하면 안되는 것이였다. 

* 잘못한 처음 코드

더보기
 {filteredDayPlan.map((it) => (
          <div className="home_daily_item">
            <div>
              <span>
                {/* 날짜 */}
                {`${new Date(it.writtenDate).getMonth() + 1}/${new Date(
                  it.writtenDate
                ).getDate()}`}
              </span>
              <span>
                {/* 요일 */}
                {(() => {
                  let day = "";
                  switch (new Date(it.writtenDate).getDay()) {
                    case 0:
                      day = "SUN";
                      break;
                    case 1:
                      day = "MON";
                      break;
                    case 2:
                      day = "TUE";
                      break;
                    case 3:
                      day = "WED";
                      break;
                    case 4:
                      day = "THU";
                      break;
                    case 5:
                      day = "FRI";
                      break;
                    case 6:
                      day = "SAT";
                      break;
                  }
                  return day;
                })()}
              </span>
            </div>

            <div>
              {it.goal.map((goal) => {
                // subject 정보에서 이름이 일치하는 정보를 찾아 색상 지정
                let subColor = "";

                filteredSubject.map((sub) => {
                  if (sub.subject === goal.dailyGoalSubject) {
                    subColor = sub.color;
                  }
                });

                return (
                  <span className="goal_item">
                    <span>
                        {goal.dailyGoalComplete ? (
                         <FontAwesomeIcon icon={faSquareCheck} />
                        ) : (
                         <FontAwesomeIcon icon={faSquare} />
                        )}
                    </span>
                    <span
                      className="subject"
                      style={{ backgroundColor: `${subColor}` }}
                    >
                      {goal.dailyGoalSubject}
                    </span>
                    <span>{goal.dailyGoalContent}</span>
                  </span>
                );
              })}
            </div>
          </div>
        ))}

그렇다면, 7개의 칸과 각각의 칸의 mon~sun은 원래 고정된 상태로 그 안에 날짜랑 계획 데이터만 집어 넣어야 하는 것이다. 

 

// 먼저 반복할 칸의 배열을 만들어 준다.
const sevenDays = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];
 
return 
<div className="home_daily_area">
    {sevenDays.map((days, index) => (
      <div className="home_daily_item">
        <div>
          <span>
          // 날짜 지정할 때 사용한 monday 정보를 복사하여 각각 칸에 날짜를 monday + 0 ~ 6일 더해주었다.
            {(() => {
              const thisMonday = new Date(monday);
              let date = thisMonday.setDate(monday.getDate() + index);
              return `${new Date(date).getMonth() + 1}/${new Date(
                date
              ).getDate()}`;
            })()}
          </span>
          <span>{days}</span>
        </div>

        <div>
        // 위와 같이 7개의 날짜 정보를 불러와 각각 컴포넌트를 생성하고 
        // 해당 날짜(date), 필터링된 데이터(item), 필터링된 주제(sub)를 전달한다.
        {(() => {
              const thisMonday = new Date(monday);
              let date = thisMonday.setDate(monday.getDate() + index);
              return <GoalItem date={date} item={thisWeekDailyPlan} sub={filteredSubject}/>
            })()}
        </div>
      </div>
    ))}
  </div>
  
  
  // GoalItem 
const GoalItem = ({date, item, sub}) => { 
return (
    <div>
        {item.map((it) =>
            it.goal.map((goal) => {
            // 날짜가 일치하지 확인 
            if (date === new Date(it.writtenDate).setHours(0, 0, 0, 0)) {
            
                // 주제 색상 지정
                let subColor = 'red';
                sub.map((sub) => {
                    if (sub.subject === goal.dailyGoalSubject) {
                    subColor = sub.color;
                    }
                });

                return (
                    <span className={`goal_item ${date}`} key={it.id}>
                        <span>
                        {goal.dailyGoalComplete ? (
                            <FontAwesomeIcon icon={faSquareCheck} />
                        ) : (
                            <FontAwesomeIcon icon={faSquare} />
                        )}
                        </span>

                        <span className="subject" style={{ backgroundColor: `${subColor}` }}>
                        {goal.dailyGoalSubject}
                        </span>
                        <span>{goal.dailyGoalContent}</span>
                    </span>
                    );
                } else {
                    return null;
                }
            })
        )}
    </div>
  );
}

이렇게 한다면 해당 날짜에 해당하는 데이터를 각각의 칸에 집어넣을 수 있게 된다.