login register api

dev
Aji Kamaludin 3 years ago
parent bec566d1c8
commit 665aa8efcc
No known key found for this signature in database
GPG Key ID: 670E1F26AD5A8099

@ -0,0 +1,4 @@
{
"singleQuote": true,
"semi": false
}

18
package-lock.json generated

@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
"name": "react-chakra",
"version": "0.1.0",
"dependencies": {
"@chakra-ui/icons": "^1.0.15",
@ -23,6 +24,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"axios": "^0.21.1",
"framer-motion": "^4.1.17",
"is_js": "^0.9.0",
"react": "^17.0.2",
@ -5780,6 +5782,14 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@ -27579,6 +27589,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",

@ -1,6 +1,6 @@
{
"name": "react-chakra",
"version": "0.1.0",
"name": "react-kasiraja-web",
"version": "1.0.0",
"private": true,
"dependencies": {
"@chakra-ui/icons": "^1.0.15",
@ -19,6 +19,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"axios": "^0.21.1",
"framer-motion": "^4.1.17",
"is_js": "^0.9.0",
"react": "^17.0.2",

@ -11,10 +11,11 @@ import {
} from 'react-router-dom'
import "@fontsource/raleway/400.css"
import "@fontsource/open-sans/700.css"
import "./axiosSetup"
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'
import NotFound from "./views/errors/404"
import { AppProvider } from "./context/AppContext"
import NotFound from "./views/errors/404"
import Loading from "./components/Common/Loading"

@ -2,31 +2,37 @@ export const navs = [
{
name: "Dashboard",
to: "/dashboard",
icon: "clipboard-list"
icon: "clipboard-list",
role: "admin",
},
{
name: "Kasir",
to: "/sales/create",
icon: "cash-register"
icon: "cash-register",
role: "kasir",
},
{
name: "Penjualan",
to: "/sales",
icon: "money-bill-wave"
icon: "money-bill-wave",
role: "admin",
},
{
name: "Pembelian",
to: "/purchases",
icon: "money-bill-wave"
icon: "money-bill-wave",
role: "admin",
},
{
name: "Kategori",
to: "/categories",
icon: "list"
icon: "list",
role: "admin",
},
{
name: "Produk",
to: "/products",
icon: "list"
icon: "list",
role: "admin",
},
]

@ -0,0 +1,19 @@
import axios from 'axios'
import { API_URL } from './config'
const id = x => x
axios.defaults.baseURL = API_URL
axios.interceptors.response.use(id, error => {
const { status, data: { message } } = error.response
if (status === 401 && message === 'Unauthenticated.') {
window.localStorage.clear()
window.location.reload()
return
}
// if expired access token lets refresh token
if (status === 403) {
window.alert('Anda tidak mempunyai akses untuk aksi ini')
}
throw error
})

@ -10,7 +10,8 @@ import {
} from '@chakra-ui/react'
import { ChevronRightIcon } from '@chakra-ui/icons'
const Header = ({ showSidebarButton = true, onShowSidebar, onLogout }) => {
const Header = ({ showSidebarButton = true, onShowSidebar, onLogout, user }) => {
return (
<Flex bg="red" p={2} color="white" justifyContent="end">
<Box flex="1">
@ -28,10 +29,10 @@ const Header = ({ showSidebarButton = true, onShowSidebar, onLogout }) => {
<MenuButton
_expanded={{ bg: "transparent" }}
>
<Avatar name="Admin" />
<Avatar name={user?.name} />
</MenuButton>
<MenuList>
<MenuItem color="blackAlpha.900">User: Admin</MenuItem>
<MenuItem color="blackAlpha.900">{user?.name}</MenuItem>
<MenuItem color="blackAlpha.900" onClick={e => onLogout(e)}>Logout</MenuItem>
</MenuList>
</Menu>

@ -13,6 +13,7 @@ import {
import { Link } from 'react-router-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { navs } from '../../_nav'
import { useAuth } from '../../context/AppContext'
const MenuItem = ({ name, icon, onClick }) => {
@ -28,7 +29,9 @@ const MenuItem = ({ name, icon, onClick }) => {
)
}
const SidebarContent = ({ onClick, variant }) => (
const SidebarContent = ({ onClick, variant }) => {
const { user } = useAuth()
return (
<VStack>
{variant === 'sidebar' && (
<Heading
@ -39,12 +42,13 @@ const SidebarContent = ({ onClick, variant }) => (
>kasirAja</Heading>
)}
{navs.map(nav => (
<Link to={nav.to} style={{width: "100%"}} key={nav.name}>
<Link to={nav.to} style={{width: "100%"}} key={nav.name} hidden={user.role !== nav.role}>
<MenuItem name={nav.name} icon={nav.icon} onClick={onClick}/>
</Link>
))}
</VStack>
)
)
}
const Sidebar = ({ isOpen, variant, onClose }) => {
return variant === 'sidebar' ? (

@ -16,7 +16,7 @@ const userManager = {
const AppContext = React.createContext()
function AppProvider(props) {
const [user, setUser] = useState(userManager.get())
const [user, setUser] = useState(JSON.parse(userManager.get()))
const value = useMemo(
() => ({ user, setUser }),
@ -39,7 +39,7 @@ function useAuth() {
return is.not.empty(user) && is.not.null(user)
}
const persistUser = user => {
userManager.set(user)
userManager.set(JSON.stringify(user))
setUser(user)
}
const logout = () => {
@ -48,6 +48,7 @@ function useAuth() {
}
return {
user,
isLoggedIn,
persistUser,
logout

@ -1,4 +1,4 @@
import { useState, Suspense } from "react";
import { useEffect, useState, Suspense } from "react";
import { Switch, Route, Redirect } from 'react-router-dom'
import {
Container,
@ -19,7 +19,7 @@ const smVariant = { navigation: 'drawer', navigationButton: true }
const mdVariant = { navigation: 'sidebar', navigationButton: false }
export default function DashboardLayout(props) {
const { loading, isLoggedIn, logout } = useAuth()
const { loading, isLoggedIn, logout, user } = useAuth()
const { history } = props;
@ -29,15 +29,18 @@ export default function DashboardLayout(props) {
history.push('/login')
}
if(!isLoggedIn()){
history.push('/login');
}
const [isSidebarOpen, setSidebarOpen] = useState(false)
const variants = useBreakpointValue({ base: smVariant, md: mdVariant })
const toggleSidebar = () => setSidebarOpen(!isSidebarOpen)
useEffect(() => {
const { history } = props;
if(!isLoggedIn()){
history.push('/login');
}
})
if(loading) {
return <Loading/>
}
@ -50,8 +53,9 @@ export default function DashboardLayout(props) {
showSidebarButton={variants?.navigationButton}
onShowSidebar={toggleSidebar}
onLogout={handleLogout}
user={user}
/>
<Container maxW="container.xl" pt="10">
<Container maxW="105rem" pt="10">
{/* Content */}
<Suspense fallback={<Loading/>}>
<Switch>

@ -0,0 +1,19 @@
import axios from 'axios'
export function login(payload) {
const { email, password } = payload
return axios({
method: 'POST',
url: '/authentications',
data: { email, password }
}).then(response => response.data)
}
export function register(payload) {
const { name, email, password } = payload
return axios({
method: 'POST',
url: '/registration',
data: { name, email, password }
}).then(res => res.data)
}

@ -7,13 +7,40 @@ import {
FormLabel,
Input,
Button,
Alert,
AlertIcon,
} from "@chakra-ui/react"
import { useEffect } from "react"
import { useEffect, useState } from "react"
import { Link } from "react-router-dom"
import { useAuth } from "../../context/AppContext"
import { login } from './Api'
export default function Login(props) {
const { isLoggedIn } = useAuth()
const { isLoggedIn, persistUser } = useAuth()
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState([])
const [submit, setSubmit] = useState(false);
const handleSubmit = (e) => {
e.preventDefault()
setSubmit(true)
login({ email, password })
.then(res => {
const { data } = res
persistUser({
...data.user,
accessToken: data.accessToken,
refreshToken: data.refreshToken,
})
})
.catch(err => {
setErrors(err.response.data)
})
.finally(() => setSubmit(false))
}
useEffect(() => {
const { history } = props
@ -36,13 +63,33 @@ export default function Login(props) {
</Box>
<Box flexShrink="0" shadow="lg" p="8" maxW="96" w="full" bg="white" rounded="lg">
<Box rounded="lg" >
{errors.message?.length > 0 && (
<Alert status="error" mb="5" rounded="md">
<AlertIcon />
{errors.message}
</Alert>
)}
<FormControl id="email" pb="2">
<FormLabel mb="1">Email</FormLabel>
<Input focusBorderColor="red.500" type="email" placeholder="email"/>
<Input
focusBorderColor="red.500"
type="email"
placeholder="email"
value={email}
onChange={(e) => {
setEmail(e.target.value)
}}
/>
</FormControl>
<FormControl id="password" pb="4">
<FormLabel mb="1">Password</FormLabel>
<Input focusBorderColor="red.500" type="password" placeholder="password" />
<Input
focusBorderColor="red.500"
type="password"
placeholder="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</FormControl>
<Box mt={5} mb="1" ml="1" fontSize="sm">
<Link to="/register">
@ -53,6 +100,8 @@ export default function Login(props) {
p={6}
w="100%"
type="submit"
disabled={submit}
onClick={(e) => handleSubmit(e)}
>
Login
</Button>

@ -7,14 +7,55 @@ import {
FormLabel,
Input,
Button,
Alert,
AlertIcon,
InputGroup,
InputRightElement,
useToast,
} from "@chakra-ui/react"
import { useEffect } from "react"
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useEffect, useState } from "react"
import { Link } from "react-router-dom"
import { useAuth } from "../../context/AppContext"
import { register } from "./Api"
export default function Register(props) {
export default function RegisterPage(props) {
const { history } = props
const { isLoggedIn } = useAuth()
const toast = useToast()
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [errors, setErrors] = useState([])
const [submit, setSubmit] = useState(false)
const [show, setShow] = useState(false)
const handleClick = (e) => { setShow(!show) }
const handleSubmit = (e) => {
e.preventDefault()
setSubmit(true)
register({ name, email, password })
.then((res) => {
setErrors([])
toast({
title: res.message,
description: "anda dapat menggunakan login sekarang",
type: "info",
position: "top-right"
})
history.push('/login')
})
.catch((err) => {
setErrors(err.response.data)
})
.finally(() => setSubmit(false))
}
useEffect(() => {
const { history } = props
if (isLoggedIn()) {
@ -36,17 +77,50 @@ export default function Register(props) {
</Box>
<Box flexShrink="0" shadow="lg" p="8" maxW="96" w="full" bg="white" rounded="lg">
<Box rounded="lg" >
{errors.message?.length > 0 && (
<Alert status="error" mb="5" rounded="md">
<AlertIcon />
{errors.message}
</Alert>
)}
<FormControl id="name" pb="2">
<FormLabel mb="1">Nama Toko</FormLabel>
<Input focusBorderColor="red.500" type="text" placeholder="nama toko"/>
<Input
focusBorderColor="red.500"
type="text"
placeholder="nama toko"
value={name}
onChange={e => setName(e.target.value)}
/>
</FormControl>
<FormControl id="email" pb="2">
<FormLabel mb="1">Email</FormLabel>
<Input focusBorderColor="red.500" type="email" placeholder="email"/>
<Input
focusBorderColor="red.500"
type="email"
placeholder="email"
value={email}
onChange={e => setEmail(e.target.value)}
/>
</FormControl>
<FormControl id="password" pb="4">
<FormLabel mb="1">Password</FormLabel>
<Input focusBorderColor="red.500" type="password" placeholder="password" />
<InputGroup size="md">
<Input
pr="4.5rem"
type={show ? "text" : "password"}
placeholder="password"
focusBorderColor="red.500"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<InputRightElement width="3.5rem">
<Button h="1.25rem" size="sm" onClick={handleClick} bg="transparent" color="black" _hover={{ bg: "transparent" }} _active={{ bg: "transparent"}}>
{show ? <FontAwesomeIcon icon={"eye"}/> : <FontAwesomeIcon icon={"eye-slash"}/>}
</Button>
</InputRightElement>
</InputGroup>
</FormControl>
<Box mt={5} mb="1" ml="1" fontSize="sm">
<Link to="/login">
@ -57,6 +131,8 @@ export default function Register(props) {
p={6}
w="100%"
type="submit"
disabled={submit}
onClick={e => handleSubmit(e)}
>
Daftar
</Button>

@ -1,12 +1,9 @@
import {
Button,
Flex,
Box,
useToast
} from "@chakra-ui/react"
export default function Dashboard() {
const toast = useToast()
return (
<Flex direction="column">
<Flex direction="row" justifyContent="space-between">
@ -20,20 +17,6 @@ export default function Dashboard() {
<div>
Dashboard
</div>
<Button
onClick={() =>
toast({
title: "Account created.",
description: "We've created your account for you.",
status: "success",
duration: 9000,
isClosable: true,
position: "bottom-right",
})
}
>
Show Toast
</Button>
</Flex>
)
}
Loading…
Cancel
Save