주간달력 및 월간달력 구현
ㆍProject Diary/Next.js + Prisma + MariaDB (KiloFlow)
1. 주간달력과 월간달력 구현을 위한 라이브러리 설정
Kiloflow 프로젝트에서 주간달력과 월간달력을 구현하기 위해 react-calendar와 dayjs 라이브러리를 사용합니다.
npm install react-calendar dayjs
2. 달력 컴포넌트 설정 및 기본 렌더링
2-1 상태값 정의 및 초기 설정
// 상태값 정의
const [currentTab, setCurrentTab] = useState<Tab>('week'); // 현재 활성화된 탭(주간 또는 월간)을 나타내는 상태값
const [selectedDate, setSelectedDate] = useState(dayjs().toDate()); // 현재 선택된 날짜를 저장하는 상태값
// 탭 변경 핸들러
const handleTabChange = (tab: Tab) => {
setCurrentTab(tab); // 탭 변경
setSelectedDate(dayjs().toDate()); // 선택된 날짜를 현재 날짜로 초기화
};
2-2 날짜 선택 핸들러
// 날짜 변경 핸들러
const handleDateChange = (value: Date) => {
setSelectedDate(dayjs(value).toDate()); // 선택된 날짜를 상태값으로 설정
};
날짜를 선택할 때 호출되는 함수입니다.
3. 달력 타일 클래스 설정
3-1 타일 클래서 설정
// 타일 클래스 설정
const tileClassName = ({ date }: { date: Date }) => {
if (currentTab === 'week') {
const startOfWeek = dayjs(selectedDate).startOf('week').toDate(); // 현재 주의 시작 날짜
const endOfWeek = dayjs(selectedDate).endOf('week').toDate(); // 현재 주의 끝 날짜
if (date < startOfWeek || date > endOfWeek) {
return 'react-calendar__tile--hidden'; // 현재 주에 해당하지 않는 날짜 숨김
}
}
return null;
};
주간 탭일 경우, 현재 주에 해당하지 않는 날짜를 숨기는 클래스를 반환합니다.
- startOfWeek, endOfWeek의 기준이 일요일 부터 시작이기 때문에 달력의 한주가 일요일 부터 시작하도록 설정해야 합니다
3-2 주간탭일경우 StyledCalendar 스타일링
const StyledCalendar = styled(Calendar)`
width: 100%;
background-color: inherit;
border: none;
border-bottom: 1px solid #ccc;
.react-calendar__navigation {
display: none; // 네비게이션 숨김
}
.react-calendar__tile--hidden {
display: none !important; // 현재 주에 해당하지 않는 날짜 숨김
}
abbr {
text-decoration: none; // 밑줄 제거
}
`;
- .react-calendar__tile--hidden : 주간 탭에서 현재 주에 해당하지 않는 날짜를 숨깁니다.
4. 이전 및 다음 버튼 핸들러
4-1 이전 버튼 핸들러
// 이전 버튼 핸들러
const handlePrev = () => {
const newDate =
currentTab === 'week'
? dayjs(selectedDate).subtract(1, 'week').toDate() // 이전 주로 이동
: dayjs(selectedDate).subtract(1, 'month').toDate(); // 이전 달로 이동
setSelectedDate(newDate); // 선택된 날짜 업데이트
};
이전 주 또는 이전 달로 이동하는 함수입니다.
4-2 다음 버튼 핸들러
// 다음 버튼 핸들러
const handleNext = () => {
const newDate =
currentTab === 'week'
? dayjs(selectedDate).add(1, 'week').toDate() // 다음 주로 이동
: dayjs(selectedDate).add(1, 'month').toDate(); // 다음 달로 이동
setSelectedDate(newDate); // 선택된 날짜 업데이트
};
다음 주 또는 다음 달로 이동하는 함수입니다.
5. 주간 및 월간 달력 렌더링
return (
<HomeBlock>
<CalendarTab
currentTab={currentTab}
setCurrentTab={handleTabChange}
selectedDate={selectedDate}
handlePrev={handlePrev}
handleNext={handleNext}
/>
{currentTab === 'month' && (
<StyledCalendar
key={selectedDate.toString()}
onChange={(value) => handleDateChange(value as Date)}
value={selectedDate}
view='month'
tileClassName={tileClassName}
formatMonthYear={(locale, date) => `${dayjs(date).year()}년 ${dayjs(date).month() + 1}월`}
formatDay={(locale, date) => dayjs(date).date().toString()}
locale='en-US'
/>
)}
{currentTab === 'week' && (
<StyledCalendar
key={selectedDate.toString()}
onChange={(value) => handleDateChange(value as Date)}
value={selectedDate}
view='month'
tileClassName={tileClassName}
formatMonthYear={(locale, date) => `${dayjs(date).year()}년 ${dayjs(date).month() + 1}월`}
formatDay={(locale, date) => dayjs(date).date().toString()}
locale='en-US'
/>
)}
</HomeBlock>
);
- StyledCalendar : react-calendar 컴포넌트를 스타일링
- locale='en-US' : 한 주가 일요일부터 시작하도록 설정합니다.