"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

require("core-js/modules/web.dom.iterable");

var _formik = require("formik");

var _react = _interopRequireWildcard(require("react"));

var _reactBootstrap = require("react-bootstrap");

var _reactPhoneNumberInput = require("react-phone-number-input");

var _input = _interopRequireDefault(require("react-phone-number-input/input"));

var _styledComponents = _interopRequireWildcard(require("styled-components"));

var yup = _interopRequireWildcard(require("yup"));

var _ui = require("../../util/ui");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

const allowedNotificationChannels = [{
  text: 'Email',
  type: 'email'
}, {
  text: 'SMS',
  type: 'sms'
}, {
  text: 'Don\'t notify me',
  type: 'none'
}]; // Styles
// HACK: Preserve container height.

const Details = _styledComponents.default.div`
  min-height: 60px;
  margin-bottom: 15px;
`;
const ControlStrip = _styledComponents.default.div`
  > * {
    margin-right: 4px;
  }
`;
const phoneFieldCss = (0, _styledComponents.css)`
  display: inline-block;
  vertical-align: middle;
  width: 14em;
`;
const InlineTextInput = (0, _styledComponents.default)(_reactBootstrap.FormControl)`
  ${phoneFieldCss}
`;
const InlineStatic = (0, _styledComponents.default)(_reactBootstrap.FormControl.Static)`
  ${phoneFieldCss}
`;
const InlinePhoneInput = (0, _styledComponents.default)(_input.default)`
  ${phoneFieldCss}
`;
const FlushLink = (0, _styledComponents.default)(_reactBootstrap.Button)`
  padding-left: 0;
  padding-right: 0;
`;
const INVALID_PHONE_MSG = 'Please enter a valid phone number.';
const VALIDATION_CODE_MSG = 'Please enter 6 digits for the validation code.';
const codeValidationSchema = yup.object({
  validationCode: yup.string().required(VALIDATION_CODE_MSG).matches(/^\d{6}$/, VALIDATION_CODE_MSG) // 6-digit string

});
/**
 * User notification preferences pane.
 */

const NotificationPrefsPane = ({
  handleBlur,
  // Formik prop
  handleChange,
  // Formik prop
  loggedInUser,
  onRequestPhoneVerificationCode,
  onSendPhoneVerificationCode,
  phoneFormatOptions,
  values: userData // Formik prop

}) => {
  const {
    email,
    isPhoneNumberVerified,
    phoneNumber
  } = loggedInUser;
  const {
    notificationChannel
  } = userData;
  const initialFormikValues = {
    validationCode: ''
  };
  return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, "You can receive notifications about trips you frequently take."), /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ControlLabel, null, "How would you like to receive notifications?"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonToolbar, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ToggleButtonGroup, {
    defaultValue: notificationChannel,
    name: "notificationChannel",
    type: "radio"
  }, allowedNotificationChannels.map(({
    text,
    type
  }, index) =>
  /*#__PURE__*/
  // TODO: If removing the Save/Cancel buttons on the account screen,
  // persist changes immediately when onChange is triggered.
  _react.default.createElement(_reactBootstrap.ToggleButton, {
    bsStyle: notificationChannel === type ? 'primary' : 'default',
    key: index // onBlur and onChange have to be set on individual controls instead of the control group
    // in order for Formik to correctly process the changes.
    ,
    onBlur: handleBlur,
    onChange: handleChange,
    value: type
  }, text))))), /*#__PURE__*/_react.default.createElement(Details, null, notificationChannel === 'email' && /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ControlLabel, null, "Notification emails will be sent to:"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormControl.Static, null, email)), notificationChannel === 'sms' && /*#__PURE__*/_react.default.createElement(_formik.Formik, {
    initialValues: initialFormikValues,
    validateOnChange: true,
    validationSchema: codeValidationSchema
  }, // Pass Formik props to the component rendered so Formik can manage its validation.
  // (The validation for this component is independent of the validation set in UserAccountScreen.)
  innerProps => {
    return /*#__PURE__*/_react.default.createElement(PhoneNumberEditor, _extends({}, innerProps, {
      initialPhoneNumber: phoneNumber,
      initialPhoneNumberVerified: isPhoneNumberVerified,
      onRequestCode: onRequestPhoneVerificationCode,
      onSubmitCode: onSendPhoneVerificationCode,
      phoneFormatOptions: phoneFormatOptions
    }));
  })));
};

var _default = NotificationPrefsPane;
/**
 * Sub-component that handles phone number and validation code editing and validation intricacies.
 */

exports.default = _default;

class PhoneNumberEditor extends _react.Component {
  constructor(props) {
    super(props);

    _defineProperty(this, "_handleEditNumber", () => {
      this.setState({
        isEditing: true,
        newPhoneNumber: ''
      });
    });

    _defineProperty(this, "_handleNewPhoneNumberChange", newPhoneNumber => {
      this.setState({
        newPhoneNumber
      });
    });

    _defineProperty(this, "_handleCancelEditNumber", () => {
      this.setState({
        isEditing: false
      });
    });

    _defineProperty(this, "_handlePhoneNumberKeyDown", e => {
      if (e.keyCode === 13) {
        // On the user pressing enter (keyCode 13) on the phone number field,
        // prevent form submission and request the code.
        e.preventDefault();

        this._handleRequestCode();
      }
    });

    _defineProperty(this, "_handleValidationCodeKeyDown", e => {
      if (e.keyCode === 13) {
        // On the user pressing enter (keyCode 13) on the validation code field,
        // prevent form submission and send the validation code.
        e.preventDefault();

        this._handleSubmitCode();
      }
    });

    _defineProperty(this, "_handleRequestCode", () => {
      const {
        initialPhoneNumber,
        initialPhoneNumberVerified,
        onRequestCode
      } = this.props;
      const {
        newPhoneNumber
      } = this.state;

      this._handleCancelEditNumber(); // Send the SMS request if one of these conditions apply:
      // - the user entered a valid phone number different than their current verified number,
      // - the user clicks 'Request new code' for an already pending number
      //   (they could have refreshed the page in between).


      let submittedNumber;

      if (newPhoneNumber && (0, _reactPhoneNumberInput.isPossiblePhoneNumber)(newPhoneNumber) && !(newPhoneNumber === initialPhoneNumber && initialPhoneNumberVerified)) {
        submittedNumber = newPhoneNumber;
      } else if (this._isPhoneNumberPending()) {
        submittedNumber = initialPhoneNumber;
      }

      if (submittedNumber) {
        onRequestCode(submittedNumber);
      }
    });

    _defineProperty(this, "_handleSubmitCode", () => {
      const {
        errors,
        onSubmitCode,
        values
      } = this.props;
      const {
        validationCode
      } = values;

      if (!errors.validationCode) {
        onSubmitCode(validationCode);
      }
    });

    _defineProperty(this, "_isPhoneNumberPending", () => {
      const {
        initialPhoneNumber,
        initialPhoneNumberVerified
      } = this.props;
      return !(0, _ui.isBlank)(initialPhoneNumber) && !initialPhoneNumberVerified;
    });

    const {
      initialPhoneNumber: _initialPhoneNumber
    } = props;
    this.state = {
      // If true, phone number is being edited.
      // For new users, render component in editing state.
      isEditing: (0, _ui.isBlank)(_initialPhoneNumber),
      // Holds the new phone number (+15555550123 format) entered by the user
      // (outside of Formik because (Phone)Input does not have a standard onChange event or simple valitity test).
      newPhoneNumber: ''
    };
  }

  componentDidUpdate(prevProps) {
    // If new phone number and verified status are received,
    // then reset/clear the inputs.
    if (this.props.phoneNumber !== prevProps.phoneNumber || this.props.isPhoneNumberVerified !== prevProps.isPhoneNumberVerified) {
      this._handleCancelEditNumber();

      this.props.resetForm();
    }
  }

  render() {
    const {
      errors,
      // Formik prop
      initialPhoneNumber,
      phoneFormatOptions,
      touched // Formik prop

    } = this.props;
    const {
      isEditing,
      newPhoneNumber
    } = this.state;

    const isPending = this._isPhoneNumberPending(); // Here are the states we are dealing with:
    // - First time entering a phone number/validation code (blank value, not modified)
    //   => no color, no feedback indication.
    // - Typing backspace all the way to erase a number/code (blank value, modified)
    //   => red error.
    // - Typing a phone number that doesn't match the configured phoneNumberRegEx
    //   => red error.


    const isPhoneInvalid = !(0, _reactPhoneNumberInput.isPossiblePhoneNumber)(newPhoneNumber);
    const showPhoneError = isPhoneInvalid && !(0, _ui.isBlank)(newPhoneNumber);
    const phoneErrorState = showPhoneError ? 'error' : null;
    const codeErrorState = (0, _ui.getErrorStates)(this.props).validationCode;
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isEditing ?
    /*#__PURE__*/
    // FIXME: If removing the Save/Cancel buttons on the account screen,
    // make this <FormGroup> a <form> and remove onKeyDown handler.
    _react.default.createElement(_reactBootstrap.FormGroup, {
      validationState: phoneErrorState
    }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ControlLabel, null, "Enter your phone number for SMS notifications:"), /*#__PURE__*/_react.default.createElement(ControlStrip, null, /*#__PURE__*/_react.default.createElement(InlinePhoneInput, {
      className: "form-control",
      country: phoneFormatOptions.countryCode,
      onChange: this._handleNewPhoneNumberChange,
      onKeyDown: this._handlePhoneNumberKeyDown,
      placeholder: "Enter phone number",
      type: "tel",
      value: newPhoneNumber
    }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
      bsStyle: "primary",
      disabled: isPhoneInvalid,
      onClick: this._handleRequestCode
    }, "Send verification text"), // Show cancel button only if a phone number is already recorded.
    initialPhoneNumber && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
      onClick: this._handleCancelEditNumber
    }, "Cancel"), showPhoneError && /*#__PURE__*/_react.default.createElement(_reactBootstrap.HelpBlock, null, INVALID_PHONE_MSG))) : /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ControlLabel, null, "SMS notifications will be sent to:"), /*#__PURE__*/_react.default.createElement(ControlStrip, null, /*#__PURE__*/_react.default.createElement(InlineStatic, null, (0, _reactPhoneNumberInput.formatPhoneNumber)(initialPhoneNumber), ' ', isPending // eslint-disable-next-line jsx-a11y/label-has-for
    ?
    /*#__PURE__*/
    _react.default.createElement(_reactBootstrap.Label, {
      bsStyle: "warning"
    }, "Pending") // eslint-disable-next-line jsx-a11y/label-has-for
    :
    /*#__PURE__*/
    _react.default.createElement(_reactBootstrap.Label, {
      bsStyle: "success"
    }, "Verified")), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
      onClick: this._handleEditNumber
    }, "Change number"))), isPending && !isEditing &&
    /*#__PURE__*/
    // FIXME: If removing the Save/Cancel buttons on the account screen,
    // make this <FormGroup> a <form> and remove onKeyDown handler.
    _react.default.createElement(_reactBootstrap.FormGroup, {
      validationState: codeErrorState
    }, /*#__PURE__*/_react.default.createElement("p", null, "Please check the SMS messaging app on your mobile phone for a text message with a verification code, and enter the code below (code expires after 10 minutes)."), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ControlLabel, null, "Verification code:"), /*#__PURE__*/_react.default.createElement(ControlStrip, null, /*#__PURE__*/_react.default.createElement(_formik.Field, {
      as: InlineTextInput,
      maxLength: 6,
      name: "validationCode",
      onKeyDown: this._handleValidationCodeKeyDown,
      placeholder: "123456" // HACK: <input type='tel'> triggers the numerical keypad on mobile devices, and otherwise
      // behaves like <input type='text'> with support of leading zeros and the maxLength prop.
      // <input type='number'> causes values to be stored as Number, resulting in
      // leading zeros to be invalid and stripped upon submission.
      ,
      type: "tel" // onBlur, onChange, and value are passed automatically by Formik

    }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
      bsStyle: "primary",
      disabled: !!errors.validationCode,
      onClick: this._handleSubmitCode
    }, "Verify"), touched.validationCode && errors.validationCode && /*#__PURE__*/_react.default.createElement(_reactBootstrap.HelpBlock, null, errors.validationCode)), /*#__PURE__*/_react.default.createElement(FlushLink, {
      bsStyle: "link",
      onClick: this._handleRequestCode
    }, "Request a new code")));
  }

}

module.exports = exports.default;

//# sourceMappingURL=notification-prefs-pane.js