Files
frontend-app-authn/src/register/components/ConfigurableRegistrationForm.jsx
Blue 8efb22595c fix: add new entry for another US label (#1244)
Add new entry for for another US label which is United States
2024-05-03 10:27:32 +05:00

242 lines
7.8 KiB
JavaScript

import React, { useEffect, useMemo } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { getCountryList, getLocale, useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import { FormFieldRenderer } from '../../field-renderer';
import { FIELDS } from '../data/constants';
import messages from '../messages';
import { CountryField, HonorCode, TermsOfService } from '../RegistrationFields';
/**
* 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 {
email,
fieldDescriptions,
fieldErrors,
formFields,
setFieldErrors,
setFormFields,
autoSubmitRegistrationForm,
} = props;
/** The reason for adding the entry 'United States' is that Chrome browser aut-fill the form with the 'Unites
States' instead of 'United States of America' which does not exist in country dropdown list and gets the user
confused and unable to create an account. So we added the United States entry in the dropdown list.
*/
const countryList = useMemo(() => getCountryList(getLocale()).concat([{ code: 'US', name: 'United States' }]), []);
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,
};
/**
* If auto submitting register form, we will check tos and honor code fields if they exist for feature parity.
*/
useEffect(() => {
if (autoSubmitRegistrationForm) {
if (Object.keys(fieldDescriptions).includes(FIELDS.HONOR_CODE)) {
setFormFields(prevState => ({
...prevState,
[FIELDS.HONOR_CODE]: true,
}));
}
if (Object.keys(fieldDescriptions).includes(FIELDS.TERMS_OF_SERVICE)) {
setFormFields(prevState => ({
...prevState,
[FIELDS.TERMS_OF_SERVICE]: true,
}));
}
}
}, [autoSubmitRegistrationForm]); // eslint-disable-line react-hooks/exhaustive-deps
const handleErrorChange = (fieldName, error) => {
if (fieldName) {
setFieldErrors(prevErrors => ({
...prevErrors,
[fieldName]: error,
}));
}
};
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 ((!value || !value.trim()) && fieldDescriptions[name]?.error_message) {
error = fieldDescriptions[name].error_message;
} else if (name === 'confirm_email' && value !== email) {
error = formatMessage(messages['email.do.not.match']);
}
setFieldErrors(prevErrors => ({ ...prevErrors, [name]: error }));
};
const handleOnFocus = (event) => {
const { name } = event.target;
setFieldErrors(prevErrors => ({ ...prevErrors, [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(
<span key={fieldData.name}>
<HonorCode
fieldType={fieldData.type}
value={formFields[fieldData.name]}
onChangeHandler={handleOnChange}
errorMessage={fieldErrors[fieldData.name]}
/>
</span>,
);
}
break;
case FIELDS.TERMS_OF_SERVICE:
honorCode.push(
<span key={fieldData.name}>
<TermsOfService
value={formFields[fieldData.name]}
onChangeHandler={handleOnChange}
errorMessage={fieldErrors[fieldData.name]}
/>
</span>,
);
break;
default:
formFieldDescriptions.push(
<span key={fieldData.name}>
<FormFieldRenderer
fieldData={fieldData}
value={formFields[fieldData.name]}
onChangeHandler={handleOnChange}
handleBlur={handleOnBlur}
handleFocus={handleOnFocus}
errorMessage={fieldErrors[fieldData.name]}
isRequired
/>
</span>,
);
}
});
}
if (flags.showConfigurableEdxFields || showCountryField) {
formFieldDescriptions.push(
<span key="country">
<CountryField
countryList={countryList}
selectedCountry={formFields.country}
errorMessage={fieldErrors.country || ''}
onChangeHandler={handleOnChange}
handleErrorChange={handleErrorChange}
onBlurHandler={handleOnBlur}
onFocusHandler={handleOnFocus}
/>
</span>,
);
}
if (flags.showMarketingEmailOptInCheckbox) {
formFieldDescriptions.push(
<span key="marketing_email_opt_in">
<FormFieldRenderer
fieldData={{
type: 'checkbox',
label: formatMessage(messages['registration.opt.in.label'], { siteName: getConfig().SITE_NAME }),
name: 'marketingEmailsOptIn',
}}
value={formFields.marketingEmailsOptIn}
className="form-field--checkbox"
onChangeHandler={handleOnChange}
handleBlur={handleOnBlur}
handleFocus={handleOnFocus}
/>
</span>,
);
}
if (flags.showConfigurableEdxFields || showTermsOfServiceAndHonorCode) {
formFieldDescriptions.push(
<span key="honor_code">
<HonorCode fieldType="tos_and_honor_code" onChangeHandler={handleOnChange} value={formFields.honor_code} />
</span>,
);
}
return (
<>
{formFieldDescriptions}
<div>
{honorCode}
</div>
</>
);
};
ConfigurableRegistrationForm.propTypes = {
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,
setFormFields: PropTypes.func.isRequired,
autoSubmitRegistrationForm: PropTypes.bool,
};
ConfigurableRegistrationForm.defaultProps = {
fieldDescriptions: {},
autoSubmitRegistrationForm: false,
};
export default ConfigurableRegistrationForm;