@bigfishtv/cockpit
Version:
179 lines (158 loc) • 4.17 kB
JavaScript
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>
)
}
}