이전글에서 달력을 만들기 앞서 재사용이 가능한 테이블을 만들었다.
그래서 이제 테이블에 값을 넣기위해 배열만 생성하면 된다.
그러기 위해서 Date 객체를 사용 할 것이다.
달력을 만들기 위해 필요한건 별거 없다.
월의 시작 요일, 월의 마지막 날짜 이 두개만 있으면 모든 날짜를 게산할 수 있다.
이 둘을 계산하는 방법은 여러개가 있는데 간단하게 Date를 사용하는 방법을 쓸것이다.
const getMonthInfo = (year: number, month: number) => {
// 월의 시작 요일 ( 0 ~ 6, 일요일 = 0)
const startDay = new Date(year, month - 1, 1).getDay();
// 월의 마지막 날짜
const endDate = new Date(year, month, 0).getDate();
}
아 하나 빼먹은게 있는데 달이 바뀔 때 항상 4주인게 아니라 4주일때도 5주일때도 6주일때도 있다.
그래서 해당 달의 주가 몇주인지도 계산해야하는데
ceil((시작요일 + 마지막날짜) / 7)을 해주면 구할 수 있다.
앞서만든 Table
컴포넌트에 넣기위해선 2차원 배열로 넣어줘야한다.
그래서 calendarGenerator
를 이제 바꿔보겠다.
const calendarGenerator = (year: number, month: number) => {
const { endDate, startDay } = getMonthInfo(year, month);
const weekNumber = Math.ceil((startDay + endDate) / 7);
const calendar: number[][] = [];
let nowDate = 0;
let nowDay = 0;
for (let i = 0; i < weekNumber; i++) {
const nowWeek = [];
for (let j = 0; j < 7; j++) {
if (startDay <= nowDay && nowDate < endDate) {
nowDate++;
nowWeek.push(nowDate);
} else {
nowWeek.push(0);
}
nowDay++;
}
calendar.push(nowWeek);
}
return calendar;
};
위의 코드를 보면 calendar
에 달력의 정보를 담아준다.
그리고 2중for문으로 넣어주는데 방법은 이렇다.
calendar
에 한주에 해당하는 배열을 넣는다.이제 모든 준비는 끝났다. 데이터를 만들어 달력을 그려주기만 하면 된다.
Table
에 넣어줄 rows, titles를 아래처럼 만들어준다.
const titles = ['일', '월', '화', '수', '목', '금', '토'];
const rows = () => {
const datas = calendarGenerator(2022, 8);
const components: TTableData[] = [];
// 주 반복
datas.forEach((week, idx) => {
const weeks: TTableColumns[] = [];
// 일 반복
week.forEach((date, idx) => {
weeks.push({
// 빈칸일때는 key가 중복되므로 idx를 넣어줌
key: date ? date : idx,
// 빈칸일때는 아무것도 안나오고 값이 있다면 날짜를 넣어줌
render: date ? <span>{date}</span> : <span />,
});
});
// 해당 주의 컴포넌트들
const weekData: TTableData = {
id: `w_${8}${idx}`,
columns: weeks,
};
components.push(weekData);
});
return components;
};
그리고 Table
에 이 값을 넣어준다.
<Table
headers={titles}
rows={rows()}
/>
그러면 아래처럼 달력이 생성된다!!