Commit ff9dad79 authored by Kim, Subin's avatar Kim, Subin
Browse files

Monthly

parent cf42430e
......@@ -8,15 +8,19 @@
"name": "client",
"version": "0.1.0",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@fullcalendar/bootstrap": "^5.10.0",
"@fullcalendar/daygrid": "^5.10.0",
"@fullcalendar/interaction": "^5.10.0",
"@fullcalendar/react": "^5.10.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"axios": "^0.21.4",
"bootstrap": "^5.1.1",
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.5.0",
"formik": "^2.2.9",
"moment": "^2.29.1",
"node-sass": "^6.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
......@@ -1824,6 +1828,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@fortawesome/fontawesome-free": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@fullcalendar/bootstrap": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/bootstrap/-/bootstrap-5.10.0.tgz",
"integrity": "sha512-PCuGBWk5a6lj2AOJFy/NX26FVYaYK+MjM3FYyTbai8Zuv1YpwFnHVTM5jziln4rmRu4A3ggIzhe0IPz0j+2tEw==",
"dependencies": {
"@fullcalendar/common": "~5.10.0",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/common": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.10.0.tgz",
......@@ -1841,6 +1863,15 @@
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/interaction": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-5.10.0.tgz",
"integrity": "sha512-zTNaly+4VkcrxxQy5oY0D8hGH+3Dkfm/0GB1dHi/NkP/z/JTACw6CUkFYbM5tynkaDkVIoU2cUXPMFf25sjU8w==",
"dependencies": {
"@fullcalendar/common": "~5.10.0",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/react": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-5.10.0.tgz",
......@@ -5399,15 +5430,15 @@
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"node_modules/bootstrap": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.1.tgz",
"integrity": "sha512-/jUa4sSuDZWlDLQ1gwQQR8uoYSvLJzDd8m5o6bPKh3asLAMYVZKdRCjb1joUd5WXf0WwCNzd2EjwQQhupou0dA==",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
},
"peerDependencies": {
"@popperjs/core": "^2.10.1"
"@popperjs/core": "^2.10.2"
}
},
"node_modules/bootstrap-icons": {
......@@ -14327,6 +14358,14 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
......@@ -24354,6 +24393,20 @@
}
}
},
"@fortawesome/fontawesome-free": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
},
"@fullcalendar/bootstrap": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/bootstrap/-/bootstrap-5.10.0.tgz",
"integrity": "sha512-PCuGBWk5a6lj2AOJFy/NX26FVYaYK+MjM3FYyTbai8Zuv1YpwFnHVTM5jziln4rmRu4A3ggIzhe0IPz0j+2tEw==",
"requires": {
"@fullcalendar/common": "~5.10.0",
"tslib": "^2.1.0"
}
},
"@fullcalendar/common": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.10.0.tgz",
......@@ -24371,6 +24424,15 @@
"tslib": "^2.1.0"
}
},
"@fullcalendar/interaction": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-5.10.0.tgz",
"integrity": "sha512-zTNaly+4VkcrxxQy5oY0D8hGH+3Dkfm/0GB1dHi/NkP/z/JTACw6CUkFYbM5tynkaDkVIoU2cUXPMFf25sjU8w==",
"requires": {
"@fullcalendar/common": "~5.10.0",
"tslib": "^2.1.0"
}
},
"@fullcalendar/react": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-5.10.0.tgz",
......@@ -27099,9 +27161,9 @@
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"bootstrap": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.1.tgz",
"integrity": "sha512-/jUa4sSuDZWlDLQ1gwQQR8uoYSvLJzDd8m5o6bPKh3asLAMYVZKdRCjb1joUd5WXf0WwCNzd2EjwQQhupou0dA==",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
"requires": {}
},
"bootstrap-icons": {
......@@ -33875,6 +33937,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
......@@ -3,15 +3,19 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@fullcalendar/bootstrap": "^5.10.0",
"@fullcalendar/daygrid": "^5.10.0",
"@fullcalendar/interaction": "^5.10.0",
"@fullcalendar/react": "^5.10.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"axios": "^0.21.4",
"bootstrap": "^5.1.1",
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.5.0",
"formik": "^2.2.9",
"moment": "^2.29.1",
"node-sass": "^6.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
......
......@@ -4,7 +4,7 @@ const CalendarBtn = ({ date }) => {
return (
<div className={`d-inline-block position-relative text-center ${styles.calendar}`}>
<strong className="position-absolute top-0 text-white">Today</strong>
<span>10</span>
<span>{date}</span>
</div>
)
}
......
import { Calendar } from '@fullcalendar/core';
import { useState, useEffect, useRef } from "react";
import { useHistory } from "react-router-dom";
import CalendarBtn from "../Buttons/CalendarBtn.js";
import DatePickerModal from "../Modal/DatePickerModal.js";
import moment from 'moment';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from "@fullcalendar/interaction";
import bootstrapPlugin from '@fullcalendar/bootstrap';
import '@fortawesome/fontawesome-free/css/all.css';
const Monthly = () => {
const [initialDate, setInitialDate] = useState(moment().format('YYYY-MM-DD'))
const [changeDate, setChangeDate] = useState(moment().format('YYYY-MM-DD'))
const [show, setShow] = useState(false)
const calenIconRef = useRef(null)
const calendarRef = useRef(null)
let calendar = null
const history = useHistory();
useEffect(() => {
if (calendarRef && calendarRef.current) {
calendar = calendarRef.current.getApi()
}
})
useEffect(() => {
if (calenIconRef && calenIconRef.current) {
calenIconRef.current.addEventListener('click', () => {
calendar.today()
let date = moment(calendar.getDate()).format('YYYY-MM-DD')
setChangeDate(date)
})
}
return () => {
if (calenIconRef && calenIconRef.current) {
calenIconRef.current.removeEventListener('click', () => {
calendar.today()
let date = moment(calendar.getDate()).format('YYYY-MM-DD')
setChangeDate(date)
})
}
}
}, [calenIconRef.current])
useEffect(() => {
calendar.gotoDate(changeDate)
}, [changeDate])
return (
<></>
<>
<div ref={calenIconRef} className="position-absolute" style={{ top: "9px", right: "8px" }}>
<CalendarBtn date={moment(initialDate).format('DD')} />
</div>
<FullCalendar
ref={calendarRef}
plugins={[dayGridPlugin, interactionPlugin, bootstrapPlugin]}
initialView="dayGridMonth"
initialDate={initialDate}
headerToolbar={{
start: 'prev',
center: 'myCustomButton',
end: 'next'
}}
dayHeaderContent={(date) => {
const weekList = ["", "", "", "", "", "", ""]
return weekList[date.dow]
}}
validRange={{
start: moment(initialDate).subtract(3, 'years').format('YYYY-MM[-01]'),
end: moment(initialDate).add(3, 'years').add(1, 'months').format('YYYY-MM[-01]')
}}
customButtons={{
myCustomButton: {
text: moment(changeDate).format('YYYY.MM'),
click: () => {
setShow(true)
return <button className="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#datePicker" aria-controls="datePicker" />
}
},
prev: {
icon: "fa-chevron-left",
click: () => {
calendar.prev()
let date = moment(calendar.getDate()).format('YYYY-MM-DD')
setChangeDate(date)
}
},
next: {
icon: "fa-chevron-right",
click: () => {
calendar.next()
let date = moment(calendar.getDate()).format('YYYY-MM-DD')
setChangeDate(date)
}
}
}}
dateClick={({ dateStr }) => history.push(`/schedule/${dateStr}`)}
timeZone="local"
themeSystem='bootstrap'
eventLimit="true"
height='75vh'
/>
<DatePickerModal initialDate={initialDate} changeDate={changeDate} setChangeDate={setChangeDate} show={show} setShow={setShow} />
</>
)
}
......
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
const Weekly = () => {
return (
<FullCalendar
plugins={[dayGridPlugin]}
initialView="dayGridWeek"
defaultView="dayGridWeek"
headerToolbar={{
start: 'prev',
center: 'title',
end: 'next'
}}
/>
)
}
export default Weekly
\ No newline at end of file
import { Link } from "react-router-dom";
import { Link, Redirect } from "react-router-dom";
import moment from "moment";
import styles from "./menu.module.scss";
const Menu = () => {
......@@ -35,7 +36,7 @@ const Menu = () => {
</Link>
</div>
<div className="d-flex flex-column">
<Link className="text-dark text-decoration-none" to="/schedule"><i className="bi bi-check"></i>일정</Link>
<Link className="text-dark text-decoration-none" to={`/schedule/${moment().format("YYYY-MM-DD")}`}><i className="bi bi-check"></i>일정</Link>
<Link className="text-dark text-decoration-none" to="/studyplan"><i className="bi bi-check"></i>학업별 계획</Link>
</div>
<p className={`position-absolute bottom-0 text-dark ${styles.logout}`}>로그아웃</p>
......
import { useState, useEffect } from "react";
import moment from 'moment';
const DatePickerModal = ({ initialDate, changeDate, setChangeDate, show, setShow }) => {
const [date, setDate] = useState({ year: moment(changeDate).get('year'), month: moment(changeDate).get('month') + 1 })
const [year, setYear] = useState({ start: moment(initialDate).get('year') - 3, end: moment(initialDate).get('year') + 3 })
const month = moment(initialDate).get('month') + 1
useEffect(() => {
setDate({ year: moment(changeDate).get('year'), month: moment(changeDate).get('month') + 1 })
}, [changeDate])
function up(e) {
const { id } = e.target
if (id === "year") {
if (date[id] < year.end) setDate({ ...date, [id]: date[id] + 1 })
} else {
if (date[id] === 12) setDate({ ...date, [id]: 1 })
else setDate({ ...date, [id]: date[id] + 1 })
}
}
function down(e) {
const { id } = e.target
if (id === "year") {
if (date[id] > year.start) setDate({ ...date, [id]: date[id] - 1 })
} else {
if (date[id] === 1) setDate({ ...date, [id]: 12 })
else setDate({ ...date, [id]: date[id] - 1 })
}
}
function cancel() {
setDate({ year: moment(changeDate).get('year'), month: moment(changeDate).get('month') + 1 })
setShow(false)
}
function handleClick() {
if (date.year === year.start) {
if (month > date.month) alert("선택하신 날짜는 유효하지 않습니다. 다시 선택해주세요.")
else {
let dateStr = date.year + "-" + date.month + "-01"
setChangeDate(moment(dateStr).format("YYYY-MM-DD"))
setShow(false)
}
} else if (date.year === year.end) {
if (month < date.month) alert("선택하신 날짜는 유효하지 않습니다. 다시 선택해주세요.")
else {
let dateStr = date.year + "-" + date.month + "-01"
setChangeDate(moment(dateStr).format("YYYY-MM-DD"))
setShow(false)
}
} else {
let dateStr = date.year + "-" + date.month + "-01"
setChangeDate(moment(dateStr).format("YYYY-MM-DD"))
setShow(false)
}
}
return (
<>
{show ? <div className="offcanvas-backdrop fade show"></div> : null}
<div className={"offcanvas offcanvas-bottom " + (show ? "visible show" : "invisiblel")} tabIndex="-1" id="datePicker" aria-labelledby="datePicker">
<div className="offcanvas-body small py-2">
<div className="d-flex my-3">
<div className="col-6 d-flex flex-column justify-content-between align-items-center fs-4">
<i className="bi bi-caret-up-fill" id="year" onClick={up}></i>
{date.year}
<i className="bi bi-caret-down-fill" id="year" onClick={down}></i>
</div>
<div className="col-6 d-flex flex-column justify-content-between align-items-center fs-4">
<i className="bi bi-caret-up-fill" id="month" onClick={up}></i>
{date.month < 10 ? "0" + date.month : date.month}
<i className="bi bi-caret-down-fill" id="month" onClick={down}></i>
</div>
</div>
<div className="d-flex pt-2 border-top border-dark">
<div className="col-6" data-bs-dismiss="offcanvas">
<p className="text-center fs-6 py-1 mb-0" onClick={cancel}>취소</p>
</div>
<div className="col-6" data-bs-dismiss="offcanvas" onClick={handleClick}>
<p className="text-center fs-6 py-1 mb-0">완료</p>
</div>
</div>
</div>
</div>
</>
)
}
export default DatePickerModal
\ No newline at end of file
import Menu from "../components/Menu/Menu.js";
import CalendarBtn from "../components/Buttons/CalendarBtn.js";
import Monthly from "../components/Calendar/Monthly.js";
import Footer from "../components/Footer.js";
const HomePage = () => {
return (
<>
<Menu />
<div className="position-absolute" style={{ top: "9px", right: "8px" }}>
<CalendarBtn date="2021-10-28" />
</div>
<Monthly />
<Footer pathname="schedule/edit" />
</>
)
......
......@@ -65,3 +65,60 @@ button {
width: 400px;
}
}
.fc {
margin-top: 1em;
& a {
text-decoration: none;
}
& table > * {
border-style: none;
border-width: 0;
}
& .fc-prev-button, & .fc-next-button {
background-color: #fff;
border: 0;
color: #000;
&:focus {
box-shadow: none;
}
}
& .fc-myCustomButton-button {
background-color: #fff;
border: 0;
color: #000;
font-size: 1.4em;
padding: 0;
&:focus {
box-shadow: none;
}
}
& .fc-day-today {
background-color: #fff !important;
& .fc-daygrid-day-number {
border-radius: 13px;
background-color: crimson;
color: #fff;
}
}
& .fc-day-other {
color: gray;
}
& td.fc-day-sat:not(.fc-day-other) {
color: #0000FF;
}
& td.fc-day-sun:not(.fc-day-other) {
color: #FF0000;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment