Ott 168 login validation errors (#41)

keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 6 years ago committed by GitHub
parent c23e650512
commit 2bdde0a79a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/config/lexics/public.tsx
  2. 7
      src/features/AuthStore/hooks/useLogin.tsx
  3. 2
      src/features/Combobox/index.tsx
  4. 2
      src/features/Common/Input/index.tsx
  5. 4
      src/features/Common/Input/styled.tsx
  6. 64
      src/features/Login/hooks.tsx
  7. 38
      src/features/Login/index.tsx
  8. 14
      src/features/Register/components/RegistrationStep/hooks/useValidateForm.tsx
  9. 2
      src/features/Register/components/RegistrationStep/index.tsx
  10. 12
      src/requests/login.tsx

@ -1,8 +1,11 @@
export const publicLexics = { export const publicLexics = {
error_account_blocked: 12909,
error_empty_email: 2498, error_empty_email: 2498,
error_empty_password: 2499,
error_fill_out_required_fields: 12911, error_fill_out_required_fields: 12911,
error_fill_out_this_field: 12933, error_fill_out_this_field: 12933,
error_invalid_email_format: 12908, error_invalid_email_format: 12908,
error_invalid_email_or_password: 2502,
error_select_country_first: 12910, error_select_country_first: 12910,
error_simple_password: 12940, error_simple_password: 12940,
form_address1: 12914, form_address1: 12914,

@ -19,12 +19,7 @@ export const useLogin = ({ setToken }: Args) => {
history.replace(PAGES.home) history.replace(PAGES.home)
} }
const onError = (message: string) => {
// eslint-disable-next-line no-alert
window.alert(message)
}
return async ({ email, password }: LoginArgs) => ( return async ({ email, password }: LoginArgs) => (
login({ email, password }).then(onSuccess, onError) login({ email, password }).then(onSuccess)
) )
} }

@ -88,7 +88,7 @@ export const Combobox = <T extends Option>(props: Props<T>) => {
</ComboboxPopoverStyled> </ComboboxPopoverStyled>
)} )}
</ComboboxStyled> </ComboboxStyled>
<Error>{error && <T9n t={error} />}</Error> <Error t={error || ''} />
</Column> </Column>
) )
} }

@ -81,6 +81,6 @@ export const Input = ({
title={title} title={title}
/> />
</InputWrapper> </InputWrapper>
<Error>{error && <T9n t={error} />}</Error> <Error t={error || ''} />
</Column> </Column>
) )

@ -2,6 +2,8 @@ import styled, { css } from 'styled-components/macro'
import isNil from 'lodash/isNil' import isNil from 'lodash/isNil'
import { T9n } from 'features/T9n'
export type WrapperProps = { export type WrapperProps = {
error?: string | null, error?: string | null,
paddingX?: number, paddingX?: number,
@ -88,7 +90,7 @@ export const Column = styled.div`
flex-direction: column; flex-direction: column;
` `
export const Error = styled.span` export const Error = styled(T9n)`
min-height: 16px; min-height: 16px;
margin-top: 5px; margin-top: 5px;
font-style: normal; font-style: normal;

@ -1,26 +1,68 @@
import type { FormEvent } from 'react' import type { FormEvent, FocusEvent } from 'react'
import trim from 'lodash/trim' import trim from 'lodash/trim'
import isEmpty from 'lodash/isEmpty'
import { useAuthStore } from 'features/AuthStore' import { useAuthStore } from 'features/AuthStore'
import { useForm } from 'features/FormStore'
import { formIds } from 'features/Register/components/RegistrationStep/config' import { formIds } from 'features/Register/components/RegistrationStep/config'
import { isValidEmail } from 'features/Register/helpers/isValidEmail'
const readFormValue = (event: FormEvent<HTMLFormElement>) => ( export const useLoginForm = () => {
(fieldName: string) => trim(event.currentTarget[fieldName]?.value) const {
) readFormError,
readFormValue,
export const useForm = () => { updateFormError,
updateFormValue,
} = useForm()
const { login } = useAuthStore() const { login } = useAuthStore()
const onEmailBlur = ({ target }: FocusEvent<HTMLInputElement>) => {
if (!isValidEmail(target.value)) {
updateFormError(formIds.email, 'error_invalid_email_format')
}
}
const readTrimmedValue = (fieldName: string) => trim(readFormValue(fieldName))
const validateForm = () => {
let hasError = false
const email = readTrimmedValue(formIds.email)
const password = readTrimmedValue(formIds.password)
if (isEmpty(email)) {
updateFormError(formIds.email, 'error_empty_email')
hasError = true
} else if (!isValidEmail(email)) {
updateFormError(formIds.email, 'error_invalid_email_format')
hasError = true
}
if (isEmpty(password)) {
updateFormError(formIds.password, 'error_empty_password')
hasError = true
}
return !hasError
}
const onError = (message: string) => {
updateFormError(formIds.formError, message)
}
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => { const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault() event.preventDefault()
const readFieldValue = readFormValue(event) if (validateForm()) {
const email = readFieldValue(formIds.email) const email = readTrimmedValue(formIds.email)
const password = readFieldValue(formIds.password) const password = readTrimmedValue(formIds.password)
login({ email, password }) login({ email, password }).catch(onError)
}
} }
return { handleSubmit } return {
handleSubmit,
onEmailBlur,
readFormError,
readFormValue,
updateFormValue,
}
} }

@ -5,10 +5,11 @@ import { PAGES } from 'config'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { Logo } from 'features/Logo' import { Logo } from 'features/Logo'
import { Input, ButtonSolid } from 'features/Common' import { Input, ButtonSolid } from 'features/Common'
import { Error } from 'features/Common/Input/styled'
import { formIds } from 'features/Register/components/RegistrationStep/config' import { formIds } from 'features/Register/components/RegistrationStep/config'
import { useLexicsStore } from 'features/LexicsStore' import { FormStore } from 'features/FormStore'
import { useForm } from './hooks' import { useLoginForm } from './hooks'
import { import {
BlockTitle, BlockTitle,
CenterBlock, CenterBlock,
@ -19,10 +20,16 @@ import {
const labelWidth = 75 const labelWidth = 75
export const Login = () => { const LoginForm = () => {
const { handleSubmit } = useForm() const {
const { translate } = useLexicsStore() handleSubmit,
const defaultMessage = translate('please_fill_out_this_field') onEmailBlur,
readFormError,
readFormValue,
updateFormValue,
} = useLoginForm()
const requestError = readFormError(formIds.formError)
return ( return (
<CenterBlock> <CenterBlock>
@ -32,21 +39,26 @@ export const Login = () => {
<T9n t='step_title_login' /> <T9n t='step_title_login' />
</BlockTitle> </BlockTitle>
{requestError && <Error t={requestError} />}
<Input <Input
required
id={formIds.email} id={formIds.email}
type='email' type='email'
value={readFormValue(formIds.email)}
error={readFormError(formIds.email)}
onChange={updateFormValue(formIds.email)}
onBlur={onEmailBlur}
labelLexic='form_email' labelLexic='form_email'
labelWidth={labelWidth} labelWidth={labelWidth}
title={defaultMessage}
/> />
<Input <Input
required
id={formIds.password} id={formIds.password}
type='password' type='password'
value={readFormValue(formIds.password)}
error={readFormError(formIds.password)}
onChange={updateFormValue(formIds.password)}
labelLexic='form_password' labelLexic='form_password'
labelWidth={labelWidth} labelWidth={labelWidth}
title={defaultMessage}
/> />
<ButtonsBlock> <ButtonsBlock>
@ -61,3 +73,9 @@ export const Login = () => {
</CenterBlock> </CenterBlock>
) )
} }
export const Login = () => (
<FormStore>
<LoginForm />
</FormStore>
)

@ -27,16 +27,16 @@ export const useValidateForm = () => {
(acc, fieldName) => { (acc, fieldName) => {
if (isFieldEmpty(fieldName)) { if (isFieldEmpty(fieldName)) {
updateFormError(fieldName, message) updateFormError(fieldName, message)
return acc + 1 return true
} }
return acc return acc
}, },
0, false,
) )
) )
const validateForm = () => { const validateForm = () => {
let errorsCount = 0 let hasError = false
const email = readTrimmedValue(formIds.email) const email = readTrimmedValue(formIds.email)
const password = readTrimmedValue(formIds.password) const password = readTrimmedValue(formIds.password)
if (allFieldsEmpty(requiredFields)) { if (allFieldsEmpty(requiredFields)) {
@ -46,16 +46,16 @@ export const useValidateForm = () => {
} }
if (isFieldEmpty(formIds.email)) { if (isFieldEmpty(formIds.email)) {
updateFormError(formIds.email, 'error_empty_email') updateFormError(formIds.email, 'error_empty_email')
errorsCount++ hasError = true
} else if (!isValidEmail(email)) { } else if (!isValidEmail(email)) {
updateFormError(formIds.email, 'error_invalid_email_format') updateFormError(formIds.email, 'error_invalid_email_format')
} }
if (!isValidPassword(password)) { if (!isValidPassword(password)) {
updateFormError(formIds.password, 'error_simple_password') updateFormError(formIds.password, 'error_simple_password')
errorsCount++ hasError = true
} }
errorsCount += setErrorOnEmptyFields(simpleValidationFields, 'error_fill_out_this_field') hasError = setErrorOnEmptyFields(simpleValidationFields, 'error_fill_out_this_field')
return errorsCount === 0 return !hasError
} }
return validateForm return validateForm

@ -139,7 +139,7 @@ const Registration = () => {
<ButtonSolid type='submit'> <ButtonSolid type='submit'>
<T9n t='next' /> <T9n t='next' />
</ButtonSolid> </ButtonSolid>
<Error><T9n t={readFormError(formIds.formError) || ''} /></Error> <Error t={readFormError(formIds.formError) || ''} />
</ButtonsBlock> </ButtonsBlock>
</Form> </Form>
) )

@ -15,12 +15,16 @@ const statusCodes = {
INVALID_CREDENTIALS: 3, INVALID_CREDENTIALS: 3,
SUCCESS: 1, SUCCESS: 1,
USER_REMOVED_OR_BLOCKED: 4, USER_REMOVED_OR_BLOCKED: 4,
} as const }
type StatusCodes = typeof statusCodes[keyof typeof statusCodes] const errorMessages = {
[statusCodes.EMAIL_NOT_FOUND]: 'error_invalid_email_or_password',
[statusCodes.INVALID_CREDENTIALS]: 'error_invalid_email_or_password',
[statusCodes.USER_REMOVED_OR_BLOCKED]: 'error_account_blocked',
}
type Response = { type Response = {
_p_status: StatusCodes, _p_status: number,
} }
type Args = { type Args = {
@ -55,7 +59,7 @@ export const login = async ({
if (token && _p_status === statusCodes.SUCCESS) { if (token && _p_status === statusCodes.SUCCESS) {
return Promise.resolve(token) return Promise.resolve(token)
} }
return Promise.reject(_p_status) return Promise.reject(errorMessages[_p_status])
} catch (error) { } catch (error) {
return Promise.reject() return Promise.reject()
} }

Loading…
Cancel
Save