src/View/Main/MainView.js
이제 MainView
를 살펴보겠다.
import React, { useState } from "react";
import Modal from "../../components/Modal/Modal";
import Calender from "../../components/Calender/Calender";
import HourSelector from "../../components/HourSelector/HourSelector";
import MinuteSelector from "../../components/MinuteSelector/MinuteSelector";
import Divider from "../../components/Divider/Divider";
import "./index.scss";
const MainView = (props) => {
const [visible, setVisible] = useState(false);
// modal을 보여줄지 말지 결정.
const [calender, setCalender] = useState(false);
// calender 가 start 인지 finish 인지 상태를 담고있음.
const _showDate = () => {
// 날짜가 모두 선택되고 난 뒤, 보여지는 내용
if (props.date !== undefined) {
const {
startDay,
startMinute,
startHour,
finishDay,
finishMinute,
finishHour,
} = props.date;
return (
<>
<div>응시 시작일 : {startDay ? startDay : "선택해주세요."}</div>
<div>
응시 시간 : <span>{startHour ? startHour : "미정"}</span>
<span>{startMinute ? startMinute : "미정"}</span>
</div>
<div>응시 마감일 : {finishDay ? finishDay : "선택해주세요."}</div>
<div>
응시 마감시간 : <span>{finishHour ? finishHour : "미정"}</span>
<span>{finishMinute ? finishMinute : "미정"}</span>
</div>
</>
);
} else {
return;
}
};
return (
<div>
<button className="call-modal" onClick={() => setVisible(!visible)}>
모달호출
</button>
<Modal
visible={visible}
setCalender={(e) => setCalender(e)}
setVisible={(e) => setVisible(e)}
date={props.date}
>
<br />
<div className="date-txt">응시 시작일</div>
<br />
<input
className="date-picker start"
readOnly
placeholder="날짜를 선택해 주세요."
value={props.date && props.date.startDay}
style={{
backgroundColor: props.date && props.date.startDay ? "#efefef" : "",
}}
onClick={() => setCalender("start")}
/>
{calender === "start" && (
<Calender
{...props}
status={"start"}
setCalender={(e) => setCalender(e)}
/>
)}
<HourSelector status="start" {...props} />
<MinuteSelector status="start" {...props} />
<Divider margin={"0 0 40px 0"} height="40px" />
<div className="date-txt">응시 마감일</div>
<br />
<input
className="date-picker finish"
readOnly
placeholder="날짜를 선택해 주세요."
value={props.date && props.date.finishDay}
style={{
backgroundColor:
props.date && props.date.finishDay ? "#efefef" : "",
}}
onClick={() => setCalender("finish")}
/>
{calender === "finish" && (
<Calender
{...props}
status="finish"
setCalender={(e) => setCalender(e)}
/>
)}
<HourSelector {...props} />
<MinuteSelector {...props} />
</Modal>
<div className="result" style={{ display: visible ? "none" : "block" }}>
{_showDate()}
</div>
</div>
);
};
export default MainView;
visible
은 모달이 보여질지 말지 관리하는 변수이다.calender
는 calender 창이 보여질지 말지 관리하는 변수._showDate
는 날짜가 모두 선택되어지고 보여질 글씨를 리턴하는 함수이다. (중요X)<Modal>
컴포넌트로 감싸져 있다. 이 Modal Component 는 props 로 visible, setVisible, setCalender , date 를 받는다.children
으로 받게 된다.Calender
,HourSelector
,MinuteSelector
가 들어간다.src/components/Calender/Calender.js
import React, { useState } from "react";
import moment from "moment";
import "./index.scss";
const Calender = (props) => {
const [select, setSelect] = useState(null);
const [choiceMonth, setChoiceMonth] = useState(moment());
// * 1. 현재 시간을 choiceMonth 로 설정함.
const dayname = () => {
let labels = [];
for (let i = 1; i <= 7; i++) {
let dayOfWeek = moment().day(i).format("dd");
if (dayOfWeek === "Mo") {
dayOfWeek = "월";
} else if (dayOfWeek === "Tu") {
dayOfWeek = "화";
} else if (dayOfWeek === "We") {
dayOfWeek = "수";
} else if (dayOfWeek === "Th") {
dayOfWeek = "목";
} else if (dayOfWeek === "Fr") {
dayOfWeek = "금";
} else if (dayOfWeek === "Sa") {
dayOfWeek = "토";
} else if (dayOfWeek === "Su") {
dayOfWeek = "일";
}
labels.push(
<div className="label" key={i}>
{dayOfWeek}
</div>
);
}
return labels;
};
const _dayClick = (date) => {
setSelect(date);
let finishStoreData = Object.assign({}, props.date, { finishDay: date });
let startStoreData = Object.assign({}, props.date, { startDay: date });
let storeData = props.status === "start" ? startStoreData : finishStoreData;
props.viewAction.receiveView("date", storeData);
};
const generate = () => {
const today = choiceMonth;
const startWeek = today.clone().startOf("month").week();
// clone 을 하는 이유 : moment 객체가 변할 수 있는(mutable) 성질이 있어서 해당 시간 고정을 위해 clone 사용함.
// * startWeek : 현재월의 첫번째날이 몇번째 주 인지
const endWeek =
today.clone().endOf("month").week() === 1
? 53
: today.clone().endOf("month").week();
// * endweek : 현재월의 마지막달이 몇번째 주 인지
let calendar = [];
for (let week = startWeek; week <= endWeek; week++) {
calendar.push(
<div className="day-row" key={week}>
{Array(7)
.fill(0)
.map((n, i) => {
let current = today
.clone()
.week(week)
.startOf("week")
.add(n + i, "day");
// * current : for문에 있는 week 의 day를 담고 있는 변수
let isToday =
moment().format("YYYYMMDD") === current.format("YYYYMMDD")
? "today"
: "";
// * isToday : moment의 현재날짜와 current 가 가지고 있는 현재날짜가 같으면 today 를 담고있음.
let isGrayed =
current.format("MM") === today.format("MM") ? "" : "grayed";
// * current 의 month 와 today의 month 가 같으면 "" 다르면 grayed 라는 변수 담고 있음.
let isSelectDay =
select === current.format("YYYY-MM-DD") ? "choice" : "";
// * 선택한 날짜와 current 가 같으면 choice 라는 변수를 담고있음.
return (
<div key={i} className="day-col">
<div
onClick={
() =>
_dayClick(
current
.clone()
.add(n + 1, "day")
.toISOString()
.split("T")[0]
)
// 클릭할 때 선택한 날의 YYYY-MM-DD 를 넘김
}
className={`box ${isToday} ${isSelectDay} ${isGrayed}`}
>
{current.format("D")}
</div>
</div>
);
})}
</div>
);
}
return calendar;
};
// console.log(props);
return (
<div className="calender-wrapper">
<div className="month-row">
<span style={{ fontWeight: "bold" }}>
{choiceMonth.format(
"YYYY MM".split(" ")[0] +
"년" +
" " +
choiceMonth.format("YYYY MM").split(" ")[1] +
"월"
)}
</span>
<span>
<span
onClick={() =>
setChoiceMonth(choiceMonth.clone().subtract(1, "month"))
}
className="arrow"
style={{ marginRight: 20 }}
>
<img src={require("../../img/btn-arrow-back.png")} alt="" />
</span>
<span
onClick={() => setChoiceMonth(choiceMonth.clone().add(1, "month"))}
className="arrow"
>
<img src={require("../../img/btn-arrow-front.png")} alt="" />
</span>
</span>
</div>
<div className="day-row">
{dayname().map((day, idx) => (
<div key={idx} className="day-col">
{day}
</div>
))}
</div>
{generate()}
</div>
);
};
export default Calender;
우선 dayname
함수는 영어로 된 요일 이름을 한글로 바꾸기 위해 사용함.
_dayClick
함수는 날짜를 선택했을 때 store 에 저장하기 위해 사용함.
generate 함수 : 설명이 길어서 주석으로 설명을 대체함.
./calender.scss
내용을 첨부함. (클래스 이름에 따라 색 변경)
.calender-wrapper {
width: 300px;
border-radius: 10px;
background-color: #f9f9f9;
padding: 10px;
position: absolute;
z-index: 200;
.month-row {
display: flex;
justify-content: space-between;
margin: 15px 0;
.arrow {
text-align: center;
font-size: 20px;
width: 25px;
line-height: 1.5;
height: 25px;
display: inline-block;
cursor: pointer;
border-radius: 15px;
background-color: #dbdbdb;
opacity: 0.3;
}
.arrow:hover {
transition: 0.3s all ease;
opacity: 0.6;
}
}
.day-row {
display: flex;
justify-content: space-between;
margin-bottom: 1px;
.day-col {
text-align: center;
position: relative;
display: inline-flex;
width: calc(100% / 7);
height: 50px;
font-size: 12pt;
.box {
display: inline-block;
margin: auto;
width: 25px;
height: 25px;
line-height: 1.7;
cursor: pointer;
border-radius: 13px;
&.today {
background-color: #dbdbdb;
// today 면
}
&.grayed {
color: darkgray;
// 이번달이 아니면 회색 처리
}
&.choice {
background-color: #4c80f1;
color: #fff;
// 선택한 날이면 배경색 변경 및 글짜 색 흰색
}
&.choice:hover {
background-color: #2263f0;
color: #fff;
// 선택한 날에 마우스 hover
}
}
.box:hover {
color: #4c80f1;
background-color: #93b5ff;
}
.label {
display: inline-block;
margin: auto;
}
}
}
}
코드양이 길어져 selectHour
부분은 다음 포스팅에 이어서작성