반응형
리액트 캘린더 라이브러리 설치 후 커스텀 할려고 했으나 실패 ( 이유 : 타입스크립트 형식 파일, css 재정의 )
라이브러리 설치하면 node-modules에 설치되고
커스텀할려면 react-calendar 밑에 dist에 css 파일을 오버라이딩(재정의) 해야 된다.
css 재정의는
같은 이름의 css파일을 내 src 아래 생성 후
같은 클래스명에 대해 css를 적어준다
=> 이 방법으로는 내가 만들려는 캘린더와 똑같이 만들기 힘들었고 다른 방법을 찾음
---------------------------------------------------------------------------------------------------------------------
새로운 방법
달력의 기본적인 틀은 내가 만들고 날짜값만 라이브러리로 설치해서 받아온다
npm install date-fns // 날짜 라이브러리 설치
import React, { useState } from 'react';
import { format, addMonths, subMonths, startOfMonth, endOfMonth, startOfWeek, addDays, getDay, getWeek, isSameMonth } from 'date-fns';
import '../components/Calendar.css';
import ExpiringProducts from './ExpiringProducts';
const Calendar = ({ onDateSelect }) => {
const [currentDate, setCurrentDate] = useState(new Date()); // 현재 날짜를 저장하는 상태
const [selectedDate, setSelectedDate] = useState(null); // 선택된 날짜를 저장하는 상태
// 한국어로 된 월 이름을 반환하는 함수
const getKoreanMonth = (date) => {
const months = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'];
return months[date.getMonth()];
};
// 해당 월의 날짜들을 반환하는 함수
const getDaysInMonth = (date) => {
const start = startOfWeek(startOfMonth(date), { weekStartsOn: 1 });
let days = [];
for (let i = 0; i < 35; i++) { // 5주(7일*5=35일)를 표현하기 위해 35일을 계산
days.push(addDays(start, i));
}
return days;
};
// 특정 날짜가 공휴일인지 확인하는 함수
const isHoliday = (date) => {
const dayOfWeek = getDay(date); // 요일을 가져옴 (0: 일요일, 1: 월요일, ...)
const weekOfMonth = getWeek(date) - getWeek(startOfMonth(date)); // 해당 월의 몇 번째 주인지 계산
return dayOfWeek === 0 && (weekOfMonth === 2 || weekOfMonth === 4); // 둘째 주, 넷째 주 일요일을 공휴일로 간주
};
const days = getDaysInMonth(currentDate); // 현재 월의 날짜들 가져오기
// 이전 달로 이동하는 함수
const onPrevMonth = () => setCurrentDate(subMonths(currentDate, 1));
// 다음 달로 이동하는 함수
const onNextMonth = () => setCurrentDate(addMonths(currentDate, 1));
// 날짜를 클릭했을 때 실행되는 함수
const handleDateClick = (date) => {
setSelectedDate(date); // 선택된 날짜 상태 업데이트
onDateSelect(date); // 부모 컴포넌트로 선택된 날짜 전달
};
return (
<div className="calendar">
<div className="calendar-header">
<button onClick={onPrevMonth} className='cal_btnP'><</button> {/* 이전 달 버튼 */}
<h2>{getKoreanMonth(currentDate)} {format(currentDate, 'yyyy')}</h2> {/* 현재 월과 연도 표시 */}
<button onClick={onNextMonth} className='cal_btnN'>></button> {/* 다음 달 버튼 */}
</div>
<div className="calendar-body">
<div className="calendar-week-days">
{['월', '화', '수', '목', '금', '토', '일'].map(day => (
<div key={day} className="week-day">{day}</div> // 요일 표시
))}
</div>
<div className="calendar-days">
{days.map(day => (
<div
key={day.toString()}
className={`calendar-day
${!isSameMonth(day, currentDate) ? 'other-month' : ''} // 다른 달의 날짜 표시
${isHoliday(day) ? 'holiday' : ''} // 공휴일 표시
${selectedDate && day.toDateString() === selectedDate.toDateString() ? 'selected' : ''}` // 선택된 날짜 표시
}
onClick={() => handleDateClick(day)}
>
{format(day, 'd')} // 날짜 숫자 표시
</div>
))}
</div>
</div>
</div>
);
};
export default Calendar;
.calendar {
font-family: 'Noto Sans KR', Arial, sans-serif;
width: 400px;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
}
.calendar-header {
background-color: #f0f0f0;
padding: 10px;
display: flex;
justify-content: center;
align-items: center;
background-color: #aada2a;
}
.calendar-header button {
background: none;
border: none;
font-size: 18px;
cursor: pointer;
}
.cal_btnP {
margin-right: 10px;
}
.cal_btnN {
margin-left: 10px;
}
.calendar-header h2 {
margin: 0;
font-size: 18px;
}
.calendar-body {
padding: 10px;
}
.calendar-week-days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
margin-bottom: 10px;
}
.week-day {
text-align: center;
font-weight: bold;
color: #777;
}
.calendar-days {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: repeat(5, 1fr);
gap: 5px;
height: 200px; /* 달력 높이 고정 */
}
.calendar-day {
text-align: center;
padding: 5px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.calendar-day:hover {
background-color: #f0f0f0;
}
.calendar-day.other-month {
color: #ccc;
}
.calendar-week-days div:nth-child(7),
.calendar-days div:nth-child(7n) {
color: #ff5555;
}
.calendar-day.holiday {
color: #ff0000;
font-weight: bold;
background-color: #ffeeee;
}
.calendar-day.selected {
background-color: #aada2a;
color: white;
}
.expiring-products {
margin-top: 20px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #f9f9f9;
}
.expiring-products h3 {
margin-top: 0;
color: #333;
}
.expiring-products ul {
list-style-type: none;
padding: 0;
}
.expiring-products li {
margin-bottom: 10px;
padding: 5px;
background-color: #fff;
border: 1px solid #eee;
border-radius: 4px;
}
728x90
반응형
'Final Project 신세계아이앤씨' 카테고리의 다른 글
결제하기 ( 토스페이먼츠 ) (0) | 2024.08.07 |
---|---|
홈페이지 들어가면 달력에 오늘 날짜 보이게하기 (0) | 2024.07.31 |
달력 일자 선택시 7일이내의 유통기한 임박상품 불러오기 ( 리액트, 스프링부트 ) (0) | 2024.07.30 |
재고관리 페이지 ( 리액트, 스프링부트 ) (0) | 2024.07.24 |
Final 기획 (1) | 2024.07.20 |