diff --git a/src/features/Register/components/RegistrationStep/hooks/index.tsx b/src/features/Register/components/RegistrationStep/hooks/index.tsx new file mode 100644 index 00000000..10bebcc4 --- /dev/null +++ b/src/features/Register/components/RegistrationStep/hooks/index.tsx @@ -0,0 +1,39 @@ +import type { FocusEvent } from 'react' +import { useCallback } from 'react' + +import trim from 'lodash/trim' + +import { isValidEmail } from 'helpers/isValidEmail' + +import { formIds } from 'config/form' + +import { useForm } from 'features/FormStore' + +import { useSubmitHandler } from './useSubmitHandler' + +export const useRegistrationForm = () => { + const { + readFormError, + readFormValue, + updateFormError, + updateFormValue, + } = useForm() + + const handleSubmit = useSubmitHandler() + + const onEmailBlur = useCallback(({ target }: FocusEvent) => { + const email = trim(target.value) + if (email && !isValidEmail(email)) { + updateFormError(formIds.email, 'error_invalid_email_format') + } + }, [updateFormError]) + + return { + handleSubmit, + onEmailBlur, + readFormError, + readFormValue, + updateFormError, + updateFormValue, + } +} diff --git a/src/features/Register/components/RegistrationStep/hooks/useSubmitHandler.tsx b/src/features/Register/components/RegistrationStep/hooks/useSubmitHandler.tsx index 74d5aedb..f57d7042 100644 --- a/src/features/Register/components/RegistrationStep/hooks/useSubmitHandler.tsx +++ b/src/features/Register/components/RegistrationStep/hooks/useSubmitHandler.tsx @@ -2,25 +2,14 @@ import type { FormEvent } from 'react' import trim from 'lodash/trim' -import type { City } from 'requests' - import { formIds } from 'config/form' import { useAuthStore } from 'features/AuthStore' import { useForm } from 'features/FormStore' -import type { SelectedCountry } from 'hooks/useCountries' -import { useValidateForm } from 'hooks/useValidateForm' - -type Args = { - selectedCity: City | null, - selectedCountry: SelectedCountry, -} +import { useValidateForm } from './useValidateForm' -export const useSubmitHandler = ({ - selectedCity, - selectedCountry, -}: Args) => { +export const useSubmitHandler = () => { const { register } = useAuthStore() const { readFormValue } = useForm() const validateForm = useValidateForm() @@ -30,31 +19,17 @@ export const useSubmitHandler = ({ const handleSubmit = async (event: FormEvent) => { event.preventDefault() - if (validateForm() && selectedCountry) { + if (validateForm()) { const firstname = readTrimmedValue(formIds.firstname) const lastname = readTrimmedValue(formIds.lastname) - const phone = readTrimmedValue(formIds.phone) const email = readTrimmedValue(formIds.email) const password = readTrimmedValue(formIds.password) - const postalCode = Number(readTrimmedValue(formIds.postalCode)) - const region = readTrimmedValue(formIds.region) - const address1 = readTrimmedValue(formIds.address1) - const address2 = readTrimmedValue(formIds.address2) - const city = readTrimmedValue(formIds.city) register({ - address1, - address2, - city, - cityId: selectedCity?.id, - countryId: selectedCountry.id, email, firstname, lastname, password, - phone, - postalCode, - region, }) } } diff --git a/src/features/Register/components/RegistrationStep/hooks/useValidateForm.tsx b/src/features/Register/components/RegistrationStep/hooks/useValidateForm.tsx new file mode 100644 index 00000000..e0e577fb --- /dev/null +++ b/src/features/Register/components/RegistrationStep/hooks/useValidateForm.tsx @@ -0,0 +1,50 @@ +import trim from 'lodash/trim' + +import { formIds } from 'config/form' + +import { isValidEmail } from 'helpers/isValidEmail' +import { isValidPassword } from 'helpers/isValidPassword' + +import { useForm } from 'features/FormStore' + +export const useValidateForm = () => { + const { + readFormValue, + updateFormError, + } = useForm() + + const readTrimmedValue = (fieldName: string) => trim(readFormValue(fieldName)) + + const validateForm = () => { + let hasError = false + const firstname = readTrimmedValue(formIds.firstname) + const lastname = readTrimmedValue(formIds.lastname) + const email = readTrimmedValue(formIds.email) + const password = readTrimmedValue(formIds.password) + if (!firstname) { + updateFormError(formIds.firstname, 'error_fill_out_this_field') + hasError = true + } + if (!lastname) { + updateFormError(formIds.lastname, 'error_fill_out_this_field') + hasError = true + } + if (!email) { + updateFormError(formIds.email, 'error_empty_email') + hasError = true + } else if (!isValidEmail(email)) { + updateFormError(formIds.email, 'error_invalid_email_format') + hasError = true + } + if (!password) { + updateFormError(formIds.password, 'error_empty_password') + hasError = true + } else if (!isValidPassword(password)) { + updateFormError(formIds.password, 'error_simple_password') + hasError = true + } + return !hasError + } + + return validateForm +} diff --git a/src/features/Register/components/RegistrationStep/index.tsx b/src/features/Register/components/RegistrationStep/index.tsx index 4f63a166..8a3544ef 100644 --- a/src/features/Register/components/RegistrationStep/index.tsx +++ b/src/features/Register/components/RegistrationStep/index.tsx @@ -3,7 +3,6 @@ import React from 'react' import { formIds } from 'config/form' import { T9n } from 'features/T9n' -import { Combobox } from 'features/Combobox' import { Input, ButtonSolid } from 'features/Common' import { Error } from 'features/Common/Input/styled' import { @@ -13,20 +12,14 @@ import { } from 'features/Login/styled' import { FormStore } from 'features/FormStore' -import { useRegistrationForm } from 'hooks/useForm' +import { useRegistrationForm } from './hooks' const labelWidth = 116 const Registration = () => { const { - cities, - countries, handleSubmit, - onCitySelect, - onCountrySelect, onEmailBlur, - onPhoneBlur, - onRegionOrCityChange, readFormError, readFormValue, updateFormValue, @@ -68,62 +61,6 @@ const Registration = () => { labelWidth={labelWidth} onChange={updateFormValue(formIds.password)} /> - - - - - - - diff --git a/src/features/UserAccount/CardNumber/index.tsx b/src/features/UserAccount/components/CardNumber/index.tsx similarity index 100% rename from src/features/UserAccount/CardNumber/index.tsx rename to src/features/UserAccount/components/CardNumber/index.tsx diff --git a/src/features/UserAccount/CardNumber/styled.tsx b/src/features/UserAccount/components/CardNumber/styled.tsx similarity index 100% rename from src/features/UserAccount/CardNumber/styled.tsx rename to src/features/UserAccount/components/CardNumber/styled.tsx diff --git a/src/features/UserAccount/PageTitle/index.tsx b/src/features/UserAccount/components/PageTitle/index.tsx similarity index 100% rename from src/features/UserAccount/PageTitle/index.tsx rename to src/features/UserAccount/components/PageTitle/index.tsx diff --git a/src/features/UserAccount/PageTitle/styled.tsx b/src/features/UserAccount/components/PageTitle/styled.tsx similarity index 100% rename from src/features/UserAccount/PageTitle/styled.tsx rename to src/features/UserAccount/components/PageTitle/styled.tsx diff --git a/src/features/UserAccount/PlusIcon/index.tsx b/src/features/UserAccount/components/PlusIcon/index.tsx similarity index 100% rename from src/features/UserAccount/PlusIcon/index.tsx rename to src/features/UserAccount/components/PlusIcon/index.tsx diff --git a/src/features/UserAccount/PlusIcon/styled.tsx b/src/features/UserAccount/components/PlusIcon/styled.tsx similarity index 100% rename from src/features/UserAccount/PlusIcon/styled.tsx rename to src/features/UserAccount/components/PlusIcon/styled.tsx diff --git a/src/features/UserAccount/TextNoBorder/index.tsx b/src/features/UserAccount/components/TextNoBorder/index.tsx similarity index 100% rename from src/features/UserAccount/TextNoBorder/index.tsx rename to src/features/UserAccount/components/TextNoBorder/index.tsx diff --git a/src/features/UserAccount/TextNoBorder/styled.tsx b/src/features/UserAccount/components/TextNoBorder/styled.tsx similarity index 99% rename from src/features/UserAccount/TextNoBorder/styled.tsx rename to src/features/UserAccount/components/TextNoBorder/styled.tsx index ecbba47c..cc3a99d9 100644 --- a/src/features/UserAccount/TextNoBorder/styled.tsx +++ b/src/features/UserAccount/components/TextNoBorder/styled.tsx @@ -11,7 +11,7 @@ export const TextNoBorderWrapper = styled.div` border: none; margin-top: 20px; width: 100%; - + ${PriceWrapper} { margin-right: 0; } diff --git a/src/features/UserAccount/UserAccountButton/index.tsx b/src/features/UserAccount/components/UserAccountButton/index.tsx similarity index 100% rename from src/features/UserAccount/UserAccountButton/index.tsx rename to src/features/UserAccount/components/UserAccountButton/index.tsx diff --git a/src/features/UserAccount/UserAccountButton/styled.tsx b/src/features/UserAccount/components/UserAccountButton/styled.tsx similarity index 99% rename from src/features/UserAccount/UserAccountButton/styled.tsx rename to src/features/UserAccount/components/UserAccountButton/styled.tsx index 76e71c03..c823067a 100644 --- a/src/features/UserAccount/UserAccountButton/styled.tsx +++ b/src/features/UserAccount/components/UserAccountButton/styled.tsx @@ -12,7 +12,7 @@ export const UserAccountButtonWrapper = styled.div` border-radius: 2px; margin-top: 20px; width: 100%; - + &:hover { cursor: pointer; } diff --git a/src/features/UserAccount/UserAccountSubscription/index.tsx b/src/features/UserAccount/components/UserAccountSubscription/index.tsx similarity index 100% rename from src/features/UserAccount/UserAccountSubscription/index.tsx rename to src/features/UserAccount/components/UserAccountSubscription/index.tsx diff --git a/src/features/UserAccount/UserAccountSubscription/styled.tsx b/src/features/UserAccount/components/UserAccountSubscription/styled.tsx similarity index 100% rename from src/features/UserAccount/UserAccountSubscription/styled.tsx rename to src/features/UserAccount/components/UserAccountSubscription/styled.tsx diff --git a/src/features/UserAccount/VisaLogo/index.tsx b/src/features/UserAccount/components/VisaLogo/index.tsx similarity index 100% rename from src/features/UserAccount/VisaLogo/index.tsx rename to src/features/UserAccount/components/VisaLogo/index.tsx diff --git a/src/features/UserAccount/VisaLogo/styled.tsx b/src/features/UserAccount/components/VisaLogo/styled.tsx similarity index 100% rename from src/features/UserAccount/VisaLogo/styled.tsx rename to src/features/UserAccount/components/VisaLogo/styled.tsx diff --git a/src/features/UserAccount/hooks.tsx b/src/features/UserAccount/hooks/index.tsx similarity index 94% rename from src/features/UserAccount/hooks.tsx rename to src/features/UserAccount/hooks/index.tsx index c0d86e4b..1bb349e3 100644 --- a/src/features/UserAccount/hooks.tsx +++ b/src/features/UserAccount/hooks/index.tsx @@ -13,9 +13,8 @@ import type { UserInfo } from 'requests/saveUserInfo' import { getUserInfo } from 'requests/getUserInfo' import { saveUserInfo } from 'requests/saveUserInfo' -import type { SelectedCountry } from 'hooks/useCountries' -import { useRegistrationForm } from 'hooks/useForm' - +import type { SelectedCountry } from './useCountries' +import { useUserInfoForm } from './useUserInfoForm' import { useValidateForm } from './useValidateForm' export const useUserInfo = () => { @@ -37,7 +36,7 @@ export const useUserInfo = () => { selectedCity, updateFormError, updateFormValue, - } = useRegistrationForm() + } = useUserInfoForm() const readTrimmedValue = useCallback( (fieldName: string) => trim(readFormValue(fieldName)), diff --git a/src/hooks/useCities.tsx b/src/features/UserAccount/hooks/useCities.tsx similarity index 100% rename from src/hooks/useCities.tsx rename to src/features/UserAccount/hooks/useCities.tsx diff --git a/src/hooks/useCountries.tsx b/src/features/UserAccount/hooks/useCountries.tsx similarity index 100% rename from src/hooks/useCountries.tsx rename to src/features/UserAccount/hooks/useCountries.tsx diff --git a/src/hooks/useForm.tsx b/src/features/UserAccount/hooks/useUserInfoForm.tsx similarity index 88% rename from src/hooks/useForm.tsx rename to src/features/UserAccount/hooks/useUserInfoForm.tsx index 33caa5e2..3d22a89a 100644 --- a/src/hooks/useForm.tsx +++ b/src/features/UserAccount/hooks/useUserInfoForm.tsx @@ -10,19 +10,18 @@ import { isValidEmail } from 'helpers/isValidEmail' import { isValidPhone } from 'helpers/isValidPhone' import { formatPhoneCode } from 'helpers/formatPhoneCode' -import type { SelectedCountry } from 'hooks/useCountries' -import { useCountries } from 'hooks/useCountries' -import { useCities } from 'hooks/useCities' - import { formIds } from 'config/form' import { useForm } from 'features/FormStore' -import { useSubmitHandler } from 'features/Register/components/RegistrationStep/hooks/useSubmitHandler' import { useLexicsStore } from 'features/LexicsStore' +import type { SelectedCountry } from './useCountries' +import { useCountries } from './useCountries' +import { useCities } from './useCities' + type Name = 'name_rus' | 'name_eng' -export const useRegistrationForm = () => { +export const useUserInfoForm = () => { const { readFormError, readFormValue, @@ -45,10 +44,6 @@ export const useRegistrationForm = () => { selectedCity, } = useCities() - const handleSubmit = useSubmitHandler({ - selectedCity, - selectedCountry, - }) const { suffix } = useLexicsStore() const onEmailBlur = useCallback(({ target }: FocusEvent) => { @@ -121,7 +116,6 @@ export const useRegistrationForm = () => { cities, countries, getCities, - handleSubmit, onCitySelect, onCountrySelect, onEmailBlur, diff --git a/src/features/UserAccount/useValidateForm.tsx b/src/features/UserAccount/hooks/useValidateForm.tsx similarity index 100% rename from src/features/UserAccount/useValidateForm.tsx rename to src/features/UserAccount/hooks/useValidateForm.tsx diff --git a/src/features/UserAccount/index.tsx b/src/features/UserAccount/index.tsx index d5024991..6de927ce 100644 --- a/src/features/UserAccount/index.tsx +++ b/src/features/UserAccount/index.tsx @@ -3,7 +3,6 @@ import React from 'react' import { userAccountLexics } from 'config/lexics/userAccount' import { formIds } from 'config/form' -import { Background } from 'features/Background' import { Combobox } from 'features/Combobox' import { Input } from 'features/Common' import { Form } from 'features/Login/styled' @@ -11,11 +10,11 @@ import { T9n } from 'features/T9n' import { Error } from 'features/Common/Input/styled' import { useLexicsStore, useLexicsConfig } from 'features/LexicsStore' -import { CardNumber } from './CardNumber' -import { UserAccountButton } from './UserAccountButton' -import { PageTitle } from './PageTitle' -import { UserAccountSubscription } from './UserAccountSubscription' -import { TextNoBorder } from './TextNoBorder' +import { CardNumber } from './components/CardNumber' +import { UserAccountButton } from './components/UserAccountButton' +import { PageTitle } from './components/PageTitle' +import { UserAccountSubscription } from './components/UserAccountSubscription' +import { TextNoBorder } from './components/TextNoBorder' import { useUserInfo } from './hooks' import { @@ -51,191 +50,189 @@ export const UserAccount = () => { return ( - - - - - -
- - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - - - -
- -
- - - - - - - - - - - - -
-
-
-
+ + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ +
+ + + + + + + + + + + + +
+
+
) } diff --git a/src/helpers/isValidPassword/__tests__/index.tsx b/src/helpers/isValidPassword/__tests__/index.tsx index 1516a97a..4031c3aa 100644 --- a/src/helpers/isValidPassword/__tests__/index.tsx +++ b/src/helpers/isValidPassword/__tests__/index.tsx @@ -2,15 +2,11 @@ import { isValidPassword } from '..' it('invalid passwords', () => { expect(isValidPassword('')).toBeFalsy() - expect(isValidPassword('a')).toBeFalsy() - expect(isValidPassword('1')).toBeFalsy() - expect(isValidPassword('abcdef')).toBeFalsy() - expect(isValidPassword('abcdef@')).toBeFalsy() - expect(isValidPassword('abcdef@123')).toBeFalsy() - expect(isValidPassword('ABcd12$')).toBeFalsy() }) it('valid passwords', () => { + expect(isValidPassword('a')).toBeTruthy() + expect(isValidPassword('1')).toBeTruthy() expect(isValidPassword('aASbc!def123$')).toBeTruthy() expect(isValidPassword('Abcdef@123$')).toBeTruthy() expect(isValidPassword('Abcd1234')).toBeTruthy() diff --git a/src/helpers/isValidPassword/index.tsx b/src/helpers/isValidPassword/index.tsx index edbf69db..2ddc9fae 100644 --- a/src/helpers/isValidPassword/index.tsx +++ b/src/helpers/isValidPassword/index.tsx @@ -1,13 +1,6 @@ -export const passwordRegex = '^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,500}$' +import trim from 'lodash/trim' +import isEmpty from 'lodash/isEmpty' -const passwordRegExp = new RegExp(passwordRegex) - -/** - * At least one upper case English letter, (?=.*?[A-Z]) - * At least one lower case English letter, (?=.*?[a-z]) - * At least one digit, (?=.*?[0-9]) - * Minimum eight in length .{8,} (with the anchors) - */ export const isValidPassword = (password: string) => ( - passwordRegExp.test(password) + !isEmpty(trim(password)) ) diff --git a/src/hooks/useValidateForm.tsx b/src/hooks/useValidateForm.tsx deleted file mode 100644 index 923315f9..00000000 --- a/src/hooks/useValidateForm.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import trim from 'lodash/trim' -import reduce from 'lodash/reduce' - -import { useForm } from 'features/FormStore' -import { isValidEmail } from 'helpers/isValidEmail' -import { isValidPassword } from 'helpers/isValidPassword' -import { isValidPhone } from 'helpers/isValidPhone' - -import { - formIds, - requiredFields, - simpleValidationFields, -} from 'config/form' - -export const useValidateForm = () => { - const { - allFieldsEmpty, - isFieldEmpty, - readFormValue, - updateFormError, - } = useForm() - - const readTrimmedValue = (fieldName: string) => trim(readFormValue(fieldName)) - - const setErrorOnEmptyFields = (fieldNames: Array, message: string) => ( - reduce( - fieldNames, - (acc, fieldName) => { - if (isFieldEmpty(fieldName)) { - updateFormError(fieldName, message) - return true - } - return acc - }, - false, - ) - ) - - const validateForm = () => { - let hasError = false - const email = readTrimmedValue(formIds.email) - const password = readTrimmedValue(formIds.password) - const phone = readTrimmedValue(formIds.phone) - if (allFieldsEmpty(requiredFields)) { - updateFormError(formIds.formError, 'error_fill_out_required_fields') - setErrorOnEmptyFields(requiredFields, '') - return false - } - hasError = setErrorOnEmptyFields(simpleValidationFields, 'error_fill_out_this_field') - if (isFieldEmpty(formIds.email)) { - updateFormError(formIds.email, 'error_empty_email') - hasError = true - } else if (!isValidEmail(email)) { - updateFormError(formIds.email, 'error_invalid_email_format') - hasError = true - } - if (!isValidPassword(password)) { - updateFormError(formIds.password, 'error_simple_password') - hasError = true - } - if (!isValidPhone(phone)) { - updateFormError(formIds.phone, 'error_invalid_phone_format') - hasError = true - } - return !hasError - } - - return validateForm -} diff --git a/src/requests/register.tsx b/src/requests/register.tsx index 832c8fea..deef2e52 100644 --- a/src/requests/register.tsx +++ b/src/requests/register.tsx @@ -14,49 +14,25 @@ type Response = { } type Args = { - address1: string, - address2?: string, - city?: string, - cityId?: number, - countryId: number, email: string, firstname: string, lastname: string, password: string, - phone: string, - postalCode: number, - region: string, } export const register = async ({ - address1, - address2, - city, - cityId, - countryId, email, firstname, lastname, password, - phone, - postalCode, - region, }: Args) => { const config = { body: { params: { - _p_address_line1: address1, - _p_address_line2: address2, - _p_city: city, - _p_city_id: cityId, - _p_country_id: countryId, _p_email: email, _p_firstname: firstname, _p_lastname: lastname, _p_password: password, - _p_phone: phone, - _p_postal_code: postalCode, - _p_region: region, }, proc, },