오픈소스로 나와있는 calendar api 들이 많지만,

필자의 경우 커스텀할 일이 많아 직접 캘린더를 구현해볼 것이다.

1.전제조건

1) 종료일자기준 30일전부터 캘린더에 전부 표현할 것 , 1개의 캘린더에 모든 날짜가 들어간다.

2) 설명을 위한 글이므로 소스코드를 여러페이지에 분리하지 않고 한 페이지에 구현

3) state, dispatch 등 calendar 설명에 불 필요한 부분은 과감히 생략

4) 꼭 필요한 부분은 소스코드에 명시할 것이며 css 관련해서는 자세하게 작성하지 않는다.

5) 순수하게 캘린더에 필요한 부분만 작성할 것이며 상황에 따른 커스텀은 따로 하길 바란다.

6) 설명을 위해 일부 주석이 들어갈 수 있다.

2. 소스코드(JS)

 

import React, {useState } from 'react';
import moment from 'moment'; 
    const [dayArray, setDayArray] = useState<any>({ array: [] }); // 실제 캘린더 데이터

    const dayInit: any = {
        monthIndex: 0,
        weekIndex: 0,
        weekData: "",
        day: "--",
        status: {
            영업구분 : { check : true, 근로자수 : 0} ,
        },
        func: {
            onClick: false,
        }
    }
    var calcEndDate = moment(data.basicInfoState.customer_calc_basic_date);
    var calcStartDate = moment(data.basicInfoState.customer_calc_basic_date).subtract(30,'d');
    var tempCalcStartDate =  moment(data.basicInfoState.customer_calc_basic_date).subtract(30,'d');

  const dayArrayInit = () => { // 캘린더 작성 버튼 클릭 이후
       
        let monthIndex = 0; // 일자별 구분
        let totalResult: any[] = []; // 전체 배열
        let calc_day : any = calcStartDate; // 시작일자 기준값
        if(calc_day.day() === 0){  // 종료일자 기준 30일 전이 일요일이면 아무행위를 하지않음
          
        }else { // 종료일자 기준 30일 전이 일요일이 아닐 경우 해당 날짜만큼 차감하여 일요일로 만든다.
            calc_day.subtract(calc_day.day(),'days');
          }

            for(let j= calc_day.week(); j <= calcEndDate.week(); j++){ // 첫주차~마지막주차까지 반복
                let weekArray : any[] = []; // 일주일 단위 데이터
                for(let z = 0; z < 7; z++){ // 주차별 일요일~토요일까지 반복한다.

                    var dayData: any = {
                        monthIndex: 0,
                        weekIndex: 0,
                        weekData: "",
                        day: "--",
                        status: {
                            영업구분 : {check : true, 근로자수 : 0},
                        },
                        func: { onClick:  true }
                    }
                    let  dayType : any = moment(calc_day.format('YYYY-MM-DD').day()); // 무슨 요일인지 선언함
              
                   
                    if(calc_day.isAfter(calcEndDate) === false && calc_day.isAfter(tempCalcStartDate) === true){
                      
                     // 시작일자부터 종료일자에 속하면, 정확한 데이터를 넣음
                   
                    weekArray.push({
                        ...dayData,
                        monthIndex: monthIndex,
                        weekIndex: z,
                        weekData: moment(calc_day.format('YYYY-MM-DD').day()),
                        day: calc_day.format('YYYY-MM-DD');
                        func: { onClick:  true }
                    });

                    }else{

                     // 날짜 범위밖에서는 날짜를 입력하지 않고, 클릭할 수 있는 기능을 없앰
                        weekArray.push({
                            ...dayInit,
                            monthIndex: 0,
                            weekIndex: z,
                            weekData: moment(calc_day.format('YYYY-MM-DD')).day(),
                        }) ;

                    }
                    calc_day.add(1,'days'); // 데이터를 넣었으니 기준일자를 하루씩 증가시킨다.
                    monthIndex++; // monthIndex 값을 1씩 증가
                }
               
                var jsonData = {
                    'weekData' : weekArray,
                };
                totalResult.push(jsonData); // 실제 데이터를 넣는다.
        }
        data.setDayArray({ array: totalResult }); // 실제 캘린더 데이터 배열
  }

이것으로 1차적으로 캘린더를 생성하는 작업은 끝났다.

이제 이 배열을 가공하여 HTML, CSS 작업을 하면 되겠다.

** 원래 시작일자와 종료일자를 나눠, 월 단위로 캘린더를 그려지는 것을

설명하려 했는 데, 소스코드가 너무 복잡하여 이해시킬 자신이 없어

최대한 간단하게 캘린더를 구현했던 버전으로 작성한다.

월별로 캘린더를 나누고 싶은 분은 현재 소스에서 커스텀을 일부 진행하길 바란다.

위 캘린더는 moment.js를 다수 활용했으니, 메서드에 대해서 모르시는 분은 아래 글들을 참고하자.

 

2025.02.10 - [JS] - JS 날짜 라이브러리중 Moment.js에 대해 알아보자

 

+ Recent posts