3일동안 열심히 구현한 달력 ...
자세한 과정은 나중에 언젠가 쓸 예정.....
일단 코드만 냅다 투척.....! 하 하 !
import moment from "moment";
import Link from "next/link";
import React, { useState } from "react";
interface DateData {
full: string;
date: string;
}
export default function Calendar() {
const [selected, setSelected] = useState(moment());
function moveNextMonth() {
setSelected(selected.clone().add(1, "month"));
}
function movePrevMonth() {
setSelected(selected.clone().subtract(1, "month"));
}
return (
<div className="container">
<div className="header">
<button onClick={movePrevMonth}>이전달</button>
<span>{selected.format("MM월")}</span>
<button onClick={moveNextMonth}>다음달</button>
<MonthCalendar selected={selected} />
</div>
</div>
);
}
export const MonthCalendar = ({ selected }: { selected: moment.Moment }) => {
let date = selected.clone().startOf("month");
let dates: DateData[] = [];
// 1일 이전의 날짜들 처리
for (let i = date.day(); i > 0; i--) {
dates.unshift({ full: `${i}`, date: `none` });
}
// 날짜 데이터 넣기
for (; date < selected.clone().endOf("month"); date.add(1, "day")) {
const data: DateData = {
full: date.format("YYYY-MM-DD"), // href 쿼리에 전달할 연도-월-날짜
date: date.format("DD"), // 화면에 표시되는 날짜
};
dates = dates.concat(data);
}
// [주][날짜] 형태의 이중배열로 저장
let calendar: DateData[][] = Array.from(Array(6), () => new Array(7));
dates.forEach((date, index) => {
calendar[Math.floor(index / 7)][index % 7] = date;
});
return (
<div>
<table border={1}>
<thead>
<tr>
<th>Sun</th>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thu</th>
<th>Fri</th>
<th>Sat</th>
</tr>
</thead>
<tbody>
{calendar.map((week, index) => (
<tr key={index}>
{week.map((day) => (
<td key={day.full}>
{day.date !== "none" ? (
<Link href={`/main?date=${day.full}`}>
<span>{day.date}</span>
</Link>
) : (
<></>
)}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
};
참고1 : 본 달력을 구현하기 위해 moment 를 설치하였습니다.
참고2 : 본 달력을 사용하는 프로젝트는 리액트 기반 NextJS와 타입스크립트를 사용하고있습니다.
...만 달력 자체의 기능은 위 코드만을 살짝 변형하여 바닐라 자바스크립트만을 이용해도 구현 가능합니다 !
구현 과정 소중하게 담아놓은 풀리퀘와 커밋내역
https://github.com/seondal/Sobok-WebApp/pull/1
- refact : react-moment 설치 및 적용
- feat : 달력 날짜 누르면 해당 날짜에 해당하는 페이지로 이동
- fix : key props
- feat :
<table />
- feat : 달력에서 1일 이전의 날짜들은 none 처리
- feat : 날짜 데이터 calendar 이중배열에 저장
- feat : 달력 표현 !!!!!
- edit : 가독성 좋게 코드 위치 변경
- fix :
<table>
구조 정확하게 알고 쓰자
- Warning: validateDOMNesting(...):<th>
cannot appear as a child of<table>
- fix : map 에서 key prop 전달
- Warning: Each child in a list should have a unique "key" prop