diff --git a/src/api/index.js b/src/api/index.js index 3be4844..bff2f47 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -1,6 +1,17 @@ import useSWR from "swr" import qs from "query-string" +export function useUsers(user, params) { + const { data, error } = useSWR([ + `/users?${qs.stringify(params)}`, user.accessToken + ]) + + return [ + data, + error, + ] +} + export function useProducts(user, params) { const { data, error } = useSWR([ `/products?${qs.stringify(params)}`, user.accessToken diff --git a/src/components/Common/Input.js b/src/components/Common/Input.js index 6282c80..93113dd 100644 --- a/src/components/Common/Input.js +++ b/src/components/Common/Input.js @@ -1,5 +1,14 @@ import { useEffect, useState } from "react"; -import { FormControl, FormLabel, Input, Box, InputGroup, InputRightElement, InputRightAddon } from "@chakra-ui/react"; +import { + FormControl, + FormLabel, + Input, + Box, + InputGroup, + InputRightElement, + InputRightAddon, + Button, +} from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import NumberFormat from "react-number-format"; @@ -37,17 +46,27 @@ export function useDebounce(value, delay) { } export function FormInput(props) { + const [show, setShow] = useState(false) const { data: [name, val, setVal = () => {}, type = "text"]} = props return ( {name} - setVal(e.target.value)} - {...props} - /> + + setVal(e.target.value)} + {...props} + /> + {type === "password" && ( + + + + )} + ) } diff --git a/src/components/Layout/Header.js b/src/components/Layout/Header.js index 1e3dceb..c3e7d70 100644 --- a/src/components/Layout/Header.js +++ b/src/components/Layout/Header.js @@ -9,6 +9,7 @@ import { MenuButton } from '@chakra-ui/react' import { ChevronRightIcon } from '@chakra-ui/icons' +import { Link } from 'react-router-dom' const Header = ({ showSidebarButton = true, onShowSidebar, onLogout, user }) => { @@ -32,7 +33,8 @@ const Header = ({ showSidebarButton = true, onShowSidebar, onLogout, user }) => - {user?.name} + Toko : {user?.company_name} + {user?.name} onLogout(e)}>logout diff --git a/src/layouts/_routeDashboard.js b/src/layouts/_routeDashboard.js index f31b238..0333da4 100644 --- a/src/layouts/_routeDashboard.js +++ b/src/layouts/_routeDashboard.js @@ -1,13 +1,15 @@ -import React from "react"; -const Dashboard = React.lazy(() => import("../views/dashboard")); -const Product = React.lazy(() => import("../views/products")); -const Categories = React.lazy(() => import("../views/categories")); +import React from "react" +const Dashboard = React.lazy(() => import("../views/dashboard")) +const User = React.lazy(() => import("../views/users")) +const Product = React.lazy(() => import("../views/products")) +const Categories = React.lazy(() => import("../views/categories")) const routes = [ { path: '/', exact: true, name: 'Home' }, { path: "/dashboard", name: "dashboard", component: Dashboard }, { path: "/products", name: "produk", component: Product }, - { path: "/categories", name: "kategori", component: Categories } + { path: "/categories", name: "kategori", component: Categories }, + { path: "/users", name: "pengguna", component: User }, ] export default routes; \ No newline at end of file diff --git a/src/views/dashboard/Dashboard.js b/src/views/dashboard/Dashboard.js index 12f315a..22fd7ae 100644 --- a/src/views/dashboard/Dashboard.js +++ b/src/views/dashboard/Dashboard.js @@ -1,32 +1,54 @@ import { Flex, Stat, StatLabel, StatNumber, StatHelpText, StatArrow } from "@chakra-ui/react" +import { useEffect } from "react" import Card from "../../components/Common/Card" +import { useAuth } from "../../context/AppContext" + +export default function Dashboard(props) { + const { user } = useAuth() + + useEffect(() => { + const { role } = user + if(role === "kasir") { + props.history.push("/sales/create") + } + return () => {} + }, [user, props]) -export default function Dashboard() { return ( - penjualan - 345.670 - - - 23.36% from yesterday - - - - - - pembelian - 145.670 - - - 3.36% from yesterday - + {user.name} + hai + {user.role === "admin" && ( + <> + + + penjualan + 345.670 + + + 23.36% from yesterday + + + + + + pembelian + 145.670 + + + 3.36% from yesterday + + + + + )} ) diff --git a/src/views/users/Api.js b/src/views/users/Api.js new file mode 100644 index 0000000..4dd808e --- /dev/null +++ b/src/views/users/Api.js @@ -0,0 +1,59 @@ +import axios from "axios"; + +export function createUser(payload, token) { + return axios({ + method: 'POST', + url: '/users', + data: payload, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data) + .catch(err => { + throw err.response.data + }) +} + +export function getUser(id, token){ + return axios({ + method: 'GET', + url: `/users/${id}`, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data.data) + .catch(err => { + throw err.response.data + }) +} + +export function updateUser(id, payload, token) { + return axios({ + method: 'PUT', + url: `/users/${id}`, + data: payload, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data) + .catch(err => { + throw err.response.data + }) +} + +export function deleteUser(id, token) { + return axios({ + method: 'DELETE', + url: `/users/${id}`, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data) + .catch(err => { + throw err.response.data + }) +} \ No newline at end of file diff --git a/src/views/users/Create.js b/src/views/users/Create.js new file mode 100644 index 0000000..213e3db --- /dev/null +++ b/src/views/users/Create.js @@ -0,0 +1,68 @@ +import { + Button, + Alert, + AlertIcon, + useToast +} from "@chakra-ui/react" +import { createUser } from "./Api" +import { useState } from "react" +import { Breadcrumb, Card, FormInput } from "../../components/Common" +import { useAuth } from "../../context/AppContext" + +export default function Create({ history }) { + const { user } = useAuth() + + const toast = useToast() + + const [name, setName] = useState('') + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [submit, setSubmit] = useState(false) + const [error, setError] = useState(null) + + const handleSubmit = () => { + setSubmit(true) + createUser({ name, email, password }, user.accessToken) + .then(res => { + toast({ + title: res.status, + description: "item ditambahkan", + status: "success", + duration: 4000, + isClosable: true, + position: "top-right" + }) + history.push('/users') + }) + .catch(err => { + setError(err.message) + }) + .finally(() => { + setSubmit(false) + }) + } + + return ( + <> + + + {error !== null && ( + + + {error} + + )} + + + + + + + ) +} \ No newline at end of file diff --git a/src/views/users/Edit.js b/src/views/users/Edit.js new file mode 100644 index 0000000..8d0a7bb --- /dev/null +++ b/src/views/users/Edit.js @@ -0,0 +1,97 @@ +import { + Button, + Alert, + AlertIcon, + useToast +} from "@chakra-ui/react" +import { getUser, updateUser } from "./Api" +import { useState } from "react" +import { Breadcrumb, Card, FormInput, Loading } from "../../components/Common" +import { useAuth } from "../../context/AppContext" +import { useEffect } from "react" + +export default function Edit(props) { + const id = props.match.params.id + const { user } = useAuth() + + const toast = useToast() + + const [name, setName] = useState('') + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + + const [loading, setLoading] = useState(false) + const [submit, setSubmit] = useState(false) + const [error, setError] = useState(null) + + const handleSubmit = () => { + setSubmit(true) + updateUser(id, { + name, + email, + password + }, user.accessToken) + .then(res => { + toast({ + title: res.status, + description: "item diubah", + status: "success", + duration: 4000, + isClosable: true, + position: "top-right" + }) + props.history.push('/users') + }) + .catch(err => { + setError(err.message) + }) + .finally(() => { + setSubmit(false) + }) + } + + useEffect(() => { + const { accessToken: token } = user + setLoading(true) + getUser(id, token) + .then(res => { + setName(res.user.name) + setEmail(res.user.email) + }) + .catch(err => setError(err.message)) + .finally(() => setLoading(false)) + return () => {} + }, [id, user]) + + return ( + <> + {user.role === "admin" && ( + + )} + + {error !== null && ( + + + {error} + + )} + {loading ? ( + + ) : ( + <> + + + + + + )} + + + ) +} \ No newline at end of file diff --git a/src/views/users/List.js b/src/views/users/List.js new file mode 100644 index 0000000..4ed9cd0 --- /dev/null +++ b/src/views/users/List.js @@ -0,0 +1,141 @@ +import { useState } from "react" +import { + Button, + Alert, + AlertIcon, + Table, + Thead, + Tr, + Td, + Th, + Tbody, + Menu, + MenuItem, + MenuButton, + MenuList, + useToast, +} from "@chakra-ui/react" +import { Link } from "react-router-dom" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { mutate } from 'swr' +import qs from "query-string" +import { + Breadcrumb, + Card, + Loading, + Pagination, + useDebounce, + AlertDialog, + SearchInput, + useModalState, +} from "../../components/Common" +import { useUsers } from "../../api" +import { deleteUser } from "./Api" +import { useAuth } from "../../context/AppContext" + +export default function List() { + const { user } = useAuth() + const toast = useToast() + + const [page, setPage] = useState(1) + const [search, setSearch] = useState('') + const q = useDebounce(search, 600) + const params = { page, q } + const [data, error] = useUsers(user, params) + + const [isOpen, toggle, selected] = useModalState(false) + + const handleDelete = async () => { + await deleteUser(selected.id, user.accessToken) + .then((res) => { + toast({ + title: res.status, + description: "item dihapus", + status: "success", + position: "top-right", + duration: 4000, + isClosable: true + }) + mutate([`/users?${qs.stringify(params)}`, user.accessToken]) + }) + .catch((err) => { + toast({ + title: err.status, + description: err.message, + status: "error", + position: "top-right", + duration: 4000, + isClosable: true + }) + }) + } + + if(error) { + return ( + + + {error.message} + + ) + } + + return ( + <> + + + + + {data ? ( + <> + + + + + + + + + + + {data.users.map((auser) => auser.id !== user.id && ( + + + + + + + ))} + +
namaemailrole
{auser.name}{auser.email}{auser.role} + + + + + + ubah + { + toggle(auser) + }} + > + hapus + + + +
+ + + ) : ( + + )} +
+ toggle()} + /> + + ) +} \ No newline at end of file diff --git a/src/views/users/index.js b/src/views/users/index.js new file mode 100644 index 0000000..e17afe6 --- /dev/null +++ b/src/views/users/index.js @@ -0,0 +1,17 @@ +import { Switch, Route } from 'react-router-dom' + +import Create from './Create' +import List from './List' +import Edit from './Edit' + +function routes(props) { + return ( + + + + + + ) +} + +export default routes