From b717e2a1e689eaadfa3e382be697cfc804d281e8 Mon Sep 17 00:00:00 2001 From: Mirlan Date: Thu, 11 Mar 2021 12:29:56 +0600 Subject: [PATCH] refactor(869): user account form refactor and bug fixes (#322) --- src/config/form.tsx | 26 +-- src/features/Combobox/hooks/index.tsx | 5 +- src/features/FormStore/helpers.tsx | 22 +++ src/features/FormStore/hooks/useFormState.tsx | 62 ++----- src/features/FormStore/index.tsx | 5 +- .../PagePersonalInfo/hooks/index.tsx | 74 ++++++++ .../PagePersonalInfo/hooks/useUserInfo.tsx | 137 --------------- .../components/PagePersonalInfo/index.tsx | 160 +----------------- .../hooks/useCities.tsx | 27 ++- .../hooks/useCountries.tsx | 39 +++-- .../PersonalInfoForm/hooks/useUserInfo.tsx | 98 +++++++++++ .../hooks/useUserInfoForm.tsx | 17 +- .../hooks/useValidateForm.tsx | 0 .../components/PersonalInfoForm/index.tsx | 158 +++++++++++++++++ .../styled.tsx | 0 src/features/UserAccount/index.tsx | 27 ++- src/requests/getUserInfo.tsx | 18 +- src/requests/saveUserInfo.tsx | 11 +- 18 files changed, 459 insertions(+), 427 deletions(-) create mode 100644 src/features/FormStore/helpers.tsx create mode 100644 src/features/UserAccount/components/PagePersonalInfo/hooks/index.tsx delete mode 100644 src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfo.tsx rename src/features/UserAccount/components/{PagePersonalInfo => PersonalInfoForm}/hooks/useCities.tsx (71%) rename src/features/UserAccount/components/{PagePersonalInfo => PersonalInfoForm}/hooks/useCountries.tsx (55%) create mode 100644 src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfo.tsx rename src/features/UserAccount/components/{PagePersonalInfo => PersonalInfoForm}/hooks/useUserInfoForm.tsx (91%) rename src/features/UserAccount/components/{PagePersonalInfo => PersonalInfoForm}/hooks/useValidateForm.tsx (100%) create mode 100644 src/features/UserAccount/components/PersonalInfoForm/index.tsx rename src/features/UserAccount/components/{PagePersonalInfo => PersonalInfoForm}/styled.tsx (100%) diff --git a/src/config/form.tsx b/src/config/form.tsx index ad6b1ec4..6ef1b45f 100644 --- a/src/config/form.tsx +++ b/src/config/form.tsx @@ -2,38 +2,16 @@ export const formIds = { address1: 'address_line1', address2: 'address_line2', city: 'city', - cityId: 'cityId', + cityId: 'city_id', country: 'country', countryId: 'countryId', email: 'email', firstname: 'firstname', formError: 'formError', + initialCountryId: 'initialCountryId', lastname: 'lastname', password: 'password', phone: 'phone', postalCode: 'postal_code', region: 'region', } - -export const requiredFields = [ - formIds.address1, - formIds.city, - formIds.country, - formIds.email, - formIds.firstname, - formIds.lastname, - formIds.password, - formIds.phone, - formIds.postalCode, - formIds.region, -] - -export const simpleValidationFields = [ - formIds.address1, - formIds.city, - formIds.country, - formIds.firstname, - formIds.lastname, - formIds.postalCode, - formIds.region, -] diff --git a/src/features/Combobox/hooks/index.tsx b/src/features/Combobox/hooks/index.tsx index 6e14a4d1..34ed64f4 100644 --- a/src/features/Combobox/hooks/index.tsx +++ b/src/features/Combobox/hooks/index.tsx @@ -69,7 +69,9 @@ export const useCombobox = ({ const onQueryChange = (e: ChangeEvent) => { onChange?.(e) - onSelect?.(null) + if (selected && onSelect) { + onSelect(null) + } } const onOptionSelect = useCallback((option: string, e?: BaseSyntheticEvent) => { @@ -95,7 +97,6 @@ export const useCombobox = ({ // если кликали элемент списка то событие обрабатывает onOptionSelect if (isOptionClicked(target)) return - onOptionSelect(query) onBlur?.(event) } diff --git a/src/features/FormStore/helpers.tsx b/src/features/FormStore/helpers.tsx new file mode 100644 index 00000000..042a3821 --- /dev/null +++ b/src/features/FormStore/helpers.tsx @@ -0,0 +1,22 @@ +import includes from 'lodash/includes' +import every from 'lodash/every' + +import { formIds } from 'config/form' + +import type { FormState } from './hooks/useFormState' + +const ignoredFields = [formIds.initialCountryId, formIds.country] + +export const isFormStateEqual = (state1: FormState, state2: FormState) => ( + every(state1, (_, key) => { + if (includes(ignoredFields, key)) return true + + const cityId1 = state1[formIds.cityId]?.value + const cityId2 = state2[formIds.cityId]?.value + if (key === formIds.city && cityId1 && cityId2) { + return cityId1 === cityId2 + } + + return state1[key]?.value === state2[key]?.value + }) +) diff --git a/src/features/FormStore/hooks/useFormState.tsx b/src/features/FormStore/hooks/useFormState.tsx index b2e28920..e8511dc1 100644 --- a/src/features/FormStore/hooks/useFormState.tsx +++ b/src/features/FormStore/hooks/useFormState.tsx @@ -2,39 +2,18 @@ import type { ChangeEvent } from 'react' import { useCallback, useState } from 'react' import isObject from 'lodash/isObject' -import isEqual from 'lodash/isEqual' -import omit from 'lodash/omit' + +import { isFormStateEqual } from '../helpers' type FieldState = { - error: string | null, + error?: string | null, value: string, } -type FormState = {[formId: string]: FieldState} -type SimilarState = {[formId: string]: string} +export type FormState = {[formId: string]: FieldState} -export const useFormState = () => { - let init = JSON.parse(localStorage.getItem('init') as string) - const countryID = init === null ? '' : init.country.id - if (init !== null) { - init.address_line1 = init.address_line1 ?? '' - init.address_line2 = init.address_line2 ?? '' - if (init.city_id !== undefined) { - init.city_id = init.city_id ?? '' - } - init.city = init.city ?? '' - init.countryId = `${countryID}` - init.cityId = init.city_id ?? '' - init.firstname = init.firstname ?? '' - init.lastname = init.lastname ?? '' - init.region = init.region ?? '' - init.postal_code = String(init.postal_code) ?? '' - init = omit(init, ['city_id', 'email', 'password', 'postalCode']) - } - const [formState, setFormState] = useState({}) - const [stateForSimilar, setStateForSimilar] = useState(init) - const isDiff = isEqual(stateForSimilar, init) - localStorage.setItem('disabled', JSON.stringify(isDiff)) +export const useFormState = (initialState: FormState = {}) => { + const [formState, setFormState] = useState(initialState) const readFormValue = useCallback( (fieldName: string) => formState[fieldName]?.value ?? '', [formState], @@ -52,32 +31,11 @@ export const useFormState = () => { ...state, [fieldName]: { error: null, - value, + value: value ?? '', }, } return newState })) - setStateForSimilar(((state) => { - if (fieldName === 'email') { - return { - ...state, - } - } - if (fieldName === 'city_id') { - return { - ...state, - } - } - if (fieldName === 'password') { - return { - ...state, - } - } - return { - ...state, - [fieldName]: value, - } - })) } ), [], @@ -99,7 +57,13 @@ export const useFormState = () => { [], ) + const hasChanges = useCallback( + () => !isFormStateEqual(formState, initialState), + [formState, initialState], + ) + return { + hasChanges, readFormError, readFormValue, updateFormError, diff --git a/src/features/FormStore/index.tsx b/src/features/FormStore/index.tsx index 5d652260..960596b1 100644 --- a/src/features/FormStore/index.tsx +++ b/src/features/FormStore/index.tsx @@ -1,11 +1,13 @@ import type { ReactNode } from 'react' import { createContext, useContext } from 'react' +import type { FormState } from './hooks/useFormState' import { useFormState } from './hooks/useFormState' type Context = ReturnType type Props = { children: ReactNode, + initialState?: FormState, } const FormContext = createContext({} as Context) @@ -17,8 +19,9 @@ const FormContext = createContext({} as Context) */ export const FormStore = ({ children, + initialState, }: Props) => { - const formState = useFormState() + const formState = useFormState(initialState) return ( {children} diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/index.tsx b/src/features/UserAccount/components/PagePersonalInfo/hooks/index.tsx new file mode 100644 index 00000000..78fb8580 --- /dev/null +++ b/src/features/UserAccount/components/PagePersonalInfo/hooks/index.tsx @@ -0,0 +1,74 @@ +import { + useState, + useEffect, + useCallback, +} from 'react' + +import find from 'lodash/find' +import reduce from 'lodash/reduce' +import isNull from 'lodash/isNull' +import isNumber from 'lodash/isNumber' +import isString from 'lodash/isString' +import isObject from 'lodash/isObject' + +import { formIds } from 'config/form' + +import type { UserInfo, SaveUserInfo } from 'requests' +import { + getUserInfo, + getCountryCities, + saveUserInfo, +} from 'requests' + +import type { FormState } from 'features/FormStore/hooks/useFormState' + +const transformToFormState = async (userInfo: UserInfo) => { + const cities = userInfo.country?.id + ? await getCountryCities('', userInfo.country.id) + : [] + return reduce( + formIds, + ( + acc: FormState, + field, + ) => { + const key = field as keyof UserInfo + const value = userInfo[key] + if (key === formIds.cityId && value) { + const city = find(cities, { id: Number(value) }) || { id: '', name: acc[formIds.city]?.value } + acc[formIds.cityId] = { value: String(city.id) } + acc[formIds.city] = { value: city.name } + } else if (key === formIds.country && isObject(value) && value.id) { + const formValue = { value: String(value.id) } + acc[formIds.initialCountryId] = formValue + acc[formIds.countryId] = formValue + } else if (isNumber(value) || isString(value)) { + acc[key] = { value: String(value) } + } else if (isNull(value)) { + acc[key] = { value: '' } + } + return acc + }, + {}, + ) +} + +export const useUserInfo = () => { + const [userInfo, setUserInfo] = useState() + + const fetchUserInfo = useCallback(() => { + getUserInfo() + .then((data) => transformToFormState(data)) + .then(setUserInfo) + }, []) + + const onSubmit = useCallback((data: SaveUserInfo) => { + saveUserInfo(data).then(fetchUserInfo) + }, [fetchUserInfo]) + + useEffect(() => { + fetchUserInfo() + }, [fetchUserInfo]) + + return { onSubmit, userInfo } +} diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfo.tsx b/src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfo.tsx deleted file mode 100644 index 791abce7..00000000 --- a/src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfo.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { - useEffect, - useCallback, - useRef, -} from 'react' - -import forEach from 'lodash/forEach' -import trim from 'lodash/trim' - -import { formIds } from 'config/form' - -import { getUserInfo } from 'requests/getUserInfo' -import { saveUserInfo } from 'requests/saveUserInfo' -import { City, getCountryCities } from 'requests/getCountryCities' - -import { useLexicsStore } from 'features/LexicsStore' - -import type { SelectedCountry } from './useCountries' -import type { Name } from './useUserInfoForm' -import { useUserInfoForm } from './useUserInfoForm' -import { useValidateForm } from './useValidateForm' - -export const useUserInfo = () => { - const validateForm = useValidateForm() - const saveButton = useRef(null) - const { suffix } = useLexicsStore() - - const { - cities, - countries, - onCitySelect, - onCountryBlur, - onCountrySelect, - onPhoneBlur, - onRegionOrCityChange, - readFormError, - readFormValue, - selectedCity, - selectedCountry, - setSelectedCountry, - updateFormValue, - } = useUserInfoForm() - const readTrimmedValue = useCallback( - (fieldName: string) => trim(readFormValue(fieldName)) || null, - [readFormValue], - ) - const handleSubmit = useCallback(() => { - if (validateForm()) { - const firstname = readTrimmedValue(formIds.firstname) - const lastname = readTrimmedValue(formIds.lastname) - const phone = readTrimmedValue(formIds.phone) - const password = readTrimmedValue(formIds.password) - const postalCode = Number(readTrimmedValue(formIds.postalCode)) - const region = readTrimmedValue(formIds.region) - const address_line1 = readTrimmedValue(formIds.address1) - const address_line2 = readTrimmedValue(formIds.address2) - const city = readTrimmedValue(formIds.city) - const countryId = Number(readTrimmedValue(formIds.countryId)) - const newUserInfo = { - address_line1, - address_line2, - city, - cityId: selectedCity?.id || null, - countryId, - firstname, - lastname, - password, - phone, - postalCode, - region, - } - const newUserInfoForStorage = { - ...newUserInfo, - country: JSON.parse(localStorage.getItem('initCountry') as string), - } - localStorage.setItem('init', JSON.stringify(newUserInfoForStorage)) - localStorage.setItem('disabled', 'true') - saveUserInfo(newUserInfo).then(() => saveButton?.current?.blur()) - } - }, [ - readTrimmedValue, - validateForm, - selectedCity, - ]) - - useEffect(() => { - getUserInfo().then((res: any) => { - const response = res - const convertResponse = () => { - forEach(response, (value: string | number | SelectedCountry, key: string) => { - if (value && typeof value === 'object') { - setSelectedCountry({ - ...value, - name: value[`name_${suffix}` as Name], - }) - updateFormValue(formIds.countryId)(String(value.id)) - } else if (value) { - updateFormValue(key)(String(value)) - } - }) - } - if (response.city === null && response.city_id !== null) { - getCountryCities('', response.country.id).then((resp) => { - const initCity = resp.find((i:City) => i.id.toString() === response.city_id.toString()) - if (initCity !== undefined) { - response.city = initCity.name - localStorage.setItem('init', JSON.stringify(res)) - convertResponse() - } - }) - return - } - localStorage.setItem('init', JSON.stringify(response)) - convertResponse() - }) - }, [ - suffix, - updateFormValue, - setSelectedCountry, - ]) - - return { - cities, - countries, - handleSubmit, - onCitySelect, - onCountryBlur, - onCountrySelect, - onPhoneBlur, - onRegionOrCityChange, - readFormError, - readFormValue, - saveButton, - selectedCountry, - updateFormValue, - } -} diff --git a/src/features/UserAccount/components/PagePersonalInfo/index.tsx b/src/features/UserAccount/components/PagePersonalInfo/index.tsx index c5304f9f..5cb106e5 100644 --- a/src/features/UserAccount/components/PagePersonalInfo/index.tsx +++ b/src/features/UserAccount/components/PagePersonalInfo/index.tsx @@ -1,158 +1,14 @@ -import { formIds } from 'config/form' +import { FormStore } from 'features/FormStore' -import { Combobox } from 'features/Combobox' -import { Input } from 'features/Common' -import { T9n } from 'features/T9n' -import { Error } from 'features/Common/Input/styled' - -import { useState } from 'react' -import { useUserInfo } from './hooks/useUserInfo' - -import { SolidButton } from '../../styled' -import { Form, ButtonWrapper } from './styled' - -const labelWidth = 104 - -const { - address1, - address2, - city, - country, - firstname, - formError, - lastname, - password, - phone, - region, -} = formIds +import { useUserInfo } from './hooks' +import { PersonalInfoForm } from '../PersonalInfoForm' export const PagePersonalInfo = () => { - const { - cities, - countries, - handleSubmit, - onCitySelect, - onCountryBlur, - onCountrySelect, - onPhoneBlur, - onRegionOrCityChange, - readFormError, - readFormValue, - saveButton, - selectedCountry, - updateFormValue, - } = useUserInfo() - - const [state, setState] = useState(true) - const isDisabled = JSON.parse(localStorage.getItem('disabled') as string) - + const { onSubmit, userInfo } = useUserInfo() + if (!userInfo) return null return ( -
- - - - - - - - - - - { handleSubmit(); setState((!state)) }} - ref={saveButton} - > - - - - - + + + ) } diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/useCities.tsx b/src/features/UserAccount/components/PersonalInfoForm/hooks/useCities.tsx similarity index 71% rename from src/features/UserAccount/components/PagePersonalInfo/hooks/useCities.tsx rename to src/features/UserAccount/components/PersonalInfoForm/hooks/useCities.tsx index 186a2af5..32555b9d 100644 --- a/src/features/UserAccount/components/PagePersonalInfo/hooks/useCities.tsx +++ b/src/features/UserAccount/components/PersonalInfoForm/hooks/useCities.tsx @@ -1,3 +1,4 @@ +import type { FocusEvent } from 'react' import { useMemo, useState, @@ -36,12 +37,6 @@ const useCitiesList = () => { export const useCities = () => { const { updateFormValue } = useForm() - const [selectedCity, setSelectedCity] = useState(null) - - const setCityQuery = useMemo( - () => updateFormValue(formIds.city), - [updateFormValue], - ) const { cities, @@ -51,24 +46,28 @@ export const useCities = () => { const onCitySelect = useCallback((newCity: City | null) => { if (newCity) { - setCityQuery(newCity.name) - setSelectedCity(newCity) + updateFormValue(formIds.city)(newCity.name) + updateFormValue(formIds.cityId)(String(newCity.id)) } else { - setSelectedCity(null) + updateFormValue(formIds.cityId)('') } - }, [setCityQuery]) + }, [updateFormValue]) const resetSelectedCity = useCallback(() => { - setCityQuery('') - setSelectedCity(null) - }, [setCityQuery]) + updateFormValue(formIds.city)('') + updateFormValue(formIds.cityId)('') + }, [updateFormValue]) + + const onCityBlur = (e: FocusEvent) => { + updateFormValue(formIds.city)(e.target.value ?? '') + } return { cities, getCities, + onCityBlur, onCitySelect, resetCities, resetSelectedCity, - selectedCity, } } diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/useCountries.tsx b/src/features/UserAccount/components/PersonalInfoForm/hooks/useCountries.tsx similarity index 55% rename from src/features/UserAccount/components/PagePersonalInfo/hooks/useCountries.tsx rename to src/features/UserAccount/components/PersonalInfoForm/hooks/useCountries.tsx index 3d7bde30..c40d4707 100644 --- a/src/features/UserAccount/components/PagePersonalInfo/hooks/useCountries.tsx +++ b/src/features/UserAccount/components/PersonalInfoForm/hooks/useCountries.tsx @@ -5,11 +5,16 @@ import { } from 'react' import orderBy from 'lodash/orderBy' +import find from 'lodash/find' import map from 'lodash/map' import type { Countries, Country } from 'requests' import { getCountries } from 'requests' + +import { formIds } from 'config/form' + import { useLexicsStore } from 'features/LexicsStore' +import { useForm } from 'features/FormStore' export type SelectedCountry = (Country & { name: string, @@ -28,29 +33,37 @@ const useCountriesList = () => { } export const useCountries = () => { + const { readFormValue, updateFormValue } = useForm() const countries = useCountriesList() const { suffix } = useLexicsStore() const [selectedCountry, setSelectedCountry] = useState(null) - const nameField = `name_${suffix}` as Names - const initCountry = { - id: selectedCountry?.id, - name_eng: selectedCountry?.name_eng, - name_rus: selectedCountry?.name_rus, - } - localStorage.setItem('initCountry', JSON.stringify(initCountry)) const transformedCountries = useMemo( () => orderBy( - map(countries, (country) => ({ - ...country, - name: country[nameField], - })), - 'name', + map(countries, (country) => { + const nameField = `name_${suffix}` as Names + return { + ...country, + name: country[nameField], + } + }), + ({ name }) => name, ), - [countries, nameField], + [countries, suffix], ) + const onCountryBlur = () => { + updateFormValue(formIds.country)('') + } + + const countryId = readFormValue(formIds.initialCountryId) + useEffect(() => { + const initialCountry = find(transformedCountries, { id: Number(countryId) }) + setSelectedCountry(initialCountry || null) + }, [transformedCountries, countryId]) + return { countries: transformedCountries, + onCountryBlur, selectedCountry, setSelectedCountry, } diff --git a/src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfo.tsx b/src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfo.tsx new file mode 100644 index 00000000..3ccf61b8 --- /dev/null +++ b/src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfo.tsx @@ -0,0 +1,98 @@ +import { useCallback } from 'react' + +import trim from 'lodash/trim' + +import { formIds } from 'config/form' + +import type { SaveUserInfo } from 'requests/saveUserInfo' + +import { useForm } from 'features/FormStore' + +import { useUserInfoForm } from './useUserInfoForm' +import { useValidateForm } from './useValidateForm' + +export type Props = { + onSubmit: (data: SaveUserInfo) => void, +} + +export const useUserInfo = ({ onSubmit }: Props) => { + const { + hasChanges, + readFormError, + readFormValue, + updateFormValue, + } = useForm() + const validateForm = useValidateForm() + const { + cities, + countries, + onCityBlur, + onCitySelect, + onCountryBlur, + onCountrySelect, + onPhoneBlur, + onRegionOrCityChange, + selectedCountry, + } = useUserInfoForm() + const readTrimmedValue = useCallback( + (fieldName: string) => trim(readFormValue(fieldName)) || null, + [readFormValue], + ) + const readNumberValue = useCallback( + (fieldName: string) => { + const value = readTrimmedValue(fieldName) + return value ? Number(value) : null + }, + [readTrimmedValue], + ) + const handleSubmit = useCallback(() => { + if (validateForm()) { + const firstname = readTrimmedValue(formIds.firstname) + const lastname = readTrimmedValue(formIds.lastname) + const phone = readTrimmedValue(formIds.phone) + const password = readTrimmedValue(formIds.password) + const postalCode = readNumberValue(formIds.postalCode) + const region = readTrimmedValue(formIds.region) + const address_line1 = readTrimmedValue(formIds.address1) + const address_line2 = readTrimmedValue(formIds.address2) + const city = readTrimmedValue(formIds.city) + const cityId = readNumberValue(formIds.cityId) + const countryId = readNumberValue(formIds.countryId) + onSubmit({ + address_line1, + address_line2, + city: cityId ? null : city, + cityId, + countryId, + firstname, + lastname, + password, + phone, + postalCode, + region, + }) + } + }, [ + onSubmit, + readTrimmedValue, + readNumberValue, + validateForm, + ]) + + return { + cities, + countries, + handleSubmit, + hasChanges, + onCityBlur, + onCitySelect, + onCountryBlur, + onCountrySelect, + onPhoneBlur, + onRegionOrCityChange, + readFormError, + readFormValue, + selectedCountry, + updateFormValue, + } +} diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfoForm.tsx b/src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfoForm.tsx similarity index 91% rename from src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfoForm.tsx rename to src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfoForm.tsx index 91e40801..521f3cd8 100644 --- a/src/features/UserAccount/components/PagePersonalInfo/hooks/useUserInfoForm.tsx +++ b/src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfoForm.tsx @@ -17,11 +17,8 @@ import type { SelectedCountry } from './useCountries' import { useCountries } from './useCountries' import { useCities } from './useCities' -export type Name = 'name_rus' | 'name_eng' - export const useUserInfoForm = () => { const { - readFormError, readFormValue, updateFormError, updateFormValue, @@ -29,6 +26,7 @@ export const useUserInfoForm = () => { const { countries, + onCountryBlur, selectedCountry, setSelectedCountry, } = useCountries() @@ -36,10 +34,10 @@ export const useUserInfoForm = () => { const { cities, getCities, + onCityBlur, onCitySelect, resetCities, resetSelectedCity, - selectedCity, } = useCities() const onPhoneBlur = useCallback(({ target }: ChangeEvent) => { @@ -54,9 +52,9 @@ export const useUserInfoForm = () => { if (country?.id === selectedCountry?.id) return setSelectedCountry(country) - updateFormValue(formIds.countryId)(country?.id ? String(country?.id) : '') - updateFormValue(formIds.cityId)('') + + updateFormValue(formIds.region)('') resetCities() resetSelectedCity() @@ -79,10 +77,6 @@ export const useUserInfoForm = () => { updateFormValue, ]) - const onCountryBlur = () => { - updateFormValue(formIds.country)(selectedCountry?.name || '') - } - const onRegionOrCityChange = useCallback((fieldName: string) => ( ({ target }: ChangeEvent) => { if (selectedCountry) { @@ -111,14 +105,13 @@ export const useUserInfoForm = () => { return { cities, countries, + onCityBlur, onCitySelect, onCountryBlur, onCountrySelect, onPhoneBlur, onRegionOrCityChange, - readFormError, readFormValue, - selectedCity, selectedCountry, setSelectedCountry, updateFormValue, diff --git a/src/features/UserAccount/components/PagePersonalInfo/hooks/useValidateForm.tsx b/src/features/UserAccount/components/PersonalInfoForm/hooks/useValidateForm.tsx similarity index 100% rename from src/features/UserAccount/components/PagePersonalInfo/hooks/useValidateForm.tsx rename to src/features/UserAccount/components/PersonalInfoForm/hooks/useValidateForm.tsx diff --git a/src/features/UserAccount/components/PersonalInfoForm/index.tsx b/src/features/UserAccount/components/PersonalInfoForm/index.tsx new file mode 100644 index 00000000..9e7b3a3d --- /dev/null +++ b/src/features/UserAccount/components/PersonalInfoForm/index.tsx @@ -0,0 +1,158 @@ +import { formIds } from 'config/form' + +import { Combobox } from 'features/Combobox' +import { Input } from 'features/Common' +import { T9n } from 'features/T9n' +import { Error } from 'features/Common/Input/styled' + +import type { Props } from './hooks/useUserInfo' +import { useUserInfo } from './hooks/useUserInfo' + +import { SolidButton } from '../../styled' +import { Form, ButtonWrapper } from './styled' + +const labelWidth = 104 + +const { + address1, + address2, + city, + cityId, + country, + firstname, + formError, + lastname, + password, + phone, + region, +} = formIds + +export const PersonalInfoForm = (props: Props) => { + const { + cities, + countries, + handleSubmit, + hasChanges, + onCityBlur, + onCitySelect, + onCountryBlur, + onCountrySelect, + onPhoneBlur, + onRegionOrCityChange, + readFormError, + readFormValue, + selectedCountry, + updateFormValue, + } = useUserInfo(props) + + return ( +
+ + + + + + + + + + + + + + + + + ) +} diff --git a/src/features/UserAccount/components/PagePersonalInfo/styled.tsx b/src/features/UserAccount/components/PersonalInfoForm/styled.tsx similarity index 100% rename from src/features/UserAccount/components/PagePersonalInfo/styled.tsx rename to src/features/UserAccount/components/PersonalInfoForm/styled.tsx diff --git a/src/features/UserAccount/index.tsx b/src/features/UserAccount/index.tsx index 2d04dc74..41d2e4c2 100644 --- a/src/features/UserAccount/index.tsx +++ b/src/features/UserAccount/index.tsx @@ -4,7 +4,6 @@ import { PAGES } from 'config' import { userAccountLexics } from 'config/lexics/userAccount' import { useLexicsConfig } from 'features/LexicsStore' -import { FormStore } from 'features/FormStore' import { Logo } from 'features/Logo' import { PagePersonalInfo } from './components/PagePersonalInfo' @@ -47,20 +46,18 @@ const UserAccount = () => { - - - - - - - - - - - - - - + + + + + + + + + + + + ) diff --git a/src/requests/getUserInfo.tsx b/src/requests/getUserInfo.tsx index 1c5f27d8..5f02f9b1 100644 --- a/src/requests/getUserInfo.tsx +++ b/src/requests/getUserInfo.tsx @@ -3,10 +3,26 @@ import { PROCEDURES, } from 'config' import { callApi } from 'helpers' -import type { UserInfo } from 'requests/saveUserInfo' const proc = PROCEDURES.get_user_info +export type UserInfo = { + address_line1: string | null, + address_line2: string | null, + city: string | null, + cityId: number | null, + country?: { + id: number, + name_eng: string, + name_rus: string, + }, + firstname: string | null, + lastname: string | null, + password: string | null, + phone: string | null, + region: string | null, +} + export const getUserInfo = (): Promise => { const config = { body: { params: {}, proc }, diff --git a/src/requests/saveUserInfo.tsx b/src/requests/saveUserInfo.tsx index 566d233a..e1d73556 100644 --- a/src/requests/saveUserInfo.tsx +++ b/src/requests/saveUserInfo.tsx @@ -3,11 +3,10 @@ import { PROCEDURES, } from 'config' import { callApi } from 'helpers' -import omit from 'lodash/omit' const proc = PROCEDURES.save_user_info -export type UserInfo = { +export type SaveUserInfo = { address_line1: string | null, address_line2: string | null, city: string | null, @@ -43,8 +42,8 @@ export const saveUserInfo = async ({ phone, postalCode, region, -}: UserInfo) => { - const commonConfig = { +}: SaveUserInfo) => { + const config = { body: { params: { _p_address_line1: address_line1, @@ -62,9 +61,7 @@ export const saveUserInfo = async ({ proc, }, } - const config = cityId === null - ? omit(commonConfig, 'body.params._p_city_id') - : omit(commonConfig, 'body.params._p_city') + const response: Response = await callApi({ config, url: DATA_URL,