From f869fd6bca94954741d2deecde563cfe088ab1b2 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Wed, 4 Apr 2018 16:49:24 +0300 Subject: [PATCH] Add phone number field to ContactDetailsForm The validation and password prompting have been changed to only depend on the email field. --- .../ContactDetailsForm/ContactDetailsForm.css | 10 ++- .../ContactDetailsForm/ContactDetailsForm.js | 68 +++++++++++++++---- src/translations/en.json | 2 + 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/containers/ContactDetailsForm/ContactDetailsForm.css b/src/containers/ContactDetailsForm/ContactDetailsForm.css index af602f27..5426aab7 100644 --- a/src/containers/ContactDetailsForm/ContactDetailsForm.css +++ b/src/containers/ContactDetailsForm/ContactDetailsForm.css @@ -23,7 +23,7 @@ .root { } -.emailSection { +.contactDetailsSection { margin-top: 16px; margin-bottom: 46px; padding-top: 6px; @@ -34,6 +34,14 @@ } } +.phone { + margin-top: 24px; + + @media (--viewportMedium) { + margin-top: 32px; + } +} + .confirmChangesSection { flex-grow: 1; display: flex; diff --git a/src/containers/ContactDetailsForm/ContactDetailsForm.js b/src/containers/ContactDetailsForm/ContactDetailsForm.js index cf19eea3..a0ce0c6e 100644 --- a/src/containers/ContactDetailsForm/ContactDetailsForm.js +++ b/src/containers/ContactDetailsForm/ContactDetailsForm.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import { compose } from 'redux'; import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; -import { reduxForm, propTypes as formPropTypes } from 'redux-form'; +import { formValueSelector, reduxForm, propTypes as formPropTypes } from 'redux-form'; import classNames from 'classnames'; import { propTypes } from '../../util/types'; import * as validators from '../../util/validators'; @@ -12,7 +13,7 @@ import { isChangeEmailWrongPassword, isTooManyEmailVerificationRequestsError, } from '../../util/errors'; -import { Form, PrimaryButton, TextInputField } from '../../components'; +import { FieldPhoneNumberInput, Form, PrimaryButton, TextInputField } from '../../components'; import css from './ContactDetailsForm.css'; @@ -53,10 +54,11 @@ class ContactDetailsFormComponent extends Component { inProgress, intl, invalid, - pristine, ready, sendVerificationEmailError, sendVerificationEmailInProgress, + email, + phoneNumber, } = this.props; const user = ensureCurrentUser(currentUser); @@ -65,13 +67,18 @@ class ContactDetailsFormComponent extends Component { return null; } + const { email: currentEmail, emailVerified, pendingEmail, profile } = user.attributes; + // email + + // has the email changed + const emailChanged = currentEmail !== email; + const emailLabel = intl.formatMessage({ id: 'ContactDetailsForm.emailLabel', }); - const { email, emailVerified, pendingEmail } = user.attributes; - const emailPlaceholder = email || ''; + const emailPlaceholder = currentEmail || ''; const emailRequiredMessage = intl.formatMessage({ id: 'ContactDetailsForm.emailRequired', @@ -116,7 +123,7 @@ class ContactDetailsFormComponent extends Component { // Email status info: unverified, verified and pending email (aka changed unverified email) let emailVerifiedInfo = null; - if (emailVerified && !pendingEmail && pristine) { + if (emailVerified && !pendingEmail && !emailChanged) { // Current email is verified and there's no pending unverified email emailVerifiedInfo = ( @@ -157,6 +164,16 @@ class ContactDetailsFormComponent extends Component { ); } + // phone + const protectedData = profile.protectedData || {}; + const currentPhoneNumber = protectedData.phoneNumber; + + // has the phone number changed + const phoneNumberChanged = currentPhoneNumber !== phoneNumber; + + const phonePlaceholder = intl.formatMessage({ id: 'ContactDetailsForm.phonePlaceholder' }); + const phoneLabel = intl.formatMessage({ id: 'ContactDetailsForm.phoneLabel' }); + // password const passwordLabel = intl.formatMessage({ id: 'ContactDetailsForm.passwordLabel', @@ -184,6 +201,8 @@ class ContactDetailsFormComponent extends Component { validators.PASSWORD_MIN_LENGTH ); + const passwordValidators = emailChanged ? [passwordRequired, passwordMinLength] : null; + const passwordFailedMessage = intl.formatMessage({ id: 'ContactDetailsForm.passwordFailed', }); @@ -192,7 +211,7 @@ class ContactDetailsFormComponent extends Component { : null; const confirmClasses = classNames(css.confirmChangesSection, { - [css.confirmChangesSectionVisible]: !pristine, + [css.confirmChangesSectionVisible]: emailChanged, }); const genericFailure = @@ -203,11 +222,12 @@ class ContactDetailsFormComponent extends Component { ) : null; const classes = classNames(rootClassName || css.root, className); - const submitDisabled = invalid || submitting || inProgress; + const submitDisabled = + invalid || submitting || inProgress || !(emailChanged || phoneNumberChanged); return (
-
+
{emailVerifiedInfo} +
@@ -236,7 +263,7 @@ class ContactDetailsFormComponent extends Component { autoComplete="current-password" label={passwordLabel} placeholder={passwordPlaceholder} - validate={[passwordRequired, passwordMinLength]} + validate={passwordValidators} customErrorText={passwordErrorText} />
@@ -264,6 +291,8 @@ ContactDetailsFormComponent.defaultProps = { inProgress: false, sendVerificationEmailError: null, sendVerificationEmailInProgress: false, + email: null, + phoneNumber: null, }; const { bool, func, string } = PropTypes; @@ -279,12 +308,23 @@ ContactDetailsFormComponent.propTypes = { ready: bool.isRequired, sendVerificationEmailError: propTypes.error, sendVerificationEmailInProgress: bool, + + // from formValueSelector + email: string, + phoneNumber: string, }; -const defaultFormName = 'ContactDetailsForm'; +const formName = 'ContactDetailsForm'; +const selector = formValueSelector(formName); +const mapStateToProps = state => ({ + email: selector(state, 'email'), + phoneNumber: selector(state, 'phoneNumber'), +}); -const ContactDetailsForm = compose(reduxForm({ form: defaultFormName }), injectIntl)( - ContactDetailsFormComponent -); +const ContactDetailsForm = compose( + connect(mapStateToProps), + reduxForm({ form: formName }), + injectIntl +)(ContactDetailsFormComponent); export default ContactDetailsForm; diff --git a/src/translations/en.json b/src/translations/en.json index 042d647b..cdb150bf 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -96,6 +96,8 @@ "ContactDetailsForm.passwordTooShort": "The password should be at least {minLength} characters", "ContactDetailsForm.pendingEmailCheckInbox": "Check your inbox to verify {pendingEmail} now.", "ContactDetailsForm.pendingEmailUnverified": "You have not verified your new address yet. {pendingEmailCheckInbox} {resendEmailMessage}", + "ContactDetailsForm.phoneLabel": "Phone number", + "ContactDetailsForm.phonePlaceholder": "Enter your phone number", "ContactDetailsForm.resendEmailVerificationText": "Resend verification email.", "ContactDetailsForm.saveChanges": "Save changes", "ContactDetailsForm.tooManyVerificationRequests": "Too many email verification requests sent.",