728x90
react-datePicker 라이브러리를 사용하는 자세한 설명은 위 게시물(v1)을 참고하는 게 더 많은 도움이 될 것이라고 생각한다. v2에서는 v1 코드를 기본으로 사용하면서 조금씩 변형 시키는 과정과 추후 내 업무를 인수인계 해드려야 할 경우를 대비한 안내문이라고 볼 수 있다.
Calendar.js 사용 설명서
- Calendar.js는 react-datepicker 라이브러리를 사용하여 구현 하였습니다.
- Calendar.js는 /elements/library/Calendar.js에 있습니다.
- Calendar.js 컴포넌트 호출 시 필수로 추가 해줘야 하는 항목은 아래와 같습니다.
-
(부모 컴포넌트 - Calendar.js 컴포넌트를 호출 하고자 하는 컴포넌트)
- - useState : startDate(기본값 : new Date()), endDate(기본값 : null), info(객체 형태 + startDate: “”, endDate: “”)
- - nextDay() : 다음 날 구하는 함수
- - useEffect 2개 : 시작일 바뀔 때마다 실행되는 함수, 종료일 바뀔 때마다 실행되는 함수
- - CalendarPop : Calendar.js 컴포넌트
(자식 컴포넌트 - Calendar.js)
- - 기본 형식과 다르다면 type으로 나눠서 기본 코드 커스텀 하면 됩니다.
결과
Test.js (부모 컴포넌트 - Calendar.js 컴포넌트를 호출하는 컴포넌트)
import { CalendarPop } from "@/elements/library_elements";
import { getFormatedDate } from "@/components/common/common";
import { useEffect, useState } from "react";
const Test = () => {
const [startDate, setStartDate] = useState(new Date()); // 시작 날짜
const [endDate, setEndDate] = useState(null); // 종료 날짜
const [info, setInfo] = useState({ startDate: "", endDate: "" });
// 다음날 구하는 함수
const nextDay = () => {
if (endDate) {
const today = endDate.setDate(endDate.getDate() + 1);
return today;
}
};
// 시작일이 바뀌면 날짜 형식 format 해서 info에 저장
useEffect(() => {
if (startDate) {
const date = getFormatedDate(startDate);
setInfo({
...info,
startDate: date,
});
}
}, [startDate]);
// 종료일이 바뀌면 날짜 형식 format 해서 info에 저장
useEffect(() => {
if (endDate) {
const date = getFormatedDate(endDate);
setInfo({
...info,
endDate: date,
});
}
}, [endDate]);
return (
<CalendarPop
type="input_calendar"
startDate={startDate}
setStartDate={setStartDate}
endDate={endDate}
setEndDate={setEndDate}
nextDay={nextDay}
info={info}
/>
);
};
export default Test;
Calendar.js (자식 컴포넌트 - Calendar.js)
import styled from "styled-components";
import DatePicker, { registerLocale } from "react-datepicker"; // DatePicker 컴포넌트 가져오기
import { addMonths } from "date-fns"; // DatePicker에 부가적인 기능 가져오고 싶을 때 해당 함수들 date-fns에서 import 해오기
// 출처: https://reactdatepicker.com/#example-filter-dates
// 출처: https://date-fns.org/
import ko from "date-fns/locale/ko"; // 한국어로
registerLocale("ko", ko); // 한국어로
const _ = require("lodash"); // _.range를 표현하기 위하여 사용
// 출처: https://blog.naver.com/PostList.naver?blogId=marsdo
import ArrowLeftSvg from "public/img/common/arrow-left.svg";
import ArrowRightSvg from "public/img/common/arrow-right.svg";
const CalendarPop = (props) => {
const { startDate, setStartDate, endDate, setEndDate, nextDay, info, type } =
props;
const months = [
// 월 표시
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12",
];
if (type === "input_calendar") {
return (
<InputDateStyle>
<div className="calendar_wrap_1">
<form autoComplete="off">
<DatePicker
className={`startDate ${startDate ? "active" : undefined}`}
id="startDate"
selected={startDate}
onChange={(date) => setStartDate(date)}
selectsStart
startDate={startDate}
endDate={endDate}
// 구분선
minDate={new Date()}
maxDate={addMonths(new Date(), 100)}
showDisabledMonthNavigation
// 구분선
locale="ko"
showPoperArrow={false}
fixedHeight
renderCustomHeader={({
date,
decreaseMonth,
increaseMonth,
prevMonthButtonDisabled,
nexMonthButtonDisabled,
}) => (
<div className="date-customheader">
<ArrowLeftSvg
onClick={decreaseMonth}
width={20}
height={20}
style={
prevMonthButtonDisabled
? { visibility: "hidden" }
: { display: "block" }
}
/>
<div className="custom-month">
<span className="month">{months[date.getMonth()]}월,</span>
<span className="year"> {date.getFullYear()}</span>
</div>
<ArrowRightSvg
onClick={increaseMonth}
width={20}
height={20}
style={
nexMonthButtonDisabled
? { visibility: "hidden", marginTop: "4px" }
: { display: "block", marginTop: "4px" }
}
/>
</div>
)}
/>
<label htmlFor="startDate" className="startDate_label">
<span>
{info.startDate}
</span>
</label>
</form>
</div>
<p>~</p>
<div className="calendar_wrap_2">
<form autoComplete="off">
<DatePicker
className={`endDate ${endDate ? "active" : undefined}`}
id="endDate"
autocomplete="off"
selected={endDate ? endDate : nextDay()}
onChange={(date) => setEndDate(date)}
selectsEnd
startDate={startDate}
endDate={endDate}
minDate={startDate}
// 구분선
locale="ko"
showPoperArrow={false}
fixedHeight
renderCustomHeader={({
date,
decreaseMonth,
increaseMonth,
prevMonthButtonDisabled,
nexMonthButtonDisabled,
}) => (
<div className="date-customheader">
<ArrowLeftSvg
onClick={decreaseMonth}
width={20}
height={20}
style={
prevMonthButtonDisabled
? { visibility: "hidden" }
: { display: "block" }
}
/>
<div className="custom-month">
<span className="month">{months[date.getMonth()]}월,</span>
<span className="year"> {date.getFullYear()}</span>
</div>
<ArrowRightSvg
onClick={increaseMonth}
width={20}
height={20}
style={
nexMonthButtonDisabled
? { visibility: "hidden", marginTop: "4px" }
: { display: "block", marginTop: "4px" }
}
/>
</div>
)}
/>
<label htmlFor="endDate" className="endDate_label">
<span>
{info.endDate}
</span>
</label>
</form>
</div>
</InputDateStyle>
);
}
return (
<DateStyle>
...v1 생략
</DateStyle>
);
};
export default CalendarPop;
v2_CSS
const InputDateStyle = styled.section`
width: 300px;
height: 40px;
position: relative;
margin-top: 200px;
display: flex;
justify-content: center;
align-content: center;
.calendar_wrap_1,
.calendar_wrap_2 {
position: relative;
.startDate_label,
.endDate_label {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
font: normal normal normal 16px/19px Pretendard;
letter-spacing: 0px;
color: #333333;
height: 40px;
line-height: 42px;
}
}
// ~
p {
display: inline-block;
padding: 0 10px;
font: normal normal normal 15px/15px Pretendard;
letter-spacing: 0px;
color: #666666;
line-height: 40px;
}
// 드래그 방지
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
// 이미지 위치 조절
.react-datepicker-wrapper {
display: block;
width: auto;
}
// 달력 위치 조절
.react-datepicker-popper {
top: -180px !important;
left: 110% !important;
z-index: 100;
transition: all 0.5s;
}
// 달력 이미지 사용을 위해 input 박스 커스텀하는 부분
& #startDate:checked + label,
& #endDate:checked + label {
background-color: #038dff;
border: 2px solid #038dff;
}
& #startDate,
#endDate {
width: 130px;
height: 40px;
background: #fbfbfb 0% 0% no-repeat padding-box;
border: 1px solid #eeeeee;
border-radius: 8px;
text-align: center;
font: normal normal normal 16px/19px Pretendard;
letter-spacing: 0px;
color: white;
&::selection {
color: white;
}
}
.active {
background: #ffffff 0% 0% no-repeat padding-box !important;
}
#startDate::before,
#startDate::after,
#endDate::before,
#endDate::after {
content: "\e99c";
display: inline-block;
position: absolute;
top: 7px;
left: 7px;
font-family: icomoon !important;
font-size: 1rem;
color: #333;
border: 1px solid #ffffff;
}
// 달력 Header 조절
.date-customheader {
display: flex;
justify-content: space-between;
margin: 0 10px;
svg {
cursor: pointer;
stroke: #666666;
stroke-width: 2px;
margin-top: 4px;
}
}
.react-datepicker__day-names {
font-size: 12px;
margin-top: 10px;
.react-datepicker__day-name {
color: #0072de;
}
}
.react-datepicker__header {
background: #fff;
border-bottom: 1px solid #eeeeee;
padding: 10px;
}
// 달력 헤더 > 월, 년 부분
.custom-month {
margin-top: 5px;
.month {
color: #000000;
font-size: 17px;
}
.year {
color: #666666;
font-size: 15px;
}
}
// 달력 Content 부분
.react-datepicker-popper[data-placement^="bottom"]
.react-datepicker__triangle::before,
.react-datepicker-popper[data-placement^="bottom"]
.react-datepicker__triangle::after {
border-top: none;
border-bottom: none;
}
.react-datepicker-popper[data-placement^="top"]
.react-datepicker__triangle::before,
.react-datepicker-popper[data-placement^="top"]
.react-datepicker__triangle::after {
border-top: none;
border-bottom: none;
}
.react-datepicker__day--selected,
.react-datepicker__day--in-selecting-range,
.react-datepicker__day--in-range,
.react-datepicker__month-text--selected,
.react-datepicker__month-text--in-selecting-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--selected,
.react-datepicker__quarter-text--in-selecting-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--selected,
.react-datepicker__year-text--in-selecting-range,
.react-datepicker__year-text--in-range {
background: #0072de;
}
`;
728x90
'더 알아보기 > 기능' 카테고리의 다른 글
ToolTip (1) - HTML/CSS (0) | 2022.05.11 |
---|---|
IOS에서 input focus 시 자동으로 zoom 되는 현상 막기 (0) | 2022.04.25 |
[React] 부트스트랩 페이징 구현하기 (0) | 2022.04.11 |
[Next.js] Chart.js (0) | 2022.04.06 |
차트(Chart) 라이브러리 (0) | 2022.04.06 |
댓글