feat: implement login
This commit is contained in:
parent
b20835257e
commit
62dfdbe40a
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -1,51 +1,52 @@
|
||||||
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");
|
<Row justify={'center'}>
|
||||||
};
|
<Col>
|
||||||
|
<div style={{
|
||||||
return <div style={{width: '100vw', display: 'flex', justifyContent: 'center'}}>
|
display: 'flex',
|
||||||
<Row justify={'center'}>
|
justifyContent: 'flex-start',
|
||||||
<Col>
|
marginTop: '5vh',
|
||||||
<div style={{
|
flexDirection: 'column',
|
||||||
display: 'flex',
|
alignItems: 'center',
|
||||||
justifyContent: 'flex-start',
|
}}>
|
||||||
marginTop: '5vh',
|
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'stretch'}}>
|
||||||
flexDirection: 'column',
|
<Typography.Paragraph
|
||||||
alignItems: 'center',
|
style={{
|
||||||
}}>
|
margin: 0,
|
||||||
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'stretch'}}>
|
padding: 0,
|
||||||
<Typography.Paragraph
|
fontSize: 20,
|
||||||
style={{
|
marginLeft: 5,
|
||||||
margin: 0,
|
fontWeight: 600,
|
||||||
padding: 0,
|
color: "#413d3e",
|
||||||
fontSize: 20,
|
}}
|
||||||
marginLeft: 5,
|
>
|
||||||
fontWeight: 600,
|
|
||||||
color: "#413d3e",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Boilerplate
|
Boilerplate
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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>;
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user