feat(#in282): resend email btn add

fix(#in282): min fix

fix(#in282): min fix2
pull/176/head
Farber Denis 3 years ago
parent 370c165905
commit 3c7e8c3a75
  1. 23
      src/features/AuthServiceApp/components/App/index.tsx
  2. 20
      src/features/AuthServiceApp/components/App/styled.tsx
  3. 32
      src/features/AuthServiceApp/components/Login/hooks.tsx
  4. 40
      src/features/AuthServiceApp/components/Login/index.tsx
  5. 36
      src/features/AuthServiceApp/components/Login/styled.tsx
  6. 6
      src/features/AuthServiceApp/components/Registration/hooks.tsx
  7. 8
      src/features/AuthServiceApp/components/Registration/index.tsx
  8. 3
      src/features/AuthServiceApp/config/lexics.tsx
  9. 57
      src/features/AuthServiceApp/requests/resendConfirmation.tsx

@ -6,37 +6,18 @@ import {
Switch,
} from 'react-router-dom'
import styled, { css } from 'styled-components/macro'
import { isMobileDevice } from 'config/userAgent'
import { useLexicsConfig } from 'features/LexicsStore'
import { PAGES } from '../../config/pages'
import { lexics } from '../../config/lexics'
import { Main } from './styled'
const Login = lazy(() => import('../Login'))
const Registration = lazy(() => import('../Registration'))
const ChangePassword = lazy(() => import('../ChangePassword'))
const Oauth = lazy(() => import('../Oauth'))
const Main = styled.main`
width: 100%;
height: 100vh;
overflow-y: auto;
::-webkit-scrollbar {
display: none;
}
${isMobileDevice
? css`
padding: 0 12px;
max-height: 100vh;
`
: ''};
`
export const App = () => {
useLexicsConfig(lexics)

@ -0,0 +1,20 @@
import styled, { css } from 'styled-components/macro'
import { isMobileDevice } from 'config/userAgent'
export const Main = styled.main`
width: 100%;
height: 100vh;
overflow-y: auto;
::-webkit-scrollbar {
display: none;
}
${isMobileDevice
? css`
padding: 0 12px;
max-height: 100vh;
`
: ''};
`

@ -1,4 +1,5 @@
import type { FormEvent, MouseEvent } from 'react'
import {
useRef,
useState,
@ -13,6 +14,7 @@ import { useLocalStore } from 'hooks'
import type { Settings } from 'features/AuthStore/helpers'
import { loginCheck } from 'features/AuthServiceApp/requests/auth'
import { resendConfirmation } from 'features/AuthServiceApp/requests/resendConfirmation'
import { getApiUrl } from 'features/AuthServiceApp/config/routes'
import { useAuthFields } from 'features/AuthServiceApp/hooks/useAuthFields'
@ -36,8 +38,10 @@ export const useLoginForm = () => {
} = urlParams
const [authError, setAuthError] = useState('')
const [resendConfirm, setResendConfirm] = useState(false)
const [isFetching, setIsFetching] = useState(false)
const [isRecoveryPopupOpen, setIsRecoveryPopupOpen] = useState(false)
const [isModalOpen, setIsModalOpen] = useState(false)
const formRef = useRef<HTMLFormElement>(null)
const {
@ -73,6 +77,10 @@ export const useLoginForm = () => {
const handleError = (error: string) => {
setAuthError(error)
setIsFetching(false)
if (error === 'error_user_not_confirm') {
setResendConfirm(true)
}
}
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
@ -97,6 +105,26 @@ export const useLoginForm = () => {
}
}
const handleResendConfirm = async () => {
setIsFetching(true)
try {
await resendConfirmation({
email,
urlParams,
})
setAuthError('')
setIsFetching(false)
setIsModalOpen(true)
} catch (err) {
handleError(String(err))
setIsFetching(false)
}
}
const handleModalClose = () => {
setIsModalOpen(false)
}
const handleAuthButtonClick = (authProvider: AuthProviders) => (
e: MouseEvent<HTMLButtonElement>,
) => {
@ -119,9 +147,12 @@ export const useLoginForm = () => {
formError,
formRef,
handleAuthButtonClick,
handleModalClose,
handleModalOpen,
handleResendConfirm,
handleSubmit,
isFetching,
isModalOpen,
isRecoveryPopupOpen,
isSubmitDisabled,
lang,
@ -131,6 +162,7 @@ export const useLoginForm = () => {
onPasswordChange,
password,
redirect_uri,
resendConfirm,
response_mode,
response_type,
scope,

@ -1,5 +1,6 @@
import { T9n } from 'features/T9n'
import { RecoveryPopup } from 'features/AuthServiceApp/components/RecoveryPopup'
import { RegisterPopup } from 'features/AuthServiceApp/components/RegisterPopup'
import { client } from 'features/AuthServiceApp/config/clients'
import { PAGES } from '../../config/pages'
@ -17,6 +18,8 @@ import {
AuthButtonText,
AuthButtonImage,
ContinueWith,
ButtonsContainer,
ResendEmailButton,
} from './styled'
import {
@ -45,9 +48,12 @@ const Login = () => {
formError,
formRef,
handleAuthButtonClick,
handleModalClose,
handleModalOpen,
handleResendConfirm,
handleSubmit,
isFetching,
isModalOpen,
isRecoveryPopupOpen,
isSubmitDisabled,
lang,
@ -57,6 +63,7 @@ const Login = () => {
onPasswordChange,
password,
redirect_uri,
resendConfirm,
response_mode,
response_type,
scope,
@ -120,13 +127,22 @@ const Login = () => {
) : (<T9n t='login' />)
}
</ButtonSolid>
<RegisterButton
to={`${PAGES.registration}${window.location.search}`}
id='auth_registration'
>
<T9n t='register' />
</RegisterButton>
<ButtonsContainer>
<RegisterButton
to={`${PAGES.registration}${window.location.search}`}
id='auth_registration'
>
<T9n t='register' />
</RegisterButton>
{resendConfirm && (
<ResendEmailButton
onClick={handleResendConfirm}
type='button'
>
<T9n t='send_new_email' />
</ResendEmailButton>
)}
</ButtonsContainer>
<ContinueWith t='or_continue_with' />
<AuthButtonsContainer>
<AuthButton onClick={handleAuthButtonClick(AuthProviders.Google)}>
@ -152,7 +168,15 @@ const Login = () => {
</LanguageSelectWrapper>
</Container>
</Form>
<RecoveryPopup isModalOpen={isRecoveryPopupOpen} setIsModalOpen={setIsRecoveryPopupOpen} />
<RecoveryPopup
isModalOpen={isRecoveryPopupOpen}
setIsModalOpen={setIsRecoveryPopupOpen}
/>
<RegisterPopup
email={email}
isModalOpen={isModalOpen}
handleModalClose={handleModalClose}
/>
</CenterBlock>
<CompanyInfo
clientName={client.name}

@ -5,6 +5,7 @@ import styled, { css } from 'styled-components/macro'
import { isMobileDevice } from 'config/userAgent'
import { outlineButtonStyles } from 'features/Common/Button'
import { ButtonOutline } from 'features/Common'
import { T9n } from 'features/T9n'
import { AuthProviders } from '../../config/authProviders'
@ -13,9 +14,21 @@ type TAuthButtonImage = {
authProvider: AuthProviders,
}
export const ButtonsContainer = styled.div`
width: 100%;
display: flex;
${isMobileDevice
? css`
flex-direction: column;
`
: ''};
`
export const RegisterButton = styled(Link)`
${outlineButtonStyles}
width: 100%;
min-width: 10rem;
height: 50px;
border-radius: 5px;
margin-top: 15px;
@ -23,6 +36,7 @@ export const RegisterButton = styled(Link)`
align-items: center;
justify-content: center;
font-size: 20px;
${isMobileDevice
? css`
height: 44px;
@ -37,6 +51,28 @@ export const RegisterButton = styled(Link)`
: ''};
`
export const ResendEmailButton = styled(ButtonOutline)`
width: 100%;
margin-left: 10px;
padding: 0 10px;
height: 50px;
margin-top: 15px;
border-radius: 5px;
line-height: 20px;
font-size: 20px;
${isMobileDevice
? css`
width: 100%;
margin-left: 0;
border-radius: 10px;
height: 44px;
font-size: 17px;
margin-top: 10px;
`
: ''};
`
export const ContinueWith = styled(T9n)`
margin: 20px auto;
font-size: 16px;

@ -1,5 +1,5 @@
import { SyntheticEvent, useState } from 'react'
import { useHistory } from 'react-router'
import { useHistory, useLocation } from 'react-router'
import { setAgreements } from 'requests/getAgreements'
import { useAuthFields } from 'features/AuthServiceApp/hooks/useAuthFields'
@ -11,11 +11,13 @@ import { PAGES } from '../../config/pages'
export const useRegistrationForm = () => {
const history = useHistory()
const urlParams = useParamsUrl()
const { search } = useLocation()
const [authError, setAuthError] = useState('')
const [termsAccepted, setTermsAccepted] = useState(true)
const [cookiesAccepted, setCookiesAccepted] = useState(true)
const [isFetching, setIsFetching] = useState(false)
const [isModalOpen, setIsModalOpen] = useState(false)
const {
email,
error: formError,
@ -56,7 +58,7 @@ export const useRegistrationForm = () => {
const handleModalClose = () => {
setIsModalOpen(false)
history.replace(PAGES.login)
history.replace(`${PAGES.login}${search}`)
}
const onTermsChange = () => {

@ -27,6 +27,7 @@ import {
Wrapper,
ScArrowLoader,
} from '../../styled'
import {
Label,
Link,
@ -71,7 +72,6 @@ const Registration = () => {
<Logo />
<Form onSubmit={handleSubmit}>
<BlockTitle t='step_title_registration' />
<InputGroup>
<Input
type='email'
@ -131,7 +131,11 @@ const Registration = () => {
</CheckboxWrapper>
<ButtonsBlock>
<ButtonSolid disabled={isSubmitDisabled} type='submit' id='auth_register'>
<ButtonSolid
disabled={isSubmitDisabled}
type='submit'
id='auth_register'
>
{
isFetching
? <ScArrowLoader />

@ -11,6 +11,7 @@ export const lexics = {
error_accept_cookies: 17268,
error_email_already_exist: 18253,
error_email_already_in_use: 11156,
error_email_field_required: 20102,
error_empty_email: 2498,
error_empty_password: 2499,
error_failed_to_send_email: 15902,
@ -18,10 +19,12 @@ export const lexics = {
error_invalid_email_or_password: 15774,
error_invalid_platform: 15925,
error_missing_required_argument: 15921,
error_no_more_than_one_email_per_minute: 20093,
error_passwords_missmatch: 15841,
error_simple_password: 12940,
error_unsupported_response_type: 15922,
error_user_already_created: 15926,
error_user_is_already_verified: 20092,
error_user_not_confirm: 16069,
error_user_not_found: 15956,
error_user_not_found_recovery: 1417,

@ -0,0 +1,57 @@
import type { ClientIds } from 'config/clients/types'
import { getApiUrl } from 'features/AuthServiceApp/config/routes'
const errorLexics = {
8: 'error_failed_to_send_email',
15: 'error_email_field_required',
18: 'error_user_is_already_verified',
19: 'error_no_more_than_one_email_per_minute',
}
type FailedResponse = {
error: {
code: keyof typeof errorLexics,
message?: string,
},
ok: false,
}
type SuccessResponse = {
ok: true,
}
export type UrlParams = {
client_id: ClientIds,
lang?: string,
nonce?: string,
redirect_uri: string,
response_mode: string,
response_type: string,
scope?: string,
state?: string,
}
type TResendConfirmation = {
email: string,
urlParams: UrlParams,
}
export const resendConfirmation = async ({
email,
urlParams,
} : TResendConfirmation) => {
const url = getApiUrl('/repeat_confirm_email')
const init: RequestInit = {
body: new URLSearchParams({
email,
...urlParams,
}),
method: 'POST',
}
const response = await fetch(url, init)
const body: SuccessResponse | FailedResponse = await response.json()
if (body.ok) return Promise.resolve()
return Promise.reject(errorLexics[body.error.code])
}
Loading…
Cancel
Save