chore(api): login to app + save auth token
This commit is contained in:
parent
0661b7cf21
commit
5d2c3e4b6a
2
frontend/.gitignore
vendored
2
frontend/.gitignore
vendored
|
|
@ -17,7 +17,7 @@ out
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.eslintcache
|
.eslintcache
|
||||||
.idea
|
.idea
|
||||||
/.env
|
.env
|
||||||
/.env.local
|
/.env.local
|
||||||
/.env.development.local
|
/.env.development.local
|
||||||
/.env.test.local
|
/.env.test.local
|
||||||
|
|
|
||||||
3271
frontend/package-lock.json
generated
3271
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
BIN
frontend/public/assets/avatars/default-avatar.png
Normal file
BIN
frontend/public/assets/avatars/default-avatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -83,9 +83,9 @@ export const AuthProvider = (props) => {
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
const user = {
|
const user = {
|
||||||
id: '5e86809283e28b96d2d38537',
|
id: '5e86809283e28b96d2d38537',
|
||||||
avatar: '/assets/avatars/avatar-anika-visser.png',
|
avatar: '/assets/avatars/default-avatar.png',
|
||||||
name: 'Anika Visser',
|
name: 'Anika Visser',
|
||||||
email: 'anika.visser@devias.io'
|
email: 'anika.visser@devias.io',
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
@ -116,9 +116,9 @@ export const AuthProvider = (props) => {
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: '5e86809283e28b96d2d38537',
|
id: '5e86809283e28b96d2d38537',
|
||||||
avatar: '/assets/avatars/avatar-anika-visser.png',
|
avatar: '/assets/avatars/default-avatar.png',
|
||||||
name: 'Anika Visser',
|
name: 'Anika Visser',
|
||||||
email: 'anika.visser@devias.io'
|
email: 'anika.visser@devias.io',
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
@ -128,10 +128,31 @@ export const AuthProvider = (props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const signIn = async (email, password) => {
|
const signIn = async (email, password) => {
|
||||||
if (email !== 'demo@oktopus.io' || password !== 'Password123!') {
|
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
|
||||||
|
var raw = JSON.stringify({
|
||||||
|
"email": email,
|
||||||
|
"password": password
|
||||||
|
});
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: myHeaders,
|
||||||
|
body: raw,
|
||||||
|
redirect: 'follow'
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = await fetch(process.env.NEXT_PUBLIC_REST_ENPOINT+"/auth/login", requestOptions)
|
||||||
|
|
||||||
|
if (result.status != 200) {
|
||||||
throw new Error('Please check your email and password');
|
throw new Error('Please check your email and password');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const token = await result.json()
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
window.sessionStorage.setItem('authenticated', 'true');
|
window.sessionStorage.setItem('authenticated', 'true');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -140,11 +161,14 @@ export const AuthProvider = (props) => {
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: '5e86809283e28b96d2d38537',
|
id: '5e86809283e28b96d2d38537',
|
||||||
avatar: '/assets/avatars/avatar-anika-visser.png',
|
avatar: '/assets/avatars/default-avatar.png',
|
||||||
name: 'Anika Visser',
|
name: 'Anika Visser',
|
||||||
email: 'anika.visser@devias.io'
|
email: 'anika.visser@devias.io',
|
||||||
|
token: token
|
||||||
};
|
};
|
||||||
|
|
||||||
|
localStorage.setItem("token", token)
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: HANDLERS.SIGN_IN,
|
type: HANDLERS.SIGN_IN,
|
||||||
payload: user
|
payload: user
|
||||||
|
|
@ -168,7 +192,7 @@ export const AuthProvider = (props) => {
|
||||||
skip,
|
skip,
|
||||||
signIn,
|
signIn,
|
||||||
signUp,
|
signUp,
|
||||||
signOut
|
signOut,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export const AccountPopover = (props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
|
|
||||||
|
|
||||||
const handleSignOut = useCallback(
|
const handleSignOut = useCallback(
|
||||||
() => {
|
() => {
|
||||||
onClose?.();
|
onClose?.();
|
||||||
|
|
@ -42,7 +43,7 @@ export const AccountPopover = (props) => {
|
||||||
color="text.secondary"
|
color="text.secondary"
|
||||||
variant="body2"
|
variant="body2"
|
||||||
>
|
>
|
||||||
Anika Visser
|
{auth.user.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import { alpha } from '@mui/material/styles';
|
import { alpha } from '@mui/material/styles';
|
||||||
import { usePopover } from 'src/hooks/use-popover';
|
import { usePopover } from 'src/hooks/use-popover';
|
||||||
import { AccountPopover } from './account-popover';
|
import { AccountPopover } from './account-popover';
|
||||||
|
import { useAuth } from 'src/hooks/use-auth';
|
||||||
|
|
||||||
const SIDE_NAV_WIDTH = 280;
|
const SIDE_NAV_WIDTH = 280;
|
||||||
const TOP_NAV_HEIGHT = 64;
|
const TOP_NAV_HEIGHT = 64;
|
||||||
|
|
@ -24,8 +25,9 @@ export const TopNav = (props) => {
|
||||||
const { onNavOpen } = props;
|
const { onNavOpen } = props;
|
||||||
const lgUp = useMediaQuery((theme) => theme.breakpoints.up('lg'));
|
const lgUp = useMediaQuery((theme) => theme.breakpoints.up('lg'));
|
||||||
const accountPopover = usePopover();
|
const accountPopover = usePopover();
|
||||||
|
const auth = useAuth();
|
||||||
|
|
||||||
return (
|
return ( auth.user &&
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
component="header"
|
component="header"
|
||||||
|
|
@ -106,7 +108,7 @@ export const TopNav = (props) => {
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 40
|
width: 40
|
||||||
}}
|
}}
|
||||||
src="/assets/avatars/avatar-anika-visser.png"
|
src={auth.user.avatar}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ const Page = () => {
|
||||||
const [method, setMethod] = useState('email');
|
const [method, setMethod] = useState('email');
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
email: 'demo@oktopus.io',
|
email: '',
|
||||||
password: 'Password123!',
|
password: '',
|
||||||
submit: null
|
submit: null
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
|
|
@ -99,7 +99,7 @@ const Page = () => {
|
||||||
<Typography variant="h4">
|
<Typography variant="h4">
|
||||||
Login
|
Login
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
{/* <Typography
|
||||||
color="text.secondary"
|
color="text.secondary"
|
||||||
variant="body2"
|
variant="body2"
|
||||||
>
|
>
|
||||||
|
|
@ -113,7 +113,7 @@ const Page = () => {
|
||||||
>
|
>
|
||||||
Register
|
Register
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography> */}
|
||||||
</Stack>
|
</Stack>
|
||||||
{/*<Tabs
|
{/*<Tabs
|
||||||
onChange={handleMethodChange}
|
onChange={handleMethodChange}
|
||||||
|
|
@ -158,9 +158,9 @@ const Page = () => {
|
||||||
value={formik.values.password}
|
value={formik.values.password}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<FormHelperText sx={{ mt: 1 }}>
|
{/* <FormHelperText sx={{ mt: 1 }}>
|
||||||
Optionally you can skip.
|
Optionally you can skip.
|
||||||
</FormHelperText>
|
</FormHelperText> */}
|
||||||
{formik.errors.submit && (
|
{formik.errors.submit && (
|
||||||
<Typography
|
<Typography
|
||||||
color="error"
|
color="error"
|
||||||
|
|
@ -179,21 +179,25 @@ const Page = () => {
|
||||||
>
|
>
|
||||||
Continue
|
Continue
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
{/* <Button
|
||||||
fullWidth
|
fullWidth
|
||||||
size="large"
|
size="large"
|
||||||
sx={{ mt: 3 }}
|
sx={{ mt: 3 }}
|
||||||
onClick={handleSkip}
|
onClick={handleSkip}
|
||||||
>
|
>
|
||||||
Skip authentication
|
Skip authentication
|
||||||
</Button>
|
</Button> */}
|
||||||
<Alert
|
<Alert
|
||||||
color="primary"
|
color="primary"
|
||||||
severity="info"
|
severity="info"
|
||||||
sx={{ mt: 3 }}
|
sx={{ mt: 3 }}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
You can use <b>demo@oktopus.io</b> and password <b>Password123!</b>
|
Don't have an account? ask one for us at <Link
|
||||||
|
href="https://github.com/leandrofars/oktopus"
|
||||||
|
underline="hover">
|
||||||
|
Github
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
</Alert>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,39 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { subDays, subHours } from 'date-fns';
|
|
||||||
import { Box, Container, Unstable_Grid2 as Grid } from '@mui/material';
|
import { Box, Container, Unstable_Grid2 as Grid } from '@mui/material';
|
||||||
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
|
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
|
||||||
import { OverviewBudget } from 'src/sections/overview/overview-budget';
|
|
||||||
import { OverviewLatestOrders } from 'src/sections/overview/overview-latest-orders';
|
import { OverviewLatestOrders } from 'src/sections/overview/overview-latest-orders';
|
||||||
import { OverviewLatestProducts } from 'src/sections/overview/overview-latest-products';
|
import { useAuth } from 'src/hooks/use-auth';
|
||||||
import { OverviewSales } from 'src/sections/overview/overview-sales';
|
|
||||||
import { OverviewTasksProgress } from 'src/sections/overview/overview-tasks-progress';
|
|
||||||
import { OverviewTotalCustomers } from 'src/sections/overview/overview-total-customers';
|
|
||||||
import { OverviewTotalProfit } from 'src/sections/overview/overview-total-profit';
|
|
||||||
import { OverviewTraffic } from 'src/sections/overview/overview-traffic';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
|
const auth = useAuth();
|
||||||
const [devices, setDevices] = useState([]);
|
const [devices, setDevices] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('https://d9962fd9-2464-4a30-9a86-a15a04b57ad0.mock.pstmn.io/device')
|
|
||||||
|
if (auth.user.token) {
|
||||||
|
console.log("auth.user.token =", auth.user.token)
|
||||||
|
}else{
|
||||||
|
auth.user.token = localStorage.getItem("token")
|
||||||
|
}
|
||||||
|
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
myHeaders.append("Authorization", auth.user.token);
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: myHeaders,
|
||||||
|
redirect: 'follow'
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(process.env.NEXT_PUBLIC_REST_ENPOINT+'/device', requestOptions)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => setDevices(json))
|
.then(json => setDevices(json))
|
||||||
.catch(error => console.error('Error:', error));
|
.catch(error => console.error('Error:', error));
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
|
||||||
|
return (devices &&
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
|
|
@ -50,7 +60,7 @@ const Page = () => {
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
Page.getLayout = (page) => (
|
Page.getLayout = (page) => (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
|
|
@ -59,125 +69,3 @@ Page.getLayout = (page) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|
||||||
/*
|
|
||||||
<OverviewSales
|
|
||||||
chartSeries={[
|
|
||||||
{
|
|
||||||
name: 'This year',
|
|
||||||
data: [18, 16, 5, 8, 3, 14, 14, 16, 17, 19, 18, 20]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Last year',
|
|
||||||
data: [12, 11, 4, 6, 2, 9, 9, 10, 11, 12, 13, 13]
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
sx={{ height: '100%' }}
|
|
||||||
/>
|
|
||||||
<OverviewLatestProducts
|
|
||||||
products={[
|
|
||||||
{
|
|
||||||
id: '5ece2c077e39da27658aa8a9',
|
|
||||||
image: '/assets/products/product-1.png',
|
|
||||||
name: 'Healthcare Erbology',
|
|
||||||
updatedAt: subHours(now, 6).getTime()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5ece2c0d16f70bff2cf86cd8',
|
|
||||||
image: '/assets/products/product-2.png',
|
|
||||||
name: 'Makeup Lancome Rouge',
|
|
||||||
updatedAt: subDays(subHours(now, 8), 2).getTime()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'b393ce1b09c1254c3a92c827',
|
|
||||||
image: '/assets/products/product-5.png',
|
|
||||||
name: 'Skincare Soja CO',
|
|
||||||
updatedAt: subDays(subHours(now, 1), 1).getTime()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'a6ede15670da63f49f752c89',
|
|
||||||
image: '/assets/products/product-6.png',
|
|
||||||
name: 'Makeup Lipstick',
|
|
||||||
updatedAt: subDays(subHours(now, 3), 3).getTime()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'bcad5524fe3a2f8f8620ceda',
|
|
||||||
image: '/assets/products/product-7.png',
|
|
||||||
name: 'Healthcare Ritual',
|
|
||||||
updatedAt: subDays(subHours(now, 5), 6).getTime()
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
sx={{ height: '100%' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid
|
|
||||||
xs={12}
|
|
||||||
md={12}
|
|
||||||
lg={8}
|
|
||||||
>
|
|
||||||
<OverviewLatestOrders
|
|
||||||
orders={[
|
|
||||||
{
|
|
||||||
id: 'f69f88012978187a6c12897f',
|
|
||||||
ref: 'DEV1049',
|
|
||||||
amount: 30.5,
|
|
||||||
customer: {
|
|
||||||
name: 'Ekaterina Tankova'
|
|
||||||
},
|
|
||||||
createdAt: 1555016400000,
|
|
||||||
status: 'pending'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '9eaa1c7dd4433f413c308ce2',
|
|
||||||
ref: 'DEV1048',
|
|
||||||
amount: 25.1,
|
|
||||||
customer: {
|
|
||||||
name: 'Cao Yu'
|
|
||||||
},
|
|
||||||
createdAt: 1555016400000,
|
|
||||||
status: 'Online'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '01a5230c811bd04996ce7c13',
|
|
||||||
ref: 'DEV1047',
|
|
||||||
amount: 10.99,
|
|
||||||
customer: {
|
|
||||||
name: 'Alexa Richardson'
|
|
||||||
},
|
|
||||||
createdAt: 1554930000000,
|
|
||||||
status: 'refunded'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '1f4e1bd0a87cea23cdb83d18',
|
|
||||||
ref: 'DEV1046',
|
|
||||||
amount: 96.43,
|
|
||||||
customer: {
|
|
||||||
name: 'Anje Keizer'
|
|
||||||
},
|
|
||||||
createdAt: 1554757200000,
|
|
||||||
status: 'pending'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '9f974f239d29ede969367103',
|
|
||||||
ref: 'DEV1045',
|
|
||||||
amount: 32.54,
|
|
||||||
customer: {
|
|
||||||
name: 'Clarke Gillebert'
|
|
||||||
},
|
|
||||||
createdAt: 1554670800000,
|
|
||||||
status: 'Online'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ffc83c1560ec2f66a1c05596',
|
|
||||||
ref: 'DEV1044',
|
|
||||||
amount: 16.76,
|
|
||||||
customer: {
|
|
||||||
name: 'Adam Denisov'
|
|
||||||
},
|
|
||||||
createdAt: 1554670800000,
|
|
||||||
status: 'Online'
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
sx={{ height: '100%' }}
|
|
||||||
/>
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user