diff --git a/app/assets/javascripts/components/common/calendar.jsx b/app/assets/javascripts/components/common/calendar.jsx index 32aaae8baf..691c864d15 100644 --- a/app/assets/javascripts/components/common/calendar.jsx +++ b/app/assets/javascripts/components/common/calendar.jsx @@ -1,56 +1,39 @@ -import React from 'react'; -import createReactClass from 'create-react-class'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import DayPicker from 'react-day-picker'; import { compact } from 'lodash-es'; import WeekdayPicker from './weekday_picker.jsx'; import CourseDateUtils from '../../utils/course_date_utils.js'; import { toDate } from '../../utils/date_utils.js'; -import { format, getDay, isValid } from 'date-fns'; +import { format, getDay } from 'date-fns'; function __in__(needle, haystack) { return haystack.indexOf(needle) >= 0; } -const Calendar = createReactClass({ - displayName: 'Calendar', - propTypes: { - course: PropTypes.object, - weeks: PropTypes.array, - calendarInstructions: PropTypes.string, - editable: PropTypes.bool, - shouldShowSteps: PropTypes.bool, - updateCourse: PropTypes.func.isRequired - }, +const Calendar = ({ + course, + weeks, + calendarInstructions, + editable, + shouldShowSteps, + updateCourse, +}) => { + const [initialMonth, setInitialMonth] = useState(() => toDate(course.start)); - statics: { - getDerivedStateFromProps(props) { - return { - initialMonth: toDate(props.course.start) - }; - } - }, + useEffect(() => { + setInitialMonth(toDate(course.start)); + }, [course.start]); - getInitialState() { - return ({ initialMonth: toDate(this.props.course.start) }); - }, - shouldComponentUpdate(nextProps) { - if (nextProps.course) { - const start = toDate(nextProps.course.start); - const end = toDate(nextProps.course.end); - return isValid(start) && isValid(end); - } - return true; - }, - selectDay(day) { + const selectDay = (day) => { + if (!inrange(day)) return; let exceptions; - if (!this.inrange(day)) { return; } - const { course } = this.props; - if (course.day_exceptions === undefined) { - course.day_exceptions = ''; + const updatedCourse = { ...course }; + if (updatedCourse.day_exceptions === undefined) { + updatedCourse.day_exceptions = ''; exceptions = []; } else { - exceptions = course.day_exceptions.split(','); + exceptions = updatedCourse.day_exceptions.split(','); } const formatted = format(day, 'yyyyMMdd'); if (__in__(formatted, exceptions)) { @@ -58,141 +41,163 @@ const Calendar = createReactClass({ } else { exceptions.push(formatted); const utils = CourseDateUtils; - if (utils.wouldCreateBlackoutWeek(this.props.course, day, exceptions) && utils.moreWeeksThanAvailable(this.props.course, this.props.weeks, exceptions)) { + if ( + utils.wouldCreateBlackoutWeek(updatedCourse, day, exceptions) + && utils.moreWeeksThanAvailable(updatedCourse, weeks, exceptions) + ) { alert(I18n.t('timeline.blackout_week_created')); return false; } } - course.day_exceptions = exceptions.join(','); - course.no_day_exceptions = (compact(exceptions).length === 0); - return this.props.updateCourse(course); - }, - selectWeekday(e, weekday) { + updatedCourse.day_exceptions = exceptions.join(','); + updatedCourse.no_day_exceptions = compact(exceptions).length === 0; + return updateCourse(updatedCourse); + }; + + const selectWeekday = (e, weekday) => { + const updatedCourse = { ...course }; let weekdays; - const toPass = this.props.course; - if (!(toPass.weekdays !== undefined)) { - toPass.weekdays = ''; + if (!(updatedCourse.weekdays !== undefined)) { + updatedCourse.weekdays = ''; weekdays = []; } else { - weekdays = toPass.weekdays.split(''); + weekdays = updatedCourse.weekdays.split(''); } weekdays[weekday] = weekdays[weekday] === '1' ? '0' : '1'; - toPass.weekdays = weekdays.join(''); - return this.props.updateCourse(toPass); - }, - inrange(day) { - const { course } = this.props; - if (course.start === undefined) { return false; } + updatedCourse.weekdays = weekdays.join(''); + return updateCourse(updatedCourse); + }; + + const inrange = (day) => { + if (course.start === undefined) return false; const start = new Date(course.start); const end = new Date(course.end); return start < day && day < end; - }, - render() { - const modifiers = { - ['outrange']: (day) => { - return !this.inrange(day); - }, - ['selected']: (day) => { - if ((this.props.course.weekdays !== undefined) && this.props.course.weekdays.charAt(day) === '1') { - return true; - } else if (day < 8) { - return false; - } - const formatted = format(day, 'yyyyMMdd'); - const inrange = this.inrange(day); - let exception = false; - let weekday = false; - if (this.props.course.day_exceptions !== undefined) { - exception = __in__(formatted, this.props.course.day_exceptions.split(',')); - } - if (this.props.course.weekdays) { - // from 0 to 6. 0 is sunday - const weekNumber = getDay(day); - weekday = this.props.course.weekdays.charAt(weekNumber) === '1'; - } - return inrange && ((weekday && !exception) || (!weekday && exception)); - }, - ['highlighted']: (day) => { - if (day <= 7) { return false; } - return this.inrange(day); - }, - ['bordered']: (day) => { - if (day <= 7) { return false; } - if (!this.props.course.day_exceptions || !this.props.course.weekdays) { return false; } - const formatted = format(day, 'yyyyMMdd'); - const inrange = this.inrange(day); - const exception = __in__(formatted, this.props.course.day_exceptions.split(',')); + }; + + const modifiers = { + ['outrange']: (day) => { + return !inrange(day); + }, + ['selected']: (day) => { + if ( + course.weekdays !== undefined + && course.weekdays.charAt(day) === '1' + ) { + return true; + } else if (day < 8) { + return false; + } + const formatted = format(day, 'yyyyMMdd'); + const inRange = inrange(day); + let exception = false; + let weekday = false; + if (course.day_exceptions !== undefined) { + exception = __in__(formatted, course.day_exceptions.split(',')); + } + if (course.weekdays) { const weekNumber = getDay(day); - const weekday = this.props.course.weekdays.charAt(weekNumber) === '1'; - return inrange && exception && weekday; + weekday = course.weekdays.charAt(weekNumber) === '1'; } - }; + return inRange && ((weekday && !exception) || (!weekday && exception)); + }, + ['highlighted']: (day) => { + if (day <= 7) return false; + return inrange(day); + }, + ['bordered']: (day) => { + if (day <= 7) return false; + if (!course.day_exceptions || !course.weekdays) return false; + const formatted = format(day, 'yyyyMMdd'); + const inRange = inrange(day); + const exception = __in__(formatted, course.day_exceptions.split(',')); + const weekNumber = getDay(day); + const weekday = course.weekdays.charAt(weekNumber) === '1'; + return inRange && exception && weekday; + }, + }; - const editDaysText = I18n.t('courses.calendar.select_meeting_days'); - const editCalendarText = this.props.calendarInstructions; + const editDaysText = I18n.t('courses.calendar.select_meeting_days'); + const editCalendarText = calendarInstructions; - let editingDays; - let editingCalendar; - if (this.props.editable) { - if (this.props.shouldShowSteps) { - editingDays = (
{editDaysText}
); - editingCalendar = ( -{editCalendarText}
- ); - } + let editingDays; + let editingCalendar; + if (editable) { + if (shouldShowSteps) { + editingDays = ( +{editDaysText}
; + editingCalendar ={editCalendarText}
; } + } + const onWeekdayClick = editable ? selectWeekday : null; + const onDayClick = editable ? selectDay : null; - const onWeekdayClick = this.props.editable ? this.selectWeekday : null; - const onDayClick = this.props.editable ? this.selectDay : null; - - return ( -