UNPKG

@bigfishtv/cockpit

Version:

179 lines (158 loc) 4.17 kB
import PropTypes from 'prop-types' import React, { Component } from 'react' import DatePicker from 'react-datepicker' import moment from 'moment' import Icon from '../Icon' const valueDateFormat = 'YYYY-MM-DD' const dateFormat = 'DD/MM/YY' const dateFormats = [ // day/month/year 'DD/MM/YYYY', 'D/MM/YYYY', 'DD/M/YYYY', 'D/M/YYYY', 'DD/MM/YY', 'D/M/YY', 'D/MM/YY', 'DD/M/YY', // year-month-day 'YYYY-MM-DD', 'YYYY-MM-D', 'YYYY-M-DD', 'YYYY-M-D', 'YY-MM-DD', 'YY-MM-D', 'YY-M-DD', 'YY-M-D', ] export default class DateInput extends Component { static propTypes = { value: PropTypes.string, onChange: PropTypes.func, readOnly: PropTypes.bool, openOnFocus: PropTypes.bool, } static defaultProps = { onChange: value => console.warn('No onChange prop set for DateInput'), readOnly: false, openOnFocus: false, } constructor(props) { super() const state = this.getStateForValue(props.value) this.state = { dirtyDate: false, dateValid: state.dateValue !== '', initState: state.dateValue === '', currentDate: null, ...state, } } componentWillReceiveProps(nextProps) { if (nextProps.value != this.props.value && !this.state.dirty) { this.setState({ ...this.getStateForValue(nextProps.value) }) } } getStateForValue(dateString) { if (!dateString) { return { dateValue: '', } } const dateTime = moment(dateString, valueDateFormat) return { dateValue: dateTime.format(dateFormat), currentDate: dateTime, } } handleChangeDate = event => { // if parsed + formatted date is the same as the // input value, then just send an onChange event const date = moment(event.target.value, dateFormats) if (date.format(dateFormat) === event.target.value) { this.props.onChange(date.format(valueDateFormat)) return } this.setState({ dirtyDate: true, dateValue: event.target.value, }) } handleChangeDatepicker = dateTime => { this.setState( { dateValue: dateTime.format(dateFormat), dirtyDate: true, }, () => this.handleBlur() ) setTimeout(() => this.setState({ currentDate: dateTime }), 1) } handleFocus = event => { if (this.props.openOnFocus) { this.datePicker.setOpen(true) } } handleBlur = event => { const { dateValue, dirtyDate } = this.state // close datepicker on blur this.datePicker.setOpen(false) // if no values have changed then donna worry bout ittt if (!dirtyDate) return // attempt to parse date and time from input values const date = moment(dateValue, dateFormats) // update state, including if values are valid this.setState({ initState: false, dirtyDate: false, dateValid: date.isValid() }, () => { // return blank date if invalid if (!this.state.dateValid) { this.props.onChange(null) return } // this just triggers onChange prop const dateValue = date.format(valueDateFormat) this.props.onChange(dateValue) }) } handleKeyDown = event => { if (event.key === 'Enter') { this.handleBlur() } } render() { const { initState, dateValid, dateValue, currentDate } = this.state const { minDate, maxDate } = this.props return ( <div className="inputs-inline"> <div className="input-group"> <div className="input-group-icon"> {!this.props.readOnly && !this.props.disabled && ( <DatePicker ref={el => (this.datePicker = el)} showYearDropdown dateFormat="YYYY-MM-DD" selected={currentDate} onChange={this.handleChangeDatepicker} minDate={minDate ? moment(minDate, valueDateFormat) : null} maxDate={maxDate ? moment(maxDate, valueDateFormat) : null} tabIndex={-1} /> )} <Icon name="calendar" size="18" /> </div> <input type="text" placeholder={dateFormat} value={dateValue} onFocus={this.handleFocus} onChange={this.handleChangeDate} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} className={!dateValid && !initState && dateValue != '' ? 'warning' : undefined} readOnly={this.props.readOnly} autoFocus={this.props.autoFocus} /> </div> </div> ) } }