import React, { Component } from 'react'; import OutsideClickWrapper from '../OutsideClickWrapper'; import Head from './Head'; import { MONTHS_NAMES, VIEW_MONTHS, VIEW_YEARS } from './constants'; import { rangeCreator } from '../utils' import { isNumeric } from 'tslint'; import { isNumber } from 'util'; export interface IProps { year: void|number, month: void|number, lang: string, startYear?: number, onChange: (selectedYear: number, selectedMonth: number) => any, onOutsideClick: (e: any) => any, onChangeYearUpdate?: boolean, rangePicker?: boolean } export interface IState { years: Array, selectedYear: any|number, selectedMonth: void|number, currentView: string, unRangeMonths: any } class MonthCalendar extends Component { static defaultProps = { onChangeYearUpdate: true, rangePicker: false } constructor(props: IProps){ super(props); const { year, month } = this.props; const startYear = this.props.startYear || new Date().getFullYear() - 6; const selectedYear = year || new Date().getFullYear() this.state = { years: Array.from({length: 12}, (v, k) => k + startYear), selectedYear, selectedMonth: month, currentView: year ? VIEW_MONTHS : VIEW_YEARS, unRangeMonths: [] }; } onChange = (selectedYear, selectedMonth): void => { if (typeof selectedYear == 'number' && typeof selectedMonth == 'number') { this.props.onChange(selectedYear, selectedMonth); } } selectYear = (selectedYear: number): void => { const { onChangeYearUpdate } = this.props this.setState({ selectedYear, currentView: VIEW_MONTHS }); onChangeYearUpdate && this.onChange(selectedYear, this.state.selectedMonth); }; selectMonth = (selectedMonth: number): void => { this.setState({ selectedMonth }); this.onChange(this.state.selectedYear, selectedMonth); }; previous = () => { this.setState(({selectedYear}) => ({ selectedYear: selectedYear -= 1 }), () => this.selectYear(this.state.selectedYear)) } next = () => { this.setState(({selectedYear}) => ({ selectedYear: selectedYear += 1 }), () => this.selectYear(this.state.selectedYear)) } updateYears = (startYear: number): void => { const years = Array.from({length: 12}, (v, k) => k + startYear); this.setState({ years, currentView: VIEW_YEARS }); } isYears = (): boolean => { return this.state.currentView === VIEW_YEARS; } getDuration = (month: number): any => { const { selectedMonth, selectedYear } = this.state const { year } = this.props let selected = 12 let duration = 0 if (year === selectedYear) { selected = Number(selectedMonth) || 1 duration = (12 - selected) } else if ((Number(year) + 1) === selectedYear) { selected = 0 duration = Number(selectedMonth) } return { selected, duration } } getRange = (month: number): string[] =>{ const { selected, duration } = this.getDuration(month); return rangeCreator(selected, duration) .map((month) => MONTHS_NAMES['default'][month]); } isCurrentActiveRange = (month: number): boolean => { const rangeMonth = this.getRange(month); return rangeMonth.indexOf(String(month)) > -1; } shouldShowActiveRange = (month) => { if (this.isCurrentActiveRange(month)) { return 'aw'; } return ''; } renderMonths = (): JSX.Element[] => { const { selectedMonth, selectedYear } = this.state; const { year, rangePicker } = this.props return MONTHS_NAMES[this.props.lang].map((month, index) => { const selectedKlass = (selectedMonth === index && selectedYear === year)? 'selected_cell active' : ''; const rangeActive = rangePicker ? this.shouldShowActiveRange(month) : '' return (
this.selectMonth(index)} className={`col_mp span_1_of_3_mp ${selectedKlass} ${rangeActive}`} >{month}
) }); }; renderYears = (): JSX.Element[] => { const { selectedYear } = this.state; return this.state.years.map((year, i) => { const selectedKlass = selectedYear === year ? 'selected_cell' : ''; return (
this.selectYear(year)} className={`col_mp span_1_of_3_mp ${selectedKlass}`} >{year}
); }); } handleMonthRange = (month): void => { const months = [ ...MONTHS_NAMES['default'] ] this.setState({ unRangeMonths: months.splice(month), }); } componentDidMount () { this.handleMonthRange(this.props.month) } componentWillReceiveProps(nextProps) { const { year: oldYear, month: oldMonth } = this.props const { year, month } = nextProps; if (typeof year == 'number' && typeof month == 'number' && (year !== oldYear || month !== oldMonth) ) { this.setState({ selectedYear: year || new Date().getFullYear(), selectedMonth: isNumber(month) ? month : new Date().getMonth(), currentView: VIEW_MONTHS }); this.handleMonthRange(month); } } render(): JSX.Element { const { selectedYear, selectedMonth } = this.state; return ( this.setState({ currentView: VIEW_YEARS })} onPrev={this.previous} onNext={this.next} /> {this.isYears() ? this.renderYears() : this.renderMonths()} ); } }; export default MonthCalendar;