MetaPhase-Consulting/State-TalentMAP

View on GitHub
src/Components/BidCycleList/BidCycleCard/BidCycleCard.jsx

Summary

Maintainability
A
1 hr
Test Coverage
F
52%
/* eslint-disable no-underscore-dangle */
import { Component } from 'react';
import { get, identity, pickBy } from 'lodash';
import DatePicker from 'react-datepicker';
import LoadingText from 'Components/LoadingText';
import { Card, Column, Row } from '../../Layout';
import DefinitionList, { Definition } from '../../DefinitionList';
import { BID_CYCLE } from '../../../Constants/PropTypes';
import { formatDate } from '../../../utilities';
import api from '../../../api';

const NO_DATE = 'None listed';
const NO_NAME = 'None listed (This may not be an active bid cycle)';

const getCycleInfo = (item, key) => {
  const defaults = {
    id: '',
    name: NO_NAME,
    handshake_allowed_date: '',
  };

  let item$ = get(item, key, defaults[key]);

  if ((/date/).test(key)) {
    item$ = item$ ? formatDate(item$, 'M.D.YYYY hh:mm') : NO_DATE;
  }

  return item$;
};

class BidCycleCard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      editActive: false,
      isLoading: false,
      hasErrored: false,
      data: null,
      date: props.cycle.handshake_allowed_date || new Date(),
      date$: null,
      hasUpdated: false,
    };
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.cycle.handshake_allowed_date !== this.props.cycle.handshake_allowed_date) {
      this.setState({ date: nextProps.cycle.handshake_allowed_date });
    }
  }

  render() {
    const { cycle } = this.props;
    const { data, date, date$, editActive, isLoading, hasErrored, hasUpdated } = this.state;

    const cycle$$ = {
      ...pickBy(cycle, identity),
      ...pickBy(data, identity),
    };

    if (hasUpdated) {
      cycle$$.handshake_allowed_date = date$;
    }

    const { _id: id$ } = cycle$$;

    const cycle$ = {
      id: getCycleInfo(cycle$$, 'id'),
      name: getCycleInfo(cycle$$, 'name'),
      deadline: getCycleInfo(cycle$$, 'handshake_allowed_date'),
    };

    const patch = (isClear = false) => {
      this.setState({ isLoading: true, hasErrored: false });
      const method = cycle$$._id || data?.id ? 'patch' : 'post';
      const body = { handshake_allowed_date: date };
      if (method === 'post') {
        body.cycle_id = cycle.id;
      }
      if (isClear) {
        body.handshake_allowed_date = null;
      }
      const url = `/bidhandshakecycle/${method === 'post' ? '' : `${cycle$$._id}/`}`;
      api()[method](url, body)
        .then((response) => {
          const { data: data$ } = response;
          this.setState({
            data: {
              ...data$,
              _id: data$.id,
              id: data$.cycle_id,
              handshake_allowed_date: data$.handshake_allowed_date,
            },
            isLoading: false,
            hasErrored: false,
            editActive: false,
            date$: data$.handshake_allowed_date,
            hasUpdated: true,
          });
        })
        .catch(() => {
          this.setState({ isLoading: false, hasErrored: true });
        });
    };

    const time = new Date(date);

    return (
      <Card>
        <Row fluid>
          <Column columns={12}>
            {
              editActive ?
                <>
                  <div style={{ display: 'block' }}>
                    <DatePicker
                      selected={time}
                      onChange={d => { this.setState({ date: d }); }}
                      showTimeSelect
                      timeFormat="HH:mm"
                      timeIntervals={15}
                      timeCaption="time"
                      dateFormat="MMMM d, yyyy h:mm aa"
                    />
                  </div>
                  <button className="usa-button-secondary" onClick={() => patch(false)}>Submit</button>
                  <button className="usa-button-secondary" onClick={() => patch(true)}>Remove Date</button>
                </>
                :
                <DefinitionList>
                  <Definition term="In Database" definition={id$ ? 'Yes' : 'No'} />
                  <Definition term="ID" definition={cycle$.id} />
                  <Definition term="Name" definition={cycle$.name} />
                  <Definition term="Handshake Reveal Date" definition={cycle$.deadline} />
                </DefinitionList>
            }
            <button onClick={() => this.setState({ editActive: !editActive })}>{ editActive ? 'Close' : 'Edit Reveal Date' }</button>
            { editActive && isLoading && <LoadingText /> }
            { editActive && !isLoading && hasErrored && 'Error. Try again'}
          </Column>
        </Row>
      </Card>
    );
  }
}

BidCycleCard.propTypes = {
  cycle: BID_CYCLE,
};

BidCycleCard.defaultProps = {
  cycle: {
    name: '',
    cycle_deadline_date: null,
    cycle_end_date: null,
    cycle_start_date: null,
    active: true,
  },
};

export default BidCycleCard;
/* eslint-enable no-underscore-dangle */