728x90
반응형

회사에서 캘린더 안에 원하는 스케쥴을 추가하고 싶은 상황이 생겼다.

 

npm 날짜 관련 모듈이 생각보다 많다. react-day-picker, react-datepicker, react-fullcalendar 등..

날짜 자체만 선택하는 경우에는 쓸 수 있는 모듈은 엄청나게 많지만

 

FullCalendar

내가 원하는 날짜를 선택하고 그 날짜에 스케줄을 추가하는 모듈을 fullcalendar 보다 좋은 모듈을 못 봤다.

 

이미 있는 것을 쓰는것은 참 편하지만 고객이 필요로 하는 정보를 기반으로 커스터마이징을 할 땐 결국 모듈의 힘을 빌리면 한계가 있다. 나중에 복잡해지면 오히려 편하자고 쓴 것 때문에 더 스트레스 받게된다..

그래서 그냥 만들자 해서 진짜 만들게 되었다.

 

먼저 Next 앱을 설치한다.

$ npx create-next-app --typescript calendar

 

캘린더를 만드는데 필요한 모듈을 설치한다.

$ npm i moment --save

 

 

일반적으로 우리가 생각하는 캘린더의 기본은 맨 위에 현재 연도와 월이 표시되어 있고,

이번 달이 아닌 날짜는 회색계열로 표시, 오늘 날짜는 유니크하게 표시하게 되어있다.

 

날짜 한 개마다 원하는 속성을 넣어주어 쉽게 커스터마이징 할 수 있는 캘린더를 만들어보자.

 

 

일단 index.tsx 파일을 깨끗하게 비우고 필요한 상태들을 선언해준다.

index.tsx

import moment from 'moment'
import type { NextPage } from 'next'
import { useEffect, useState } from 'react'
import styles from '../styles/Home.module.css'

const Home: NextPage = () => {

  const [getMoment, setMoment] = useState(moment()); // 오늘

  const today = getMoment; // 오늘

  const todayFirstWeek = today.clone().startOf('month').week(); // 이번달의 첫째 주
  const todayLastWeek = today.clone().endOf('month').week() === 1 ? 53 : today.clone().endOf('month').week(); // 이번달의 마지막 주

  const [dayArray, setDayArray] = useState<any>([]); // 날짜들이 가지는 상태값들 모아둔 배열


  return (
    <div className={styles.container}>
      
    </div>
  )
}

export default Home

 

moment()를 useState에 넣고 today에 할당시켜 오늘 날짜를 가지게 하고

이번달의 첫째 주, 마지막 주의 데이터를 moment를 이용해 가져온다.

 

또한 날짜들의 데이터가 담길 배열을 선언해준다.

 

그 다음 useEffect()를 추가하여 배열 안에 이번 달의 날짜 내용을 담아준다.

useEffect(() => {

    // 고유 인덱스 번호
    let Index = 0;

    // 이번 달 배열에 담기 
    let week = todayFirstWeek;
    let result = []; // 이번 달 배열
    for (week; week <= todayLastWeek; week++) {
      let weekArray: any[] = []; // 주 별로 배열에 담음
      for (var i = 0; i < 7; i++) { // 7번 반복(일주일)
        let days = today.clone().startOf('year').week(week).startOf('week').add(i, 'day'); // 그날의 시간 정보
        if (moment().format('YYYYMMDD') === days.format('YYYYMMDD')) { // 현재날짜일 경우
          weekArray.push({
            Index: i,
            day: days.format('YYYY-MM-DD'),
            work: "",
            tardy: "",
            css: {
              color: "",
              bgColor: "lightpink",
              display: "",
            },
            func: {
              onClick: true,
            }
          });
        }
        else if (days.format('MM') !== today.format('MM')) { // 현재 월이 아닐 경우 (클릭옵션 주지 않기 or dispaly none)
          weekArray.push({
            Index: i,
            day: days.format('YYYY-MM-DD'),
            work: "",
            tardy: "",
            css: {
              color: "",
              bgColor: "white",
              display: "",
            },
            func: {
              onClick: true,
            }
          });
        }
        else {
          weekArray.push({
            Index: i,
            day: days.format('YYYY-MM-DD'),
            work: "",
            tardy: "",
            css: {
              color: "",
              bgColor: "lightgrey",
              display: "",
            },
            func: {
              onClick: true,
            }
          });
        }
        Index++; // monthIndex 값을 1씩 증가
      }
      result.push(weekArray);
    }

    setDayArray(result);
  }, []);

주석에 표기한 바와 같이 현재 날짜와 이번 달 날짜가 아닌 날짜들은 좀 다른 데이터를 넣어주었다.

이 상태로 서버를 실행하고 브라우저 콘솔로 배열을 확인해보자

 

날짜들에 대한 데이터가 잘 담긴 것을 확인할 수 있다. 

사실상 스케줄러를 제외한 캘린더 구현은 이 데이터들을 매핑해주는 것으로 끝이다.

728x90
반응형

+ Recent posts