Ott 106 login (#19)

keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 6 years ago committed by GitHub
parent 332249e29d
commit 714de076b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/config/pages.tsx
  2. 1
      src/config/procedures.tsx
  3. 20
      src/features/App/AuthenticatedApp.tsx
  4. 25
      src/features/App/UnauthenticatedApp.tsx
  5. 44
      src/features/App/index.tsx
  6. 30
      src/features/AuthStore/hooks/useLogin.tsx
  7. 26
      src/features/AuthStore/hooks/useLogout.tsx
  8. 23
      src/features/AuthStore/hooks/useRegister.tsx
  9. 43
      src/features/AuthStore/index.tsx
  10. 14
      src/features/GlobalStores/index.tsx
  11. 33
      src/features/HomePage/index.tsx
  12. 26
      src/features/Login/hooks.tsx
  13. 26
      src/features/Login/index.tsx
  14. 18
      src/features/Register/components/RegistrationStep/hooks/useForm.tsx
  15. 27
      src/features/Register/index.tsx
  16. 4
      src/helpers/callApi/getRequestConfig.tsx
  17. 1
      src/helpers/callApi/loadIdToken.tsx
  18. 1
      src/helpers/index.tsx
  19. 13
      src/helpers/token/index.tsx
  20. 52
      src/requests/login.tsx

@ -1,4 +1,5 @@
export const PAGES = {
home: '/home',
login: '/login',
register: '/register',
}

@ -1,4 +1,5 @@
export const PROCEDURES = {
auth_user: 'auth_user',
create_user: 'create_user',
get_cities: 'get_cities',
lst_c_country: 'lst_c_country',

@ -0,0 +1,20 @@
import React from 'react'
import {
Route,
Redirect,
Switch,
} from 'react-router-dom'
import { PAGES } from 'config'
import { HomePage } from 'features/HomePage'
export const AuthenticatedApp = () => (
<Switch>
<Route path={PAGES.home}>
<HomePage />
</Route>
<Redirect to={PAGES.home} />
</Switch>
)

@ -0,0 +1,25 @@
import React from 'react'
import {
Route,
Redirect,
Switch,
} from 'react-router-dom'
import { PAGES } from 'config'
import { Login } from 'features/Login'
import { Register } from 'features/Register'
export const UnauthenticatedApp = () => (
<Switch>
<Route path={PAGES.login}>
<Login />
</Route>
<Route path={PAGES.register}>
<Register />
</Route>
<Redirect to={PAGES.login} />
</Switch>
)

@ -1,36 +1,38 @@
import React from 'react'
import {
Router,
Route,
Redirect,
Switch,
} from 'react-router-dom'
import { Router } from 'react-router-dom'
import { createBrowserHistory } from 'history'
import { PAGES } from 'config'
import { GlobalStores } from 'features/GlobalStores'
import { useAuthStore } from 'features/AuthStore'
import { Background } from 'features/Background'
import { GlobalStyles } from 'features/GlobalStyles'
import { Theme } from 'features/Theme'
import { Login } from 'features/Login'
import { Register } from 'features/Register'
import { AuthenticatedApp } from './AuthenticatedApp'
import { UnauthenticatedApp } from './UnauthenticatedApp'
const history = createBrowserHistory()
const Main = () => {
const { token } = useAuthStore()
return (
<Background>
{
token
? <AuthenticatedApp />
: <UnauthenticatedApp />
}
</Background>
)
}
export const App = () => (
<Router history={history}>
<Theme>
<GlobalStyles />
<Switch>
<Route path={PAGES.login}>
<Login />
</Route>
<Route path={PAGES.register}>
<Register />
</Route>
<Redirect to={PAGES.login} />
</Switch>
<GlobalStores>
<Main />
</GlobalStores>
</Theme>
</Router>
)

@ -0,0 +1,30 @@
import { useHistory } from 'react-router-dom'
import { PAGES } from 'config'
import { login } from 'requests'
import { writeToken } from 'helpers'
type LoginArgs = Parameters<typeof login>[0]
type Args = {
setToken: (token: string | null) => void,
}
export const useLogin = ({ setToken }: Args) => {
const history = useHistory()
const onSuccess = (token: string) => {
writeToken(token)
setToken(token)
history.replace(PAGES.home)
}
const onError = (message: string) => {
// eslint-disable-next-line no-alert
window.alert(message)
}
return async ({ email, password }: LoginArgs) => (
login({ email, password }).then(onSuccess, onError)
)
}

@ -0,0 +1,26 @@
import { useHistory } from 'react-router-dom'
import { PAGES } from 'config'
import { removeToken } from 'helpers'
// import { logout } from 'requests'
// временная заглушка запроса
const logout = () => Promise.resolve()
type Args = {
setToken: (token: string | null) => void,
}
export const useLogout = ({ setToken }: Args) => {
const history = useHistory()
const onSuccess = () => {
removeToken()
setToken(null)
history.replace(PAGES.login)
}
return async () => (
logout().then(onSuccess)
)
}

@ -0,0 +1,23 @@
import { useHistory } from 'react-router-dom'
import { PAGES } from 'config'
import { register } from 'requests'
type Args = Parameters<typeof register>[0]
export const useRegister = () => {
const history = useHistory()
const goToLoginPage = () => {
history.replace(PAGES.login)
}
const showError = (message: string) => {
// eslint-disable-next-line no-alert
window.alert(message)
}
return async (args: Args) => (
register(args).then(goToLoginPage, showError)
)
}

@ -0,0 +1,43 @@
import type { ReactNode } from 'react'
import React, {
createContext,
useContext,
useState,
} from 'react'
import { readToken } from 'helpers'
import { useLogin } from './hooks/useLogin'
import { useLogout } from './hooks/useLogout'
import { useRegister } from './hooks/useRegister'
type Auth = {
login: ReturnType<typeof useLogin>,
logout: ReturnType<typeof useLogout>,
register: ReturnType<typeof useRegister>,
token: string | null,
}
const AuthContext = createContext({} as Auth)
type Props = {
children: ReactNode,
}
export const AuthStore = ({ children }: Props) => {
const [token, setToken] = useState(readToken())
const login = useLogin({ setToken })
const logout = useLogout({ setToken })
const register = useRegister()
const auth = {
login,
logout,
register,
token,
}
return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>
}
export const useAuthStore = () => useContext(AuthContext)

@ -0,0 +1,14 @@
import React, { ReactNode } from 'react'
import { AuthStore } from 'features/AuthStore'
type Props = {
children: ReactNode,
}
// аутентификация, лексики и другие глобальные сторы
export const GlobalStores = ({ children }: Props) => (
<AuthStore>
{children}
</AuthStore>
)

@ -0,0 +1,33 @@
import React from 'react'
import styled from 'styled-components/macro'
import { Logo } from 'features/Logo'
import { CenterBlock } from 'features/Login/styled'
import { useAuthStore } from 'features/AuthStore'
// временные компоненты
const TempContainer = styled.div`
margin-top: 50px;
color: white;
font-size: 20px;
display: flex;
flex-direction: column;
`
const TempPageTitle = styled.span`
margin: 20px 0;
`
export const HomePage = () => {
const { logout } = useAuthStore()
return (
<CenterBlock>
<Logo />
<TempContainer>
<TempPageTitle>HOME PAGE</TempPageTitle>
<button type='button' onClick={logout}>Logout</button>
</TempContainer>
</CenterBlock>
)
}

@ -0,0 +1,26 @@
import type { FormEvent } from 'react'
import trim from 'lodash/trim'
import { useAuthStore } from 'features/AuthStore'
import { formIds } from 'features/Register/components/RegistrationStep/config'
const readFormValue = (event: FormEvent<HTMLFormElement>) => (
(fieldName: string) => trim(event.currentTarget[fieldName]?.value)
)
export const useForm = () => {
const { login } = useAuthStore()
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault()
const readFieldValue = readFormValue(event)
const email = readFieldValue(formIds.email)
const password = readFieldValue(formIds.password)
login({ email, password })
}
return { handleSubmit }
}

@ -2,13 +2,11 @@ import React from 'react'
import { PAGES } from 'config'
import { Background } from 'features/Background'
import { Logo } from 'features/Logo'
import {
Input,
ButtonSolid,
} from 'features/Common'
import { Input, ButtonSolid } from 'features/Common'
import { formIds } from 'features/Register/components/RegistrationStep/config'
import { useForm } from './hooks'
import {
BlockTitle,
CenterBlock,
@ -19,35 +17,37 @@ import {
const labelWidth = 60
export const Login = () => (
<Background>
export const Login = () => {
const { handleSubmit } = useForm()
return (
<CenterBlock>
<Logo />
<Form>
<Form onSubmit={handleSubmit}>
<BlockTitle>Авторизация</BlockTitle>
<Input
required
id='email'
id={formIds.email}
type='email'
label='Логин'
labelWidth={labelWidth}
/>
<Input
required
id='password'
id={formIds.password}
type='password'
label='Пароль'
labelWidth={labelWidth}
/>
<ButtonsBlock>
<ButtonSolid>Войти</ButtonSolid>
<ButtonSolid type='submit'>Войти</ButtonSolid>
<RegisterButton to={PAGES.register}>
Зарегистрироваться
</RegisterButton>
</ButtonsBlock>
</Form>
</CenterBlock>
</Background>
)
)
}

@ -1,12 +1,9 @@
import type { FormEvent } from 'react'
import { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import trim from 'lodash/trim'
import { PAGES } from 'config'
import { register } from 'requests'
import { useAuthStore } from 'features/AuthStore'
import { isValidEmail } from 'features/Register/helpers/isValidEmail'
import { formIds } from '../config'
@ -18,7 +15,7 @@ const readFormValue = (event: FormEvent<HTMLFormElement>) => (
)
export const useForm = () => {
const history = useHistory()
const { register } = useAuthStore()
const {
countries,
onCountrySelect,
@ -44,15 +41,6 @@ export const useForm = () => {
resetCities,
])
const goToLoginPage = () => {
history.replace(PAGES.login)
}
const showError = (message: string) => {
// eslint-disable-next-line no-alert
window.alert(message)
}
const getCityParams = () => {
if (selectedCity) return { cityId: selectedCity.id }
return { city: cityQuery }
@ -86,7 +74,7 @@ export const useForm = () => {
phone,
postalCode,
region,
}).then(goToLoginPage, showError)
})
}
}

@ -3,7 +3,6 @@ import { Route } from 'react-router'
import { PAGES } from 'config'
import { Background } from 'features/Background'
import { Logo } from 'features/Logo'
import { CenterBlock } from 'features/Login/styled'
@ -12,18 +11,16 @@ import { CardStep } from './components/CardStep'
import { SubscriptionStep } from './components/SubscriptionsStep'
export const Register = () => (
<Background>
<CenterBlock>
<Logo />
<Route exact path={`${PAGES.register}`}>
<RegistrationStep />
</Route>
<Route exact path={`${PAGES.register}/card`}>
<CardStep />
</Route>
<Route exact path={`${PAGES.register}/subscriptions`}>
<SubscriptionStep />
</Route>
</CenterBlock>
</Background>
<CenterBlock>
<Logo />
<Route exact path={`${PAGES.register}`}>
<RegistrationStep />
</Route>
<Route exact path={`${PAGES.register}/card`}>
<CardStep />
</Route>
<Route exact path={`${PAGES.register}/subscriptions`}>
<SubscriptionStep />
</Route>
</CenterBlock>
)

@ -1,6 +1,6 @@
import { AUTH_KEYS } from 'config'
import { readToken } from 'helpers'
import { loadIdToken } from './loadIdToken'
import { TRequestConfig } from './types'
export const getRequestConfig = (
@ -19,7 +19,7 @@ export const getRequestConfig = (
requestConfig.headers.set('Content-Type', 'application/json')
}
const token = loadIdToken()
const token = readToken()
if (token) {
requestConfig.headers.set(AUTH_KEYS.headerToken, token)

@ -1 +0,0 @@
export const loadIdToken = () => localStorage.getItem('id_token')

@ -1,2 +1,3 @@
export * from './callApi'
export * from './callApi/getResponseData'
export * from './token'

@ -0,0 +1,13 @@
const TOKEN_KEY = 'token'
export const readToken = () => (
localStorage.getItem(TOKEN_KEY)
)
export const writeToken = (token: string) => (
localStorage.setItem(TOKEN_KEY, token)
)
export const removeToken = () => (
localStorage.removeItem(TOKEN_KEY)
)

@ -1 +1,51 @@
export const login = () => {}
import { DATA_URL, PROCEDURES } from 'config'
import { callApi, writeToken } from 'helpers'
const proc = PROCEDURES.auth_user
const statusCodes = {
ACCOUNT_EXPIRED: 5,
EMAIL_NOT_FOUND: 2,
INVALID_CREDENTIALS: 3,
SUCCESS: 1,
USER_REMOVED_OR_BLOCKED: 4,
} as const
type StatusCodes = typeof statusCodes[keyof typeof statusCodes]
type Response = {
_p_status: StatusCodes,
_p_token: string,
}
type Args = {
email: string,
password: string,
}
export const login = async ({
email,
password,
}: Args) => {
const config = {
body: {
params: {
_p_email: email,
_p_password: password,
},
proc,
},
}
const response: Response = await callApi({
config,
url: DATA_URL,
})
if (response._p_status === statusCodes.SUCCESS) {
writeToken(response._p_token)
return Promise.resolve(response._p_token)
}
return Promise.reject(response._p_status)
}

Loading…
Cancel
Save