mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: stores
This commit is contained in:
parent
2b655ddd09
commit
73841e8f68
73
package-lock.json
generated
73
package-lock.json
generated
@ -2819,6 +2819,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/history": {
|
||||
"version": "4.7.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz",
|
||||
"integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/html-minifier-terser": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz",
|
||||
@ -2845,6 +2851,12 @@
|
||||
"@types/istanbul-lib-report": "*"
|
||||
}
|
||||
},
|
||||
"@types/js-cookie": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
|
||||
"integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
|
||||
@ -2924,6 +2936,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/react-helmet": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.2.tgz",
|
||||
"integrity": "sha512-dcfAZNlWb5JYFbO9CGfrPWLJAyFcT6UeR3u35eBbv8liY2Rg4K7fM1G5+HnwVgot+C+kVwXAZ8pLEn2jsMfTDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-router": {
|
||||
"version": "5.1.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.16.tgz",
|
||||
"integrity": "sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/history": "*",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-router-dom": {
|
||||
"version": "5.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz",
|
||||
"integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/history": "*",
|
||||
"@types/react": "*",
|
||||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"@types/resolve": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
|
||||
@ -3763,6 +3805,14 @@
|
||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.2.tgz",
|
||||
"integrity": "sha512-5LMaDRWm8ZFPAEdzTYmgjjEdj1YnQcpfrVajO/sn/LhbpGp0Y0H64c2hLZI1gRMxfA+w1S71Uc/nHaOXgcCvGg=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||
@ -9493,6 +9543,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.0.tgz",
|
||||
"integrity": "sha512-oUbbplKuH07/XX2YD2+Q+GMiPpnVXaRz8npE7suhBH9QEkJe2W7mQ6rwuMXHue3fpfcftQwzgyvGzIHyfCSngQ=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -10121,6 +10176,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"mobx": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mobx/-/mobx-6.3.2.tgz",
|
||||
"integrity": "sha512-xGPM9dIE1qkK9Nrhevp0gzpsmELKU4MFUJRORW/jqxVFIHHWIoQrjDjL8vkwoJYY3C2CeVJqgvl38hgKTalTWg=="
|
||||
},
|
||||
"mobx-react": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-7.2.0.tgz",
|
||||
"integrity": "sha512-KHUjZ3HBmZlNnPd1M82jcdVsQRDlfym38zJhZEs33VxyVQTvL77hODCArq6+C1P1k/6erEeo2R7rpE7ZeOL7dg==",
|
||||
"requires": {
|
||||
"mobx-react-lite": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"mobx-react-lite": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.2.0.tgz",
|
||||
"integrity": "sha512-q5+UHIqYCOpBoFm/PElDuOhbcatvTllgRp3M1s+Hp5j0Z6XNgDbgqxawJ0ZAUEyKM8X1zs70PCuhAIzX1f4Q/g=="
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
|
||||
@ -12,7 +12,11 @@
|
||||
"@types/jest": "^25.0.0",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/react-dom": "^16.9.0",
|
||||
"axios": "^0.21.1",
|
||||
"framer-motion": "^4.0.0",
|
||||
"js-cookie": "^3.0.0",
|
||||
"mobx": "^6.3.2",
|
||||
"mobx-react": "^7.2.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
@ -47,6 +51,9 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.14.13"
|
||||
"@types/js-cookie": "^2.2.7",
|
||||
"@types/react": "^16.14.13",
|
||||
"@types/react-helmet": "^6.1.2",
|
||||
"@types/react-router-dom": "^5.1.8"
|
||||
}
|
||||
}
|
||||
|
||||
25
src/App.tsx
25
src/App.tsx
@ -1,14 +1,21 @@
|
||||
import * as React from "react";
|
||||
import { ChakraProvider, Box, Text, Grid, theme } from "@chakra-ui/react";
|
||||
import { ColorModeSwitcher } from "./ColorModeSwitcher";
|
||||
import * as React from 'react';
|
||||
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||
import PrivateRoute from './components/PrivateRoute/PrivateRoute';
|
||||
import { ChakraProvider, theme } from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
import MainPage from './pages/main';
|
||||
import AuthPage from './pages/auth';
|
||||
|
||||
export const App = () => (
|
||||
<ChakraProvider theme={theme}>
|
||||
<Box textAlign="center" fontSize="xl">
|
||||
<Grid minH="100vh" p={3}>
|
||||
<ColorModeSwitcher justifySelf="flex-end" />
|
||||
<Text>Appliction</Text>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Router>
|
||||
<Switch>
|
||||
<PrivateRoute exact path='/' component={MainPage} title='Main' />
|
||||
<Route path='/auth' component={AuthPage} />
|
||||
</Switch>
|
||||
</Router>
|
||||
</ChakraProvider>
|
||||
);
|
||||
|
||||
10
src/axios/index.ts
Normal file
10
src/axios/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import axios from 'axios';
|
||||
import { API_BASE_URL } from '../constants';
|
||||
|
||||
/**
|
||||
* Create axios config
|
||||
*/
|
||||
export default axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
responseType: 'json',
|
||||
});
|
||||
104
src/components/Auth/Auth.tsx
Normal file
104
src/components/Auth/Auth.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
import React, { useState } from 'react';
|
||||
import { MdAccountCircle, MdVpnKey } from 'react-icons/md';
|
||||
import {
|
||||
Flex,
|
||||
Box,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
InputGroup,
|
||||
Input,
|
||||
InputLeftElement,
|
||||
Button,
|
||||
Icon,
|
||||
} from '@chakra-ui/react';
|
||||
import { useRootStore } from '../../hooks/useRootStore';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
type LoginDataInput = {
|
||||
login: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Authorize user through a form.
|
||||
*/
|
||||
const Auth: React.FC = () => {
|
||||
const [loginData, setLoginData] = useState<LoginDataInput>({
|
||||
login: '',
|
||||
password: '',
|
||||
});
|
||||
const { authStore } = useRootStore();
|
||||
const history = useHistory();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
const { login, password } = loginData;
|
||||
await authStore.login(login, password);
|
||||
history.push('/');
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex minHeight='100vh' align='center' justifyContent='center'>
|
||||
<Box
|
||||
p={8}
|
||||
my={40}
|
||||
width='full'
|
||||
maxWidth='450px'
|
||||
borderWidth={1}
|
||||
borderRadius={8}>
|
||||
<Box textAlign='center'>
|
||||
<Flex justifyContent='center'>
|
||||
{/* <LogoIcon viewBox='0 0 24 24' boxSize={'64px'} fill='blue.600' /> */}
|
||||
</Flex>
|
||||
</Box>
|
||||
<Box my='30px'>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<FormControl isRequired={true}>
|
||||
<FormLabel>Login</FormLabel>
|
||||
<InputGroup>
|
||||
<InputLeftElement children={<Icon as={MdAccountCircle} />} />
|
||||
<Input
|
||||
type='text'
|
||||
name='login'
|
||||
placeholder='email@mail.com'
|
||||
value={loginData.login}
|
||||
onChange={(e) =>
|
||||
setLoginData({ ...loginData, login: e.target.value })
|
||||
}
|
||||
/>
|
||||
</InputGroup>
|
||||
</FormControl>
|
||||
<FormControl mt={5} isRequired={true}>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<InputGroup>
|
||||
<InputLeftElement children={<Icon as={MdVpnKey} />} />
|
||||
<Input
|
||||
type='password'
|
||||
name='password'
|
||||
placeholder='********'
|
||||
value={loginData.password}
|
||||
onChange={(e) =>
|
||||
setLoginData({ ...loginData, password: e.target.value })
|
||||
}
|
||||
/>
|
||||
</InputGroup>
|
||||
</FormControl>
|
||||
<Button
|
||||
loadingText='Logging in...'
|
||||
type='submit'
|
||||
colorScheme='blue'
|
||||
variant='outline'
|
||||
width='full'
|
||||
mt={4}>
|
||||
Log in
|
||||
</Button>
|
||||
</form>
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(Auth);
|
||||
29
src/components/Layout/Layout.tsx
Normal file
29
src/components/Layout/Layout.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { Flex, Box } from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
*
|
||||
* Layout component
|
||||
* Сomponent for rendering the current page.
|
||||
*/
|
||||
const Layout: React.FC = ({ children }) => {
|
||||
return (
|
||||
<Flex minH='100vh' flexDirection='column'>
|
||||
<Box pl='18rem' mt='4rem' mb='4rem' flex='1 0 auto'>
|
||||
<Box
|
||||
as='main'
|
||||
mr='auto'
|
||||
ml='auto'
|
||||
maxW='85rem'
|
||||
pl={5}
|
||||
pr={5}
|
||||
pt='2rem'
|
||||
pb='2rem'>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
43
src/components/PrivateRoute/PrivateRoute.tsx
Normal file
43
src/components/PrivateRoute/PrivateRoute.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import Layout from '../Layout/Layout';
|
||||
import { Route, Redirect } from 'react-router-dom';
|
||||
import { IPrivateRouteProps } from '../../interfaces';
|
||||
import { useRootStore } from '../../hooks/useRootStore';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
/**
|
||||
* Checks if the user is loggedIn by reactive variable and if not,
|
||||
* then a redirect to "/auth" route.
|
||||
*/
|
||||
const PrivateRoute: React.FC<IPrivateRouteProps> = ({
|
||||
children,
|
||||
component: Component,
|
||||
title,
|
||||
...options
|
||||
}) => {
|
||||
const { authStore } = useRootStore();
|
||||
const isLoggedIn = authStore.isLoggedIn;
|
||||
|
||||
return (
|
||||
<Route
|
||||
{...options}
|
||||
render={(props) =>
|
||||
isLoggedIn ? (
|
||||
<Layout>
|
||||
<Helmet>
|
||||
<title>{title} • App </title>
|
||||
</Helmet>
|
||||
<Component {...props} title={title} />
|
||||
</Layout>
|
||||
) : (
|
||||
<Redirect
|
||||
to={{ pathname: '/auth', state: { from: props.location } }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(PrivateRoute);
|
||||
1
src/constants.ts
Normal file
1
src/constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const API_BASE_URL: string = 'http://localhost:3333/api';
|
||||
6
src/contexts/index.ts
Normal file
6
src/contexts/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import RootStore from '../stores/RootStore';
|
||||
|
||||
export const StoreContext = React.createContext<RootStore | undefined>(
|
||||
undefined
|
||||
);
|
||||
11
src/hooks/useRootStore.ts
Normal file
11
src/hooks/useRootStore.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { StoreContext } from '../contexts';
|
||||
|
||||
export const useRootStore = () => {
|
||||
const context = React.useContext(StoreContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useRootStore must be used within RootStoreProvider');
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
@ -1,15 +1,18 @@
|
||||
import { ColorModeScript } from "@chakra-ui/react";
|
||||
import * as React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { App } from "./App";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
import { ColorModeScript } from '@chakra-ui/react';
|
||||
import * as React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { App } from './App';
|
||||
import { RootStoreProvider } from './providers';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<>
|
||||
<ColorModeScript />
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
<RootStoreProvider>
|
||||
<App />
|
||||
</RootStoreProvider>
|
||||
</>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
|
||||
17
src/interfaces/index.ts
Normal file
17
src/interfaces/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import type { RouteProps } from 'react-router-dom';
|
||||
import type { RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
export interface IDataResult {
|
||||
data: any;
|
||||
message: string;
|
||||
status: number;
|
||||
}
|
||||
|
||||
export interface IPageProps extends RouteComponentProps {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface IPrivateRouteProps extends RouteProps {
|
||||
component: React.FC<any>;
|
||||
title?: string;
|
||||
}
|
||||
30
src/pages/auth.tsx
Normal file
30
src/pages/auth.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Auth from '../components/Auth/Auth';
|
||||
import { useRootStore } from '../hooks/useRootStore';
|
||||
import { IPageProps } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Auth page
|
||||
*/
|
||||
const AuthPage: React.FC<IPageProps> = () => {
|
||||
const { authStore } = useRootStore();
|
||||
const history = useHistory();
|
||||
|
||||
if (authStore.isLoggedIn) {
|
||||
history.push('/');
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Auth</title>
|
||||
</Helmet>
|
||||
<Auth />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(AuthPage);
|
||||
35
src/pages/main.tsx
Normal file
35
src/pages/main.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Heading,
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
Grid,
|
||||
} from '@chakra-ui/react';
|
||||
import { IPageProps } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Main page
|
||||
*/
|
||||
const MainPage: React.FC<IPageProps> = ({ title, history }) => {
|
||||
return (
|
||||
<>
|
||||
<Breadcrumb fontWeight='medium' fontSize='sm'>
|
||||
<BreadcrumbItem isCurrentPage>
|
||||
<BreadcrumbLink href='/'>{title}</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
<Box marginTop={10}>
|
||||
<Box>
|
||||
<Heading as='h1'>Main page</Heading>
|
||||
<Grid templateColumns='3fr 1fr' mt='25px'>
|
||||
...
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MainPage;
|
||||
13
src/providers/index.tsx
Normal file
13
src/providers/index.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import { StoreContext } from '../contexts';
|
||||
import RootStore from '../stores/RootStore';
|
||||
|
||||
let store: RootStore;
|
||||
|
||||
/**
|
||||
* Root store provider
|
||||
*/
|
||||
export const RootStoreProvider = ({ children }: { children: ReactNode }) => {
|
||||
const root = store ?? new RootStore();
|
||||
return <StoreContext.Provider value={root}>{children}</StoreContext.Provider>;
|
||||
};
|
||||
24
src/services/AuthService.ts
Normal file
24
src/services/AuthService.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import api from '../axios/index';
|
||||
import { IDataResult } from '../interfaces';
|
||||
|
||||
interface ILoginResult extends IDataResult {
|
||||
data: {
|
||||
token: string;
|
||||
type: string;
|
||||
expires_at: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default class AuthService {
|
||||
public async requestLogin(
|
||||
login: string,
|
||||
password: string
|
||||
): Promise<ILoginResult> {
|
||||
const result = await api.post('v1/auth/login', {
|
||||
login,
|
||||
password,
|
||||
});
|
||||
|
||||
return result.data;
|
||||
}
|
||||
}
|
||||
42
src/stores/AuthStore.ts
Normal file
42
src/stores/AuthStore.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { makeAutoObservable } from 'mobx';
|
||||
import Cookies from 'js-cookie';
|
||||
import AuthService from '../services/AuthService';
|
||||
import RootStore from './RootStore';
|
||||
|
||||
export default class AuthStore {
|
||||
public root: RootStore;
|
||||
|
||||
public token: string | null = null;
|
||||
|
||||
public isLoggedIn: boolean = !!Cookies.get('logged_in');
|
||||
|
||||
public authService: AuthService;
|
||||
|
||||
constructor(root: RootStore) {
|
||||
this.root = root;
|
||||
this.authService = new AuthService();
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
get getToken(): string | null {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public setIsLoggedIn(value: boolean) {
|
||||
this.isLoggedIn = value;
|
||||
}
|
||||
|
||||
public setToken(token: string) {
|
||||
Cookies.set('logged_in', 'true');
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public async login(login: string, password: string) {
|
||||
const result = await this.authService.requestLogin(login, password);
|
||||
|
||||
this.setIsLoggedIn(true);
|
||||
this.setToken(result.data.token);
|
||||
}
|
||||
|
||||
public logout() {}
|
||||
}
|
||||
9
src/stores/RootStore.ts
Normal file
9
src/stores/RootStore.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import AuthStore from './AuthStore';
|
||||
|
||||
export default class RootStore {
|
||||
public authStore: AuthStore;
|
||||
|
||||
constructor() {
|
||||
this.authStore = new AuthStore(this);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user