react-timeslot-calendar
Version:
A calendar based on timeslots which can be set as available, occupied and so on.
190 lines (165 loc) • 5.58 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import helpers from './../util/helpers';
import Week from './week.jsx';
export default class Month extends React.Component {
constructor(props) {
super(props);
this.state = {
currentWeekIndex: this._getStartingWeek(props.currentDate, props.weeks),
};
}
_getStartingWeek(currentDate, weeks) {
// find out staring week:
const currentDateWithoutTime = currentDate.startOf('day');
let startingWeek = 0;
weeks.some((week, index) => {
let weekContainsDate = week.some((day) => {
const momentDay = helpers.getMomentFromCalendarJSDateElement(day);
return momentDay.format() === currentDateWithoutTime.format();
});
if (weekContainsDate) {
startingWeek = index;
return weekContainsDate;
}
});
return startingWeek;
}
render() {
return (
<div className = "tsc-month">
{ this._renderActions() }
{ this._renderWeek() }
</div>
);
}
_renderActions() {
const {
weeks,
} = this.props;
const {
currentWeekIndex,
} = this.state;
const currentWeek = weeks[currentWeekIndex];
const startDate = helpers.getMomentFromCalendarJSDateElement(currentWeek[0]);
const endDate = helpers.getMomentFromCalendarJSDateElement(currentWeek[currentWeek.length - 1]);
const actionTitle = `${startDate.format('MMM Do')} - ${endDate.format('MMM Do')}`;
return (
<div className = "tsc-month__actions">
<div className = "tsc-month__action tsc-month__action-element tsc-month__action-element--left" onClick = { this._onPrevWeekClicked.bind(this) }>
‹
</div>
<div className = "tsc-month__action tsc-month__action-title">
{ actionTitle }
</div>
<div className = "tsc-month__action tsc-month__action-element tsc-month__action-element--right" onClick = { this._onNextWeekClicked.bind(this) }>
›
</div>
</div>
);
}
_renderWeek() {
const {
currentWeekIndex,
} = this.state;
const {
weeks,
initialDate,
timeslots,
timeslotProps,
selectedTimeslots,
disabledTimeslots,
renderDays,
} = this.props;
return (
<Week
weekToRender = { weeks[currentWeekIndex] }
onTimeslotClick = { this._onTimeslotClick.bind(this) }
initialDate = { initialDate }
timeslots = { timeslots }
timeslotProps = { timeslotProps }
selectedTimeslots = { selectedTimeslots }
disabledTimeslots = { disabledTimeslots }
renderDays = { renderDays }
/>
);
}
_onTimeslotClick(timeslot) {
const {
onTimeslotClick,
} = this.props;
onTimeslotClick(timeslot);
}
/**
* Handles prev week button click.
*/
_onPrevWeekClicked() {
const {
currentWeekIndex,
} = this.state;
const {
onWeekOutOfMonth,
weeks,
} = this.props;
if (currentWeekIndex - 1 >= 0) {
this.setState({
currentWeekIndex: currentWeekIndex - 1,
});
}
else if (onWeekOutOfMonth) {
const firstDayOfPrevWeek = helpers.getMomentFromCalendarJSDateElement(weeks[0][0]).clone().subtract(1, 'days');
onWeekOutOfMonth(firstDayOfPrevWeek);
}
}
/**
* Handles next week button click.
*/
_onNextWeekClicked() {
const {
currentWeekIndex,
} = this.state;
const {
weeks,
onWeekOutOfMonth,
} = this.props;
if (currentWeekIndex + 1 < weeks.length) {
this.setState({
currentWeekIndex: currentWeekIndex + 1,
});
}
else if (onWeekOutOfMonth) {
const lastDay = weeks[currentWeekIndex].length - 1;
const firstDayOfNextWeek = helpers.getMomentFromCalendarJSDateElement(weeks[currentWeekIndex][lastDay]).clone().add(1, 'days');
onWeekOutOfMonth(firstDayOfNextWeek);
}
}
componentWillReceiveProps(nextProps) {
this.setState({
currentWeekIndex: this._getStartingWeek(nextProps.currentDate, nextProps.weeks),
});
}
}
/**
* @type {Object} currentDate: Base currentDate to get the month from - Usually first day of the month
* @type {Array} weeks: A list of weeks based on calendarJS
* @type {Function} onWeekOutOfMonth: A callback to call when user goes out of the month
* @type {Function} onTimeslotClick: Function to be excecuted when clicked.
* @type {Object} initialDate: Moment JS Date used to initialize the Calendar and which progresses further into the tree.
* @type {Array} timeslots: An array of timeslots to be displayed in each day.
* @type {Object} timeslotProps: An object with keys and values for timeslot props (format, viewFormat)
* @type {Array} selectedTimeslots: Selected Timeslots Set used further into the tree to add the classes needed to when renderizing timeslots.
* @type {Array} DisabledTimeslots: Disabled Timeslots Set used further into the tree to add the classes needed to when renderizing timeslots.
* @type {Object} renderDays: An array of days which states which days of the week to render. By default renders all days.
*/
Month.propTypes = {
currentDate: PropTypes.object.isRequired,
weeks: PropTypes.array.isRequired,
onWeekOutOfMonth: PropTypes.func,
onTimeslotClick: PropTypes.func,
initialDate: PropTypes.object.isRequired,
timeslots: PropTypes.array.isRequired,
timeslotProps: PropTypes.object,
selectedTimeslots: PropTypes.array,
disabledTimeslots: PropTypes.array,
renderDays: PropTypes.object,
};