feat: implement login

This commit is contained in:
caturbgs 2021-12-09 23:00:56 +07:00
parent b346e1fdbd
commit 84d3085c0c
8 changed files with 124 additions and 152 deletions

View File

@ -1,5 +1,5 @@
export const appConfig = { export const appConfig = {
apiUrl: 'http://localhost:3222/v1' apiUrl: 'https://ppob-backend.k3s.bangun-kreatif.com/v1'
}; };
//export default appConfig; //export default appConfig;

View File

@ -1,7 +1,7 @@
import React, {useState} from "react"; import React, {useState} from "react";
import {Button, Drawer, Layout, Menu, Popover, Typography,} from "antd"; import {Button, Drawer, Layout, Menu, Popover, Typography,} from "antd";
import {MenuList} from "./MenuList"; import {MenuList} from "./MenuList";
import {Link} from "react-router-dom"; import {Link, useHistory} from "react-router-dom";
import {CalendarOutlined, HomeOutlined, MenuOutlined, UserOutlined,} from "@ant-design/icons"; import {CalendarOutlined, HomeOutlined, MenuOutlined, UserOutlined,} from "@ant-design/icons";
import {AppRoute} from "../../routes/app"; import {AppRoute} from "../../routes/app";
import {useStore} from "../../utils/useStore"; import {useStore} from "../../utils/useStore";
@ -12,6 +12,7 @@ const {Text, Paragraph} = Typography;
const {Header, Content, Sider} = Layout; const {Header, Content, Sider} = Layout;
export const DesktopLayout = observer(() => { export const DesktopLayout = observer(() => {
let history = useHistory();
const xl = useMediaQuery({minWidth: 1024}); const xl = useMediaQuery({minWidth: 1024});
const store = useStore(); const store = useStore();
const [clicked, setClicked] = useState(false); const [clicked, setClicked] = useState(false);
@ -268,8 +269,8 @@ export const DesktopLayout = observer(() => {
</Menu.Item> </Menu.Item>
<Menu.Item <Menu.Item
onClick={() => { onClick={() => {
// store.authentication.logout(); store.authentication.logout();
// return history.push("/login"); history.push("/login");
}} }}
> >
<span>Sign out</span> <span>Sign out</span>
@ -278,10 +279,10 @@ export const DesktopLayout = observer(() => {
} }
title={ title={
<Text> <Text>
{/*{store.user.data.email}{" "}*/} {store.user.data.email}{" "}
{/*<Paragraph style={{fontWeight: 400}} type={"secondary-dark"}>*/} <Paragraph style={{fontWeight: 400}} type={"secondary-dark"}>
{/* {store.authentication.userData.full_name}*/} {store.authentication.userData.email}
{/*</Paragraph>*/} </Paragraph>
</Text> </Text>
} }
trigger="click" trigger="click"
@ -359,8 +360,8 @@ export const DesktopLayout = observer(() => {
</Menu.Item> </Menu.Item>
<Menu.Item <Menu.Item
onClick={() => { onClick={() => {
// store.authentication.logout(); store.authentication.logout();
// return history.push("/login"); history.push("/login");
}} }}
> >
<span>Sign out</span> <span>Sign out</span>

View File

@ -1,31 +1,32 @@
import React, {useState} from "react"; import React from "react";
import {observer} from 'mobx-react-lite'; import {observer} from 'mobx-react-lite';
import {useStore} from "../../utils/useStore"; import {useStore} from "../../utils/useStore";
import {Button, Card, Checkbox, Col, Form, Input, Row, Typography} from 'antd'; import {Button, Card, Col, Form, Input, message, Row, Typography} from 'antd';
import {LockOutlined, UserOutlined} from '@ant-design/icons';
import {useHistory} from "react-router-dom"; import {useHistory} from "react-router-dom";
export const Login = observer(() => { export const Login = observer(() => {
const store = useStore(); const store = useStore();
const [loading, setLoading] = useState(false);
let history = useHistory(); let history = useHistory();
const [form] = Form.useForm();
const onFinish = values => { const handleLogin = async (params) => {
console.log('Received values of form: ', values); try {
enterLoading(values).then(res => { await store.authentication.login({
console.log(res, "awasaa"); username: params.username,
}).catch((error) => { password: params.password,
console.log({error}, "awasaa error");
}); });
}; history.push('/app/home');
} catch (e) {
if (e.response?.body?.message) {
message.error(e.response.body.message);
return;
}
message.error(e.message);
}
}
const enterLoading = async (props) => { return (
// store.setInitialToken("ayayay", "clap"); <div style={{width: '100vw', display: 'flex', justifyContent: 'center'}}>
return history.push("/app/page_example_1");
};
return <div style={{width: '100vw', display: 'flex', justifyContent: 'center'}}>
<Row justify={'center'}> <Row justify={'center'}>
<Col> <Col>
<div style={{ <div style={{
@ -57,83 +58,28 @@ export const Login = observer(() => {
title={'Sign in to your account'} title={'Sign in to your account'}
> >
<Form <Form
layout={'vertical'} layout={"vertical"}
name="normal_login" form={form}
className="login-form" onFinish={handleLogin}
onFinish={onFinish} className={"w-9/12"}
> >
<Form.Item <Form.Item label="Username" name="username"
label="Email" rules={[{required: true, message: 'Please input your username!'}]}>
name="email" <Input/>
size={'large'}
rules={[{required: false, message: 'Please input your Username!'}]}
>
<Input
prefix={<UserOutlined className="site-form-item-icon"/>}
type="text"
placeholder="Email"/>
</Form.Item> </Form.Item>
<Form.Item label="Password" name="password"
<Form.Item rules={[{required: true, message: 'Please input your password!'}]}>
style={{ <Input.Password/>
marginBottom: 0,
}}
label="Password"
name="password"
size={'large'}
rules={[{required: false, message: 'Please input your Password!'}]}
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon"/>}
type="password"
placeholder="Password"
/>
</Form.Item>
<Form.Item
style={{
marginTop: 0,
marginBottom: 20,
padding: 0
}}
// label="Password"
name="forgot-password"
size={'small'}
rules={[{required: false, message: 'Please input your Password!'}]}
>
<a className="login-form-forgot" href="">
Forgot password
</a>
</Form.Item>
<Form.Item
style={{
marginBottom: 5,
textAlign: 'left'
}}>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>Remember me</Checkbox>
</Form.Item>
</Form.Item>
<Form.Item
style={{
marginBottom: 0,
}}>
<Button type="primary"
block
loading={loading}
htmlType="submit"
size={'large'}
onSubmit={enterLoading}
className="login-form-button">
Sign In
</Button>
</Form.Item> </Form.Item>
<div className={"flex flex-row justify-between content-center"}>
<Button type="primary" htmlType="submit"
loading={store.authentication.isLoginLoading}>Submit</Button>
</div>
</Form> </Form>
</Card> </Card>
</div> </div>
</Col> </Col>
</Row> </Row>
</div>
</div>; );
}); });

View File

@ -2,15 +2,16 @@ import {Redirect, Route, Switch} from "react-router-dom";
import {Login} from "../pages/Login/Login"; import {Login} from "../pages/Login/Login";
import {PublicRoute} from "../component/PublicRoute"; import {PublicRoute} from "../component/PublicRoute";
import {App} from "../pages/App/App"; import {App} from "../pages/App/App";
import {PrivateRoute} from "../component/PrivateRoute";
export const MainRoutes = (props) => { export const MainRoutes = (props) => {
return ( return (
<Switch> <Switch>
<Route path="/" exact> <Route path="/" exact>
<Redirect to={"/app/home"}/> <Redirect to={"/login"}/>
</Route> </Route>
<PublicRoute restricted={true} component={Login} path="/login" exact/> <PublicRoute restricted={true} component={Login} path="/login" exact/>
<PublicRoute component={App} path="/app"/> <PrivateRoute component={App} path="/app"/>
</Switch> </Switch>
); );
}; };

View File

@ -1,27 +1,63 @@
import {makeAutoObservable} from "mobx"; import {makeAutoObservable, runInAction} from "mobx";
import {TokenUtil} from "../utils/token";
import {http} from "../utils/http";
export class Authentication { export class Authentication {
isLoggedIn = false;
isLoginLoading = false;
ctx; ctx;
accessToken = ''; accessToken = '';
refreshToken = '';
constructor(ctx) { constructor(ctx) {
this.ctx = ctx; this.ctx = ctx;
makeAutoObservable(this); makeAutoObservable(this);
} }
get isLoggedIn() { get isLoggedIn() {
return !!this.refreshToken; return !!this.accessToken;
} }
setInitialToken(accessToken, refreshToken) { get userData() {
this.setToken(accessToken, refreshToken); const defaultValue = {
role: '',
user_id: '',
username: '',
};
try {
return JSON.parse(atob(this.accessToken.split('.')[1]));
} catch (err) {
return defaultValue;
}
} }
setToken(accessToken, refreshToken) { async login({username, password}) {
this.accessToken = accessToken; runInAction(() => {
this.refreshToken = refreshToken; this.isLoginLoading = true;
});
try {
const result = await http.post('/auth/login').send({username, password});
TokenUtil.setAccessToken(result.body.access_token);
TokenUtil.persistToken();
runInAction(() => {
this.isLoginLoading = false;
this.isLoggedIn = true;
});
} catch (e) {
runInAction(() => {
this.isLoginLoading = false;
});
console.error(e);
throw e;
}
}
logout() {
TokenUtil.clearAccessToken();
TokenUtil.persistToken();
this.isLoggedIn = false;
} }
} }

View File

@ -4,6 +4,7 @@ import {User} from "./user";
import {Membership} from "./membership"; import {Membership} from "./membership";
import {Product} from "./product"; import {Product} from "./product";
import {Categories} from "./categories"; import {Categories} from "./categories";
import {TokenUtil} from "../utils/token";
export class Store { export class Store {
ui = new UI(this); ui = new UI(this);
@ -14,5 +15,9 @@ export class Store {
categories = new Categories(this); categories = new Categories(this);
constructor() { constructor() {
TokenUtil.loadToken();
if (TokenUtil.accessToken) {
this.authentication.isLoggedIn = true;
}
} }
} }

View File

@ -6,7 +6,7 @@ export class User {
@action @action
async getData() { async getData() {
this.data = (await http.get('/product')).body.data; this.data = (await http.get('/user')).body.data;
} }
} }

View File

@ -4,15 +4,10 @@ export class TokenUtil {
static loadToken() { static loadToken() {
const accessToken = localStorage.getItem('access_token'); const accessToken = localStorage.getItem('access_token');
const refreshToken = localStorage.getItem('refresh_token');
if (accessToken) { if (accessToken) {
TokenUtil.setAccessToken(accessToken); TokenUtil.setAccessToken(accessToken);
} }
if (refreshToken) {
TokenUtil.setRefreshToken(refreshToken);
}
} }
static persistToken() { static persistToken() {
@ -22,25 +17,13 @@ export class TokenUtil {
localStorage.removeItem('access_token'); localStorage.removeItem('access_token');
} }
if (TokenUtil.refreshToken != null) {
localStorage.setItem('refresh_token', TokenUtil.refreshToken);
} else {
localStorage.removeItem('refresh_token');
}
} }
static setAccessToken(accessToken) { static setAccessToken(accessToken) {
TokenUtil.accessToken = accessToken; TokenUtil.accessToken = accessToken;
} }
static setRefreshToken(refreshToken) {
TokenUtil.refreshToken = refreshToken;
}
static clearAccessToken() { static clearAccessToken() {
TokenUtil.accessToken = null; TokenUtil.accessToken = null;
} }
static clearRefreshToken() {
TokenUtil.accessToken = null;
}
} }