From 683c7034b7c23b53f41c560ba4a82db76e252cd0 Mon Sep 17 00:00:00 2001 From: maxceem Date: Tue, 10 Nov 2020 13:26:39 +0200 Subject: [PATCH 1/4] feat: reject/accept terms in user profile ref issue #4184 --- src/components/BtnGroup/BtnGroup.jsx | 2 +- src/components/BtnGroup/BtnGroup.scss | 3 +- src/components/BtnGroup/FormsyBtnGroup.jsx | 42 +++++++++++++++++++ .../IncompleteUserProfile.jsx | 2 +- src/config/constants.js | 4 ++ src/helpers/tcHelpers.js | 2 +- .../components/ProfileSettingsForm.jsx | 32 +++++++++++++- .../components/ProfileSettingsForm.scss | 21 +++++++++- .../containers/ProfileSettingsContainer.jsx | 10 ++++- 9 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 src/components/BtnGroup/FormsyBtnGroup.jsx diff --git a/src/components/BtnGroup/BtnGroup.jsx b/src/components/BtnGroup/BtnGroup.jsx index c48831565..d7ccf2093 100644 --- a/src/components/BtnGroup/BtnGroup.jsx +++ b/src/components/BtnGroup/BtnGroup.jsx @@ -45,7 +45,7 @@ class BtnGroup extends React.Component { BtnGroup.propTypes = { items: PropTypes.arrayOf(PropTypes.shape({ - value: PropTypes.string.isRequired, + value: PropTypes.oneOfType(PropTypes.string, PropTypes.number, PropTypes.bool).isRequired, text: PropTypes.string.isRequired })).isRequired, onChange: PropTypes.func diff --git a/src/components/BtnGroup/BtnGroup.scss b/src/components/BtnGroup/BtnGroup.scss index 1e0c75803..9e688c7c6 100644 --- a/src/components/BtnGroup/BtnGroup.scss +++ b/src/components/BtnGroup/BtnGroup.scss @@ -20,7 +20,8 @@ > .tc-btn.active, > .tc-btn.active:hover, - > .tc-btn.active:active { + > .tc-btn.active:active, + > .tc-btn.active:focus { background: $tc-gray-20; box-shadow: inset 0 1px 3px 0 rgba($tc-gray-80, 0.38); cursor: default; diff --git a/src/components/BtnGroup/FormsyBtnGroup.jsx b/src/components/BtnGroup/FormsyBtnGroup.jsx new file mode 100644 index 000000000..87f51bfba --- /dev/null +++ b/src/components/BtnGroup/FormsyBtnGroup.jsx @@ -0,0 +1,42 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { HOC as hoc } from 'formsy-react' +import BtnGroup from './BtnGroup' + +/** + * This component is a formsy wrapper for the BtnGroup component + * @param {Object} props Component props + */ +class FormsyBtnGroup extends Component { + constructor(props) { + super(props) + this.changeValue = this.changeValue.bind(this) + } + + changeValue(value) { + this.props.setValue(value) + this.props.onChange && this.props.onChange(this.props.name, value) + } + + render() { + const { items } = this.props + const hasError = !this.props.isPristine() && !this.props.isValid() + const errorMessage = this.props.getErrorMessage() || this.props.validationError + + return ( +
+ + {(hasError && errorMessage) ? (

{errorMessage}

) : null} +
+ ) + } +} + +FormsyBtnGroup.PropTypes = { + items: PropTypes.arrayOf(PropTypes.shape({ + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]).isRequired, + text: PropTypes.string.isRequired + })).isRequired +} + +export default hoc(FormsyBtnGroup) diff --git a/src/components/IncompleteUserProfile/IncompleteUserProfile.jsx b/src/components/IncompleteUserProfile/IncompleteUserProfile.jsx index bdf948102..b70f1926f 100644 --- a/src/components/IncompleteUserProfile/IncompleteUserProfile.jsx +++ b/src/components/IncompleteUserProfile/IncompleteUserProfile.jsx @@ -20,7 +20,7 @@ const IncompleteUserProfile = ({ delete fieldsConfig.avatar // config the form to only show required fields which doesn't have the value yet const missingFieldsConfig = _.reduce(fieldsConfig, (acc, isFieldRequired, fieldKey) => { - if (isFieldRequired && !_.get(profileSettings, `settings.${fieldKey}`)) { + if (isFieldRequired && _.isNil(_.get(profileSettings, `settings.${fieldKey}`))) { acc[fieldKey] = isFieldRequired } return acc diff --git a/src/config/constants.js b/src/config/constants.js index 5438a3afe..c862f92f3 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -739,6 +739,7 @@ export const TC_CDN_URL = process.env.TC_CDN_URL || `https://community-app.${DOM export const RESET_PASSWORD_URL = `https://accounts.${DOMAIN}/member/reset-password` export const VERIFY_EMAIL_URL = `http://www.${DOMAIN}/settings/account/changeEmail` +export const TOPCODER_CONNECT_TERMS_URL = `https://connect.${DOMAIN}/terms` export const PROJECT_NAME_MAX_LENGTH = 255 export const PROJECT_REF_CODE_MAX_LENGTH = 32 @@ -1048,6 +1049,7 @@ export const PROFILE_FIELDS_CONFIG = { timeZone: true, workingHourStart: true, workingHourEnd: true, + // termsAccepted: true, // optional fields avatar: false, @@ -1065,6 +1067,7 @@ export const PROFILE_FIELDS_CONFIG = { companyURL: true, businessPhone: true, businessEmail: true, + termsAccepted: true, // optional fields avatar: false, @@ -1080,6 +1083,7 @@ export const PROFILE_FIELDS_CONFIG = { timeZone: true, workingHourStart: true, workingHourEnd: true, + // termsAccepted: true, // optional fields avatar: false, diff --git a/src/helpers/tcHelpers.js b/src/helpers/tcHelpers.js index d86af5825..78bf56176 100644 --- a/src/helpers/tcHelpers.js +++ b/src/helpers/tcHelpers.js @@ -67,7 +67,7 @@ export const isUserProfileComplete = (user, profileSettings) => { _.forEach(_.keys(fieldsConfig), (fieldKey) => { const isFieldRequired = fieldsConfig[fieldKey] - if (isFieldRequired && !profileSettings[fieldKey]) { + if (isFieldRequired && _.isNil(profileSettings[fieldKey])) { isMissingUserInfo = true return false } diff --git a/src/routes/settings/routes/profile/components/ProfileSettingsForm.jsx b/src/routes/settings/routes/profile/components/ProfileSettingsForm.jsx index 76f4742c6..7085ce8c4 100644 --- a/src/routes/settings/routes/profile/components/ProfileSettingsForm.jsx +++ b/src/routes/settings/routes/profile/components/ProfileSettingsForm.jsx @@ -11,10 +11,12 @@ const TCFormFields = FormsyForm.Fields const Formsy = FormsyForm.Formsy import ProfileSettingsAvatar from './ProfileSettingsAvatar' import FormsySelect from '../../../../../components/Select/FormsySelect' +import FormsyBtnGroup from '../../../../../components/BtnGroup/FormsyBtnGroup' import ISOCountries from '../../../../../helpers/ISOCountries' import { formatPhone } from '../../../../../helpers/utils' import { hasPermission } from '../../../../../helpers/permissions' import PERMISSIONS from '../../../../../config/permissions' +import { TOPCODER_CONNECT_TERMS_URL } from '../../../../../config/constants' import './ProfileSettingsForm.scss' const countries = _.orderBy(ISOCountries, ['name'], ['asc']).map((country) => ({ @@ -382,8 +384,36 @@ class ProfileSettingsForm extends Component { )} + {!_.isUndefined(fieldsConfig.termsAccepted) && ( +
+
+ Topcoder Terms  + {fieldsConfig.termsAccepted && *} +
+
+
+ {_.isNil(this.props.values.settings.termsAccepted) ? ( + + ) : ( + {this.props.values.settings.termsAccepted ? 'Accepted' : 'Rejected'} + )} +
+
+
+ )}
- {showBackButton && (