diff --git a/client/components/registration/registration.js b/client/components/registration/registration.js index 20345788c..0c2e42708 100644 --- a/client/components/registration/registration.js +++ b/client/components/registration/registration.js @@ -3,17 +3,17 @@ import "./index.css"; import axios from "axios"; import PropTypes from "prop-types"; -import React, {Suspense} from "react"; +import React, { Suspense } from "react"; import Select from "react-select"; -import {Link, Route, Routes} from "react-router-dom"; -import {toast} from "react-toastify"; +import { Link, Route, Routes } from "react-router-dom"; +import { toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; -import {t} from "ttag"; +import { t } from "ttag"; import "react-phone-input-2/lib/style.css"; import countries from "./countries.json"; import LoadingContext from "../../utils/loading-context"; import PasswordToggleIcon from "../../utils/password-toggle"; -import {mainToastId, registerApiUrl} from "../../constants"; +import { mainToastId, registerApiUrl } from "../../constants"; import getErrorText from "../../utils/get-error-text"; import logError from "../../utils/log-error"; import handleChange from "../../utils/handle-change"; @@ -69,8 +69,8 @@ export default class Registration extends React.Component { } componentDidMount() { - const {orgSlug, settings, setTitle, orgName, language} = this.props; - const {setLoading} = this.context; + const { orgSlug, settings, setTitle, orgName, language } = this.props; + const { setLoading } = this.context; setTitle(t`REGISTRATION_TITL`, orgName); @@ -82,9 +82,9 @@ export default class Registration extends React.Component { } async componentDidUpdate(prevProps) { - const {plans} = this.state; - const {settings, loading} = this.props; - const {setLoading} = this.context; + const { plans } = this.state; + const { settings, loading } = this.props; + const { setLoading } = this.context; if ( settings.subscriptions && plans.length === 0 && @@ -96,8 +96,8 @@ export default class Registration extends React.Component { } getPlansSuccessCallback(plans) { - const {setLoading} = this.context; - this.setState({plans, plansFetched: true}); + const { setLoading } = this.context; + this.setState({ plans, plansFetched: true }); setLoading(false); } @@ -106,14 +106,14 @@ export default class Registration extends React.Component { } toggleModal = () => { - const {modalActive} = this.state; - this.setState({modalActive: !modalActive}); + const { modalActive } = this.state; + this.setState({ modalActive: !modalActive }); }; handleSubmit(event) { - const {setLoading} = this.context; + const { setLoading } = this.context; event.preventDefault(); - const {orgSlug, authenticate, settings, language, setUserData, navigate} = + const { orgSlug, authenticate, settings, language, setUserData, navigate } = this.props; const { phone_number, @@ -144,12 +144,18 @@ export default class Registration extends React.Component { return false; } - this.setState({errors: {...errors, password2: null}}); + this.setState({ errors: { ...errors, password2: null } }); const url = registerApiUrl.replace("{orgSlug}", orgSlug); // prepare post data + + const generateUsername = (email) => { + return email.replace(/[@.]/g, "_"); // user@gmail.com → user_gmail_com + }; + + const postData = { email, - username: email, + username: generateUsername(email), // NEW first_name, last_name, birth_date, @@ -211,7 +217,7 @@ export default class Registration extends React.Component { }) .then((res = {}) => { if (!res && !res.data) throw new Error(); - const {key: auth_token} = res.data; + const { key: auth_token } = res.data; setUserData({ is_verified: false, auth_token, @@ -238,7 +244,7 @@ export default class Registration extends React.Component { authenticate(true); }) .catch((error) => { - const {data, status} = error.response; + const { data, status } = error.response; if (status === 404) { setLoading(false); toast.error(t`404_PG_TITL`); @@ -247,7 +253,7 @@ export default class Registration extends React.Component { if (status === 409) { setLoading(false); this.toggleModal(); - this.setState({errors: {...errors, ...data}}); + this.setState({ errors: { ...errors, ...data } }); return; } if ("billing_info" in data) { @@ -262,71 +268,71 @@ export default class Registration extends React.Component { this.setState({ errors: { ...errors, - ...(data.phone_number ? {phone_number: data.phone_number} : null), - ...(data.email ? {email: data.email.toString()} : {email: ""}), + ...(data.phone_number ? { phone_number: data.phone_number } : null), + ...(data.email ? { email: data.email.toString() } : { email: "" }), ...(data.username - ? {username: data.username.toString()} - : {username: ""}), + ? { username: data.username.toString() } + : { username: "" }), ...(data.first_name - ? {first_name: data.first_name.toString()} - : {first_name: ""}), + ? { first_name: data.first_name.toString() } + : { first_name: "" }), ...(data.last_name - ? {last_name: data.last_name.toString()} - : {last_name: ""}), + ? { last_name: data.last_name.toString() } + : { last_name: "" }), ...(data.birth_date - ? {birth_date: data.birth_date.toString()} - : {birth_date: ""}), + ? { birth_date: data.birth_date.toString() } + : { birth_date: "" }), ...(data.location - ? {location: data.location.toString()} - : {location: ""}), + ? { location: data.location.toString() } + : { location: "" }), ...(data.tax_number - ? {tax_number: data.tax_number.toString()} - : {tax_number: ""}), - ...(data.street ? {street: data.street.toString()} : {street: ""}), - ...(data.city ? {city: data.city.toString()} : {city: ""}), + ? { tax_number: data.tax_number.toString() } + : { tax_number: "" }), + ...(data.street ? { street: data.street.toString() } : { street: "" }), + ...(data.city ? { city: data.city.toString() } : { city: "" }), ...(data.zipcode - ? {zipcode: data.zipcode.toString()} - : {zipcode: ""}), + ? { zipcode: data.zipcode.toString() } + : { zipcode: "" }), ...(data.country - ? {country: data.country.toString()} - : {country: ""}), + ? { country: data.country.toString() } + : { country: "" }), ...(data.password1 - ? {password1: data.password1.toString()} - : {password1: ""}), + ? { password1: data.password1.toString() } + : { password1: "" }), ...(data.password2 - ? {password2: data.password2.toString()} - : {password2: ""}), + ? { password2: data.password2.toString() } + : { password2: "" }), }, }); }); } selectedCountry = (data) => { - this.setState({countrySelected: data, country: data.value}); + this.setState({ countrySelected: data, country: data.value }); }; changePlan = (event) => { - this.setState({selectedPlan: event.target.value}); + this.setState({ selectedPlan: event.target.value }); }; autoSelectFirstPlan = () => { - const {registration} = this.props; + const { registration } = this.props; if (registration.auto_select_first_plan) { - this.changePlan({target: {value: 0}}); + this.changePlan({ target: { value: 0 } }); } }; isPlanIdentityVerifier = () => { // If a payment is required, the plan is valid for identity verification - const {selectedPlan, plans} = this.state; + const { selectedPlan, plans } = this.state; return ( selectedPlan !== null && plans[selectedPlan].requires_payment === true ); }; doesPlanRequireInvoice = () => { - const {settings} = this.props; - const {selectedPlan, plans} = this.state; + const { settings } = this.props; + const { selectedPlan, plans } = this.state; return ( settings.subscriptions && selectedPlan !== null && @@ -335,7 +341,7 @@ export default class Registration extends React.Component { }; handleResponse = (response) => { - const {orgSlug, navigate} = this.props; + const { orgSlug, navigate } = this.props; if (response) { toast.info(t`PLEASE_LOGIN`); return navigate(`/${orgSlug}/login`); @@ -344,8 +350,8 @@ export default class Registration extends React.Component { }; getForm = () => { - const {registration, settings, orgSlug, defaultLanguage} = this.props; - const {additional_info_text, input_fields, links, auto_select_first_plan} = + const { registration, settings, orgSlug, defaultLanguage } = this.props; + const { additional_info_text, input_fields, links, auto_select_first_plan } = registration; const { success, @@ -391,19 +397,53 @@ export default class Registration extends React.Component { )} {(plans.length === 0 || (plans.length > 0 && selectedPlan !== null)) && ( - <> - {!this.isPlanIdentityVerifier() && - settings.mobile_phone_verification && - input_fields.phone_number && ( -
- - {getError(errors, "phone_number")} - + {!this.isPlanIdentityVerifier() && + settings.mobile_phone_verification && + input_fields.phone_number && ( +
+ + {getError(errors, "phone_number")} + + this.handleChange({ + target: { + name: "phone_number", + value: `+${value}`, + }, + }) + } + onKeyDown={(event) => { + submitOnEnter( + event, + this, + "registration-form", + ); + }} + placeholder={t`PHONE_PHOLD`} + /> + } + > + this.handleChange({ @@ -421,324 +461,289 @@ export default class Registration extends React.Component { ); }} placeholder={t`PHONE_PHOLD`} + enableSearch={Boolean( + input_fields.phone_number.enable_search, + )} + inputProps={{ + name: "phone_number", + id: "phone-number", + className: `form-control input ${errors.phone_number ? "error" : "" + }`, + required: true, + autoComplete: "tel", + }} /> - } - > - - this.handleChange({ - target: { - name: "phone_number", - value: `+${value}`, - }, - }) - } - onKeyDown={(event) => { - submitOnEnter( - event, - this, - "registration-form", - ); - }} - placeholder={t`PHONE_PHOLD`} - enableSearch={Boolean( - input_fields.phone_number.enable_search, - )} - inputProps={{ - name: "phone_number", - id: "phone-number", - className: `form-control input ${ - errors.phone_number ? "error" : "" - }`, - required: true, - autoComplete: "tel", - }} - /> - -
- )} +
+
+ )} -
- - {getError(errors, "email")} - -
- - {this.isPlanIdentityVerifier() && ( -
- - {getError(errors, "username")} +
+ + {getError(errors, "email")}
- )} - {(input_fields.first_name.setting !== "disabled" || - this.doesPlanRequireInvoice()) && ( -
- - {getError(errors, "first_name")} - -
- )} - - {(input_fields.last_name.setting !== "disabled" || - this.doesPlanRequireInvoice()) && ( -
- - {getError(errors, "last_name")} - -
- )} - - {input_fields.birth_date.setting !== "disabled" && ( -
- - {getError(errors, "birth_date")} - -
- )} - - {input_fields.location.setting !== "disabled" && ( -
- - {getError(errors, "location")} - -
- )} - -
- - {getError(errors, "password1")} - - - this.setState({hidePassword: !hidePassword}) - } - /> -
- -
- - {getError(errors, "password2")} - - - this.setState({hidePassword: !hidePassword}) - } - /> -
- - {this.doesPlanRequireInvoice() && ( -
-
- - {getError(errors, "country")} - -
-
- - {getError(errors, "street")} + {this.isPlanIdentityVerifier() && ( +
+ + {getError(errors, "username")}
-
- - {getError(errors, "zipcode")} + )} + + {(input_fields.first_name.setting !== "disabled" || + this.doesPlanRequireInvoice()) && ( +
+ + {getError(errors, "first_name")} + +
+ )} + + {(input_fields.last_name.setting !== "disabled" || + this.doesPlanRequireInvoice()) && ( +
+ + {getError(errors, "last_name")} + +
+ )} + + {input_fields.birth_date.setting !== "disabled" && ( +
+ + {getError(errors, "birth_date")}
-
- - {getError(errors, "tax_number")} + )} + + {input_fields.location.setting !== "disabled" && ( +
+ + {getError(errors, "location")}
+ )} + +
+ + {getError(errors, "password1")} + + + this.setState({ hidePassword: !hidePassword }) + } + />
- )} - - )} + +
+ + {getError(errors, "password2")} + + + this.setState({ hidePassword: !hidePassword }) + } + /> +
+ + {this.doesPlanRequireInvoice() && ( +
+
+ + {getError(errors, "country")} + +
+
+ + {getError(errors, "street")} + +
+
+ + {getError(errors, "zipcode")} + +
+
+ + {getError(errors, "tax_number")} + +
+
+ )} + + )}
{(plans.length === 0 || @@ -756,12 +761,12 @@ export default class Registration extends React.Component {
{(plans.length === 0 || (plans.length > 0 && selectedPlan !== null)) && ( - - )} + + )}
{links && ( @@ -802,8 +807,8 @@ export default class Registration extends React.Component { }; render() { - const {settings} = this.props; - const {plansFetched, modalActive, errors} = this.state; + const { settings } = this.props; + const { plansFetched, modalActive, errors } = this.state; if (settings.subscriptions && !plansFetched) { return null;