From d4703b97d3dee13efac0ddee7f91e7fe81bad94f Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Tue, 24 Aug 2021 12:58:13 +0300 Subject: [PATCH] feat: added typing for user result fetch & logout --- src/App.tsx | 23 ++++++++----------- src/components/Header/User/UserInfo.tsx | 3 +-- src/components/Layout/Layout.tsx | 8 +++---- src/components/PrivateRoute/PrivateRoute.tsx | 16 ++++++++----- src/interfaces/index.ts | 24 ++++++++++++++++++++ src/services/AuthService.ts | 22 +++++------------- src/services/UserService.ts | 3 ++- src/stores/AuthStore.ts | 5 ++-- src/stores/UserStore.ts | 17 +++++++++----- 9 files changed, 70 insertions(+), 51 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index fadae32..c0e305c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,22 +13,19 @@ import MessagesPage from './pages/messages'; import ProfilePage from './pages/profile'; import AuthPage from './pages/auth'; import NotFoundPage from './pages/404'; -import { ErrorBoundary } from 'react-error-boundary'; const App = () => { return ( - - - - - - - - - - - - + + + + + + + + + + ); }; diff --git a/src/components/Header/User/UserInfo.tsx b/src/components/Header/User/UserInfo.tsx index ab3da2f..cb82d59 100644 --- a/src/components/Header/User/UserInfo.tsx +++ b/src/components/Header/User/UserInfo.tsx @@ -11,14 +11,13 @@ import { Box, Avatar, Text, - Link, useToast, Skeleton, } from '@chakra-ui/react'; import { MdSettings, MdExitToApp } from 'react-icons/md'; import { observer } from 'mobx-react'; import { useRootStore } from '../../../hooks/useRootStore'; -import { useHistory } from 'react-router-dom'; +import { useHistory, Link } from 'react-router-dom'; const UserInfo: React.FC = () => { const { authStore, userStore } = useRootStore(); diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index 58423e6..56a5fc5 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -12,15 +12,13 @@ import { useErrorHandler } from 'react-error-boundary'; * Сomponent for rendering the current page. */ const Layout: React.FC = ({ children }) => { - const { authStore } = useRootStore(); + const { authStore, userStore } = useRootStore(); const handleError = useErrorHandler(); React.useEffect(() => { if (authStore.isLoggedIn) { - authStore.root.userStore.loadCurrentUserData().catch(error => { - if (error.response && error.response.status === 401) { - handleError(error); - } + userStore.loadCurrentUserData().catch(error => { + handleError(error); }); } }); diff --git a/src/components/PrivateRoute/PrivateRoute.tsx b/src/components/PrivateRoute/PrivateRoute.tsx index 17cd8fd..1617939 100644 --- a/src/components/PrivateRoute/PrivateRoute.tsx +++ b/src/components/PrivateRoute/PrivateRoute.tsx @@ -5,6 +5,8 @@ import { Route, Redirect } from 'react-router-dom'; import { IPrivateRouteProps } from '../../interfaces'; import { useRootStore } from '../../hooks/useRootStore'; import { observer } from 'mobx-react'; +import { ErrorBoundary } from 'react-error-boundary'; +import ErrorFallback from '../ErrorFallback'; /** * Checks if the user is loggedIn by reactive variable and if not, @@ -18,12 +20,14 @@ const PrivateRoute: React.FC = ({ children, component: Compo {...options} render={props => authStore.isLoggedIn ? ( - - - {title} • App - - - + + + + {title} • App + + + + ) : ( ) diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 4d2eee5..797ecc4 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -12,12 +12,36 @@ export interface IAppConfig { links: LinkType[]; } +export interface IUserRole { + id: number; + name: string; + slug: string; +} + export interface IDataResult { data: any; message: string; status: number; } +export interface ILoginResult extends IDataResult { + data: { + token: string; + type: string; + expires_at: string; + }; +} + +export interface IUserResult extends IDataResult { + data: { + id: string; + first_name: string; + last_name: string; + email: string; + roles: IUserRole[]; + }; +} + export interface IPageProps extends RouteComponentProps { title?: string; } diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index a653ba4..270f0f6 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -1,13 +1,5 @@ -import { IDataResult } from '../interfaces'; -import { AxiosInstance } from 'axios'; - -export interface ILoginResult extends IDataResult { - data: { - token: string; - type: string; - expires_at: string; - }; -} +import { IDataResult, ILoginResult } from '../interfaces'; +import { AxiosInstance, AxiosResponse } from 'axios'; export default class AuthService { public api: AxiosInstance; @@ -24,22 +16,20 @@ export default class AuthService { * @returns Login result */ public async requestLogin(login: string, password: string): Promise { - const result = await this.api.post('v1/auth/login', { + const result: AxiosResponse = await this.api.post('v1/auth/login', { login, password, }); - return result.data; } /** * Revoke token * - * @returns Logout result + * @returns Data result */ - public async requestLogout(): Promise { - const result = await this.api.post('v1/auth/logout'); - + public async requestLogout(): Promise { + const result: AxiosResponse = await this.api.post('v1/auth/logout'); return result.data; } } diff --git a/src/services/UserService.ts b/src/services/UserService.ts index f78f08c..c86eb3e 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -1,4 +1,5 @@ import { AxiosInstance } from 'axios'; +import { IUserResult } from '../interfaces'; export default class UserService { public api: AxiosInstance; @@ -12,7 +13,7 @@ export default class UserService { * * @returns User data */ - public async fetchMe(): Promise { + public async fetchMe(): Promise { const result = await this.api.get('v1/me'); return result.data; } diff --git a/src/stores/AuthStore.ts b/src/stores/AuthStore.ts index 7cee833..ec5c071 100644 --- a/src/stores/AuthStore.ts +++ b/src/stores/AuthStore.ts @@ -3,6 +3,7 @@ import Cookies from 'js-cookie'; import RootStore from './RootStore'; import AuthService from '../services/AuthService'; import { AxiosInstance } from 'axios'; +import { IDataResult, ILoginResult } from '../interfaces'; export default class AuthStore { public root: RootStore; @@ -27,7 +28,7 @@ export default class AuthStore { this.loading = value; } - public async login(login: string, password: string) { + public async login(login: string, password: string): Promise { try { this.setLoading(true); const result = await this.authService.requestLogin(login, password); @@ -43,7 +44,7 @@ export default class AuthStore { } } - public async logout() { + public async logout(): Promise { try { this.setLoading(true); const result = await this.authService.requestLogout(); diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts index 6928709..6fb9346 100644 --- a/src/stores/UserStore.ts +++ b/src/stores/UserStore.ts @@ -1,5 +1,6 @@ import { AxiosInstance } from 'axios'; import { autorun, makeAutoObservable } from 'mobx'; +import { IUserResult } from '../interfaces'; import UserService from '../services/UserService'; import RootStore from './RootStore'; @@ -25,13 +26,17 @@ export default class UserStore { makeAutoObservable(this); } - public async loadCurrentUserData(): Promise { - const result = await this.userService.fetchMe(); + public async loadCurrentUserData(): Promise { + try { + const result = await this.userService.fetchMe(); - autorun(() => { - this.me = result.data; - }); + autorun(() => { + this.me = result.data; + }); - return result; + return result; + } catch (error) { + throw error; + } } }