# All files / components/DateRangePicker DateRangePicker.js

6.45% Statements 2/31
0% Branches 0/24
0% Functions 0/8
7.14% Lines 2/28

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123

    6x

    6x

     import React from 'react';
    import DatePicker from '../DatePicker';
    import PropTypes from 'prop-types';
    import _ from 'lodash';
    import styled from 'styled-components';

    const HorizontalAlign = styled.div`
      display: flex;
      width: 100%;
    `;

    const Separator = styled.div`
      width: 100px;
      line-height: 50px;
      text-align: center;
      font-weight: 600;
    `;

    export default class DateRangePicker extends React.Component {
      static propTypes = {
        startDate: PropTypes.instanceOf(Date).isRequired,
        endDate: PropTypes.instanceOf(Date).isRequired,
        onChange: PropTypes.func.isRequired,
        onError: PropTypes.func,
      }

      static defaultProps = {
        onError: _.noop,
      }

      state = {
        startDate: this.props.startDate,
        endDate: this.props.endDate,
      }

      componentWillReceiveProps(newProps) {
        if (newProps.startDate !== this.props.startDate || newProps.endDate !== this.props.endDate) {
          this.setState(Object.assign({}, this.state, {
            startDate: newProps.startDate,
            endDate: newProps.endDate,
          }));
        }
      }

      getTotalWidth = element => {
        this.setState(Object.assign({}, this.state, {
          totalWidth: `${element.offsetWidth}px`,
        }));
      }

      setEndDatePicker = element => {
        this.setState(Object.assign({}, this.state, {
          endDatePicker: element,
        }));
      }

      updateStartDate = (startDate, calendarClicked) => {
        this.setState(Object.assign({}, this.state, { startDate }));
        const updatedWithoutError = this.validateAndUpdateDateRange(startDate, this.state.endDate);
        if (updatedWithoutError && calendarClicked) this.state.endDatePicker.focus();
      }

      updateEndDate = endDate => {
        this.setState(Object.assign({}, this.state, { endDate }));
        this.validateAndUpdateDateRange(this.state.startDate, endDate);
      }

      validateAndUpdateDateRange = (startDate, endDate) => {
        const { onChange, onError } = this.props;
        try {
          this.validateDateRange(startDate, endDate);
          if (_.isFunction(onChange)) {
            onChange({
              startDate,
              endDate,
            });
            if (_.isFunction(onError)) onError(undefined);
          }
        } catch (err) {
          if (_.isFunction(onError)) onError(err);
          return false;
        }
        return true;
      }

      validateDateRange = (startDate, endDate) => {
        if (!(startDate instanceof Date) || isNaN(startDate)) {
          throw new Error('Invalid start date for range');
        } else if (!(endDate instanceof Date) || isNaN(endDate)) {
          throw new Error('Invalid end date for range');
        } else if (startDate.getTime() > endDate.getTime()) {
          throw new Error('Start date is after end date');
        }
      }

      render() {
        const { startDate, endDate, totalWidth } = this.state;
        return (
          <HorizontalAlign innerRef={this.getTotalWidth}>
            <DatePicker
              onChange={this.updateStartDate}
              value={startDate}
              startDate={startDate}
              endDate={endDate}
              onError={this.props.onError}
              calendarWidth={totalWidth}
            />
            <Separator>—</Separator>
            <DatePicker
              onChange={this.updateEndDate}
              value={endDate}
              startDate={startDate}
              endDate={endDate}
              onError={this.props.onError}
              calendarWidth={totalWidth}
              isEndDate
              inputRef={this.setEndDatePicker}
            />
          </HorizontalAlign>
        );
      }
    }