import * as React from "react"; import { CalendarTileProperties } from "react-calendar/dist/entry.nostyle"; import RCalendar from "react-calendar/dist/Calendar"; import { css, cx } from "emotion"; import { CalendarProps, CalendarState } from "./typings/Calendar"; import { buttonsWrapper, dateStyle, dotStyle, dotWrapper, tileStyle, wrapperStyle } from "./styles/Calendar.styles"; import Button from "./Button"; import { isSameDay, endOfDay, startOfDay, addDays, subDays } from "date-fns"; class Calendar extends React.PureComponent { static defaultProps: Partial = { onChange: () => {}, tileDots: [] }; state: Readonly = { value: this.props.selected, singleSelectedDate: null }; private onChange = (value: Date | Date[]) => { // tslint:disable-next-line no-this-assignment Doing this to reduce lookups on this, not avoiding to use fat arrow functions const { props } = this; // The following is exactly the same code. // But Typescript cannot merge into one. if (props.range) { if (Array.isArray(value) && value.length === 2) { this.setState( { value: value as [Date, Date], singleSelectedDate: null, maxRangeDates: undefined }, () => props.onChange(value as [Date, Date]) ); } } else { if (!Array.isArray(value)) { this.setState( { value, singleSelectedDate: null, maxRangeDates: undefined }, () => props.onChange(value) ); } } }; private onDayClick = (day: Date) => { const { onClickDay } = this.props; if (this.props.range && this.props.maxRange) { const { maxRange } = this.props; this.setState({ maxRangeDates: { future: addDays(day, maxRange), past: subDays(day, maxRange) } }); } this.setState({ singleSelectedDate: [startOfDay(day), endOfDay(day)] }); if (onClickDay) onClickDay(day); }; private getTileContent = ({ date }: CalendarTileProperties) => { const dot = this.props.tileDots.find( datum => !!datum.timeStamp && isSameDay(date, datum.timeStamp) ); return dot ? (
{dot.colors && dot.colors.map((color, i) => ( ))}
) : null; }; private getDisabledDays = ({ date }: CalendarTileProperties) => { const { disabledDays } = this.props; return ( (disabledDays && disabledDays.length && disabledDays.some(_date => isSameDay(_date, date))) || false ); }; private onApply = () => { // tslint:disable-next-line no-this-assignment const { props } = this; const { value, singleSelectedDate } = this.state; if (props.range && props.onApply) { if (singleSelectedDate) { props.onApply(singleSelectedDate); } else if (Array.isArray(value)) { props.onApply(value); } else if (value === undefined) { props.onApply(value); } } else if (!props.range && props.onApply && !Array.isArray(value)) { props.onApply(value); } }; private onClear = () => { const { onClear } = this.props; this.setState({ value: undefined }); if (onClear) { onClear(); } }; render() { const { range, selected, hideShadow, className, onApply, onClear, maxDate, minDate, ...rest } = this.props; const { maxRangeDates } = this.state; return (
} nextLabel={ } maxDate={maxDate || (maxRangeDates && maxRangeDates.future)} minDate={minDate || (maxRangeDates && maxRangeDates.past)} /> {(onClear || onApply) && (
{onClear && ( )} {onApply && }
)}
); } } export default Calendar;