import React from 'react'; import PropTypes from 'prop-types'; import createClass from 'create-react-class'; import moment from '../moment-range'; import calendar from 'calendar'; import Immutable from 'immutable'; import BemMixin from '../utils/BemMixin'; import CustomPropTypes from '../utils/CustomPropTypes'; import isMomentRange from '../utils/isMomentRange'; import PureRenderMixin from '../utils/PureRenderMixin'; const CalendarMonth = createClass({ mixins: [BemMixin, PureRenderMixin], displayName: "CalendarMonth", propTypes: { dateComponent: PropTypes.func, disableNavigation: PropTypes.bool, enabledRange: CustomPropTypes.momentRange, firstOfMonth: CustomPropTypes.moment, firstOfWeek: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6]), hideSelection: PropTypes.bool, highlightedDate: PropTypes.object, highlightedRange: PropTypes.object, onMonthChange: PropTypes.func, onYearChange: PropTypes.func, value: CustomPropTypes.momentOrMomentRange, locale: PropTypes.string, }, setLocale(locale) { moment.locale(locale); this.WEEKDAYS = Immutable.List(moment.weekdays()).zip(Immutable.List(moment.weekdaysShort())); this.MONTHS = Immutable.List(moment.months()); }, componentWillMount() { const { locale } = this.props; this.setLocale(locale); }, componentWillReceiveProps(nextProps) { const { locale } = nextProps; if (locale !== this.props.locale) { this.setLocale(locale); } }, renderDay(date, i) { let {dateComponent: CalendarDate, value, highlightedDate, highlightedRange, hideSelection, enabledRange, ...props} = this.props; let d = moment(date).locale(this.props.locale); let isInSelectedRange; let isSelectedDate; let isSelectedRangeStart; let isSelectedRangeEnd; if (!hideSelection && value && moment.isMoment(value) && value.isSame(d, 'day')) { isSelectedDate = true; } else if (!hideSelection && value && isMomentRange(value) && value.contains(d)) { isInSelectedRange = true; isSelectedRangeStart = value.start.isSame(d, 'day'); isSelectedRangeEnd = value.end.isSame(d, 'day'); } return ( ); }, renderWeek(dates, i) { let days = dates.map(this.renderDay); return ( {days.toJS()} ); }, renderDayHeaders() { let {firstOfWeek} = this.props; let indices = Immutable.Range(firstOfWeek, 7).concat(Immutable.Range(0, firstOfWeek)); let headers = indices.map(function(index) { let weekday = this.WEEKDAYS.get(index); return ( {weekday[1]} ); }.bind(this)); return ( {headers.toJS()} ); }, handleYearChange(event) { this.props.onYearChange(parseInt(event.target.value, 10)); }, renderYearChoice(year) { let {enabledRange} = this.props; if (year < enabledRange.start.year()) { return null; } if (year > enabledRange.end.year()) { return null; } return ( ); }, renderHeaderYear() { let {firstOfMonth} = this.props; let y = firstOfMonth.year(); let years = Immutable.Range(y - 5, y).concat(Immutable.Range(y, y + 10)); let choices = years.map(this.renderYearChoice); let modifiers = {year: true}; return ( {firstOfMonth.locale(this.props.locale).format('YYYY')} {this.props.disableNavigation ? null : } ); }, handleMonthChange(event) { this.props.onMonthChange(parseInt(event.target.value, 10)); }, renderMonthChoice(month, i) { let {firstOfMonth, enabledRange} = this.props; let disabled = false; let year = firstOfMonth.year(); if (moment({years: year, months: i + 1, date: 1}).unix() < enabledRange.start.unix()) { disabled = true; } if (moment({years: year, months: i, date: 1}).unix() > enabledRange.end.unix()) { disabled = true; } return ( ); }, renderHeaderMonth() { let {firstOfMonth} = this.props; let choices = this.MONTHS.map(this.renderMonthChoice); let modifiers = {month: true}; return ( {firstOfMonth.locale(this.props.locale).format('MMMM')} {this.props.disableNavigation ? null : } ); }, renderHeader() { return (
{this.renderHeaderMonth()} {this.renderHeaderYear()}
); }, render() { let {firstOfWeek, firstOfMonth} = this.props; let cal = new calendar.Calendar(firstOfWeek); let monthDates = Immutable.fromJS(cal.monthDates(firstOfMonth.year(), firstOfMonth.month())); let weeks = monthDates.map(this.renderWeek); return (
{this.renderHeader()} {this.renderDayHeaders()} {weeks.toJS()}
); }, }); export default CalendarMonth;