본문 바로가기
공부낙서장

부트캠프 프론트엔드 및 백엔드 협업 과제 진행 ing (FullCalendar)

by 곰인간 2023. 8. 9.

 

연차 및 당직 관리 웹애플리케이션 메인 페이지이다.

달력은 FullCalendar를 사용했다.

switch 토글은 ant design

{
  "success": "true",
  "response": [
    {
	  "id": 1, // 스케쥴 id
      "userName": "Park",
      "scheduleType": "ANNUAL",
      "startDate": "2023-08-11",
      "endDate": "2023-08-13",
	  "state": "APPROVE"
    },
		{
	  "id": 2,
      "userName": "Jon",
      "scheduleType": "DUTY",
      "startDate": "2023-08-20",
      "endDate": "2023-08-20",
	  "state": "PENDING"
    }
  ]
 "error": null
}

일단 서버에 요청해서 오는 response 스키마

연차/당직 이벤트를 받아서 위에 보이는 달력에 렌더링되게 해야하는데, 

조건은 state가 approve일 것,

state는 현재 pending, approve, reject로 나눠져있음.

연차/당직을 신청하면 승인을 받아야 달력에 렌더링되는 구조

상단에 스위치가 All상태이면 모든 사용자들의 승인된 연차/당직을 달력에서 확인 가능하고,

스위치가 My상태가 되면 나의 일정만 달력에서 확인 가능하다.

그리고 Calendar 컴포넌트 보다 상위 컴포넌트에서 로그인 상태를 확인 할 수 있게 props를 받아오는 상태
(AccessToken의 유무로 확인 중)

  // 데이터로 받아올 events를 상태관리
  const [events, setEvents] = useState([]);

  // 달력의 현재 월 상태관리
  const [month, setMonth] = useState(new Date().getMonth() + 1);
  // switch 체크 상태관리
  const [isAllChecked, setIsAllChecked] = useState(true);

  const [isLoading, setIsLoading] = useState(false);

  // 처음엔 달력의 날짜를 클릭했을 때 데이터를 가져오려고 했었는데,
  // 지금은 달력 Header 부분을 커스텀할 때 사용 중
  const calendarRef = useRef<FullCalendar | null>(null);

events는 달력에 렌더링 될 이벤트 상태관리,

month는 달력의 현재 월 상태관리인데, 년도는 상위 컴포넌트에서 관리 중 이다.

isAllChecked는 switch 토글 상태를 관리한다.

스위치가 true인 상태가 All이다. false면 My

로딩 ui를 구현하기 위해서 isLoading으로 상태관리

calendarRef는 처음엔 달력의 날짜를 클릭하면 데이터를 가져오려고 했는데,

생각해보니깐 딱히 필요가 없을거 같아서 냅뒀는데,

현재는 FullCalendar header부분 커스터마이징 하는데 사용 되고 있다.

useEffect(() => {
    const schedule = async () => {
      // getAccessTokenFromCookie를 이용해서 쿠키에 저장된 accessToken을 가져옴
      const accessToken = getAccessTokenFromCookie();
      // 엑세스 토큰이 없으면 서버에 요청하지 않음
      if (!accessToken) {
        return;
      }

      setIsLoading(true);

      const listResponse = await scheduleList(year);
      const infoResponse = await getMyAccount();

      // 실제 응답 데이터 추출
      const listResponseData = listResponse.data.response;
      const infoResponseData = infoResponse.data.response;

      // response data를 가져오는데 그 내부에 있는 response라는 배열 데이터를 각각의 요소를
      // 아래의 형태의 객체로 변환해서 events 변수에 저장, setEvents에 전달
      const events = listResponseData
        .filter(
          (item: ScheduleItem) =>
            (isAllChecked && item.state === 'APPROVE') ||
            (item.userName === infoResponseData.userName &&
              item.state === 'APPROVE'),
        )
        .map((item: ScheduleItem) => {
          return {
            title: item.userName,
            start: item.startDate,
            end: item.endDate,
            color: DUTY_ANNUAL[item.scheduleType].color,
          };
        });
      setEvents(events);
      setIsLoading(false);
    };
    schedule();
  }, [isSignedin, year, month, isAllChecked]);

useEffect를 사용해서 로그인 상태가 변할 때나, 년, 월 변경 될 때, 스위치의 상태가 변경될 때를 리렌더링 시키고 있다.

일단 엑세스 토큰이 없으면 서버에 요청되어 봤자 인증된 사용자가 아니기 때문에 필요없는 요청이 들어간다고 판단,

if조건문을 이용해서 accessToken이 없으면 바로 종료하게 하였다.

accessToken이 발급된 상태이면, 

setIsLoading을 통해 로딩 상태가 되고,

scheduleList 함수가 실행되어, 해당년도의 일정을 가져오고,

getMyAccount를 통해서 사용자의 정보를 가져온다.

그리고 각각의 response에서 필요한 데이터를 가져와서 filter와 map을 통해서 원하는 형태로 events 변수에 생성한다.

(filter를 사용해서 스위치가 true이고, scheduleList의 state가 APPROVE일 때 통과 하거나,
// 이 부분이 스위치가 true, All 상태일 때, 모든 사용자의 일정이 달력에 렌더링되게 하는 부분

scheduleList의 userName이 getMyAccount의 userName과 동일하고, scheduleList의 state가 APPROVE일 때 통과
// 이 부분이 스위치가 false, My 상태일 때, 나의 일정을 달력에 렌더링되게 하는 부분)

그리고 setEvents를 사용해서 events의 배열에 업데이트한다.

마지막으로 setIsLoading이 false상태가 되면서 로딩 상태를 비활성화한다.

댓글