import React, { useEffect } from 'react'; import { getConfig } from '@edx/frontend-platform'; import { useIntl } from '@edx/frontend-platform/i18n'; import PropTypes from 'prop-types'; import { FIELDS } from './data/constants'; import { validateCountryField } from './data/utils'; import messages from './messages'; import { HonorCode, TermsOfService } from './registrationFields'; import CountryField from './registrationFields/CountryField'; import { FormFieldRenderer } from '../field-renderer'; /** * Fields on registration page that are not the default required fields (name, email, username, password). * These configurable required fields are defined on the backend using REGISTRATION_EXTRA_FIELDS setting. * * Country and Honor Code/Terms of Services (if enabled) will appear at the bottom of the form, even if they * appear higher in order returned by backend. This is to make the user experience better. * * For edX only: * Country and honor code fields are required by default, and we will continue to show them on * frontend even if the API doesn't return it. The `SHOW_CONFIGURABLE_EDX_FIELDS` flag will enable * it for edX. * */ const ConfigurableRegistrationForm = (props) => { const { formatMessage } = useIntl(); const { countryList, email, fieldDescriptions, fieldErrors, formFields, setFieldErrors, setFocusedField, setFormFields, } = props; let showTermsOfServiceAndHonorCode = false; let showCountryField = false; const formFieldDescriptions = []; const honorCode = []; const flags = { showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS, showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS, showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN, }; useEffect(() => { if (!formFields.country) { setFormFields(prevState => ({ ...prevState, country: { countryCode: '', displayValue: '' } })); } }); const handleOnChange = (event, countryValue = null) => { const { name } = event.target; let value; if (countryValue) { value = { ...countryValue }; } else { value = event.target.type === 'checkbox' ? event.target.checked : event.target.value; if (event.target.type === 'checkbox') { setFieldErrors(prevErrors => ({ ...prevErrors, [name]: '' })); } } setFormFields(prevState => ({ ...prevState, [name]: value })); }; const handleOnBlur = (event) => { const { name, value } = event.target; let error = ''; if (name === 'country') { const countryValidation = validateCountryField( value.trim(), countryList, formatMessage(messages['empty.country.field.error']), ); const { countryCode, displayValue } = countryValidation; error = countryValidation.error; setFormFields(prevState => ({ ...prevState, country: { countryCode, displayValue } })); } else if (!value || !value.trim()) { error = fieldDescriptions[name].error_message; } else if (name === 'confirm_email' && value !== email) { error = formatMessage(messages['email.do.not.match']); } setFocusedField(null); setFieldErrors(prevErrors => ({ ...prevErrors, [name]: error })); }; const handleOnFocus = (event) => { const { name } = event.target; setFieldErrors(prevErrors => ({ ...prevErrors, [name]: '' })); // Since we are removing the form errors from the focused field, we will // need to rerun the validation for focused field on form submission. setFocusedField(name); }; if (flags.showConfigurableRegistrationFields) { Object.keys(fieldDescriptions).forEach(fieldName => { const fieldData = fieldDescriptions[fieldName]; switch (fieldData.name) { case FIELDS.COUNTRY: showCountryField = true; break; case FIELDS.HONOR_CODE: if (fieldData.type === 'tos_and_honor_code') { showTermsOfServiceAndHonorCode = true; } else { honorCode.push( , ); } break; case FIELDS.TERMS_OF_SERVICE: honorCode.push( , ); break; default: formFieldDescriptions.push( , ); } }); } if (flags.showConfigurableEdxFields || showCountryField) { formFieldDescriptions.push( , ); } if (flags.showMarketingEmailOptInCheckbox) { formFieldDescriptions.push( , ); } if (flags.showConfigurableEdxFields || showTermsOfServiceAndHonorCode) { formFieldDescriptions.push( , ); } return ( <> {formFieldDescriptions}
{honorCode}
); }; ConfigurableRegistrationForm.propTypes = { countryList: PropTypes.arrayOf(PropTypes.shape({})).isRequired, email: PropTypes.string.isRequired, fieldDescriptions: PropTypes.shape({}), fieldErrors: PropTypes.shape({ country: PropTypes.string, }).isRequired, formFields: PropTypes.shape({ country: PropTypes.shape({ displayValue: PropTypes.string, countryCode: PropTypes.string, }), honor_code: PropTypes.bool, marketingEmailsOptIn: PropTypes.bool, }).isRequired, setFieldErrors: PropTypes.func.isRequired, setFocusedField: PropTypes.func.isRequired, setFormFields: PropTypes.func.isRequired, }; ConfigurableRegistrationForm.defaultProps = { fieldDescriptions: {}, }; export default ConfigurableRegistrationForm;