diff --git a/src/layouts/_routeDashboard.js b/src/layouts/_routeDashboard.js index cf2eba0..9ab3de2 100644 --- a/src/layouts/_routeDashboard.js +++ b/src/layouts/_routeDashboard.js @@ -3,8 +3,10 @@ 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 Sales = React.lazy(() => import("../views/sales")) const Customers = React.lazy(() => import("../views/customers")) +const Sales = React.lazy(() => import("../views/sales")) +const Purchases = React.lazy(() => import("../views/purchases")) + const routes = [ { path: '/', exact: true, name: 'Home' }, @@ -14,6 +16,7 @@ const routes = [ { path: "/categories", name: "kategori", component: Categories }, { path: "/users", name: "pengguna", component: User }, { path: "/sales", name: "penjualan", component: Sales }, + { path: "/purchases", name: "pembelian", component: Purchases }, ] export default routes; \ No newline at end of file diff --git a/src/views/purchases/Api.js b/src/views/purchases/Api.js new file mode 100644 index 0000000..6faba97 --- /dev/null +++ b/src/views/purchases/Api.js @@ -0,0 +1,43 @@ +import axios from "axios" +import useSWR from "swr" +import qs from "query-string" + +export function usePurchases(user, params) { + const { data, error } = useSWR([ + `/purchases?${qs.stringify(params)}`, user.accessToken + ]) + + return [ + data, + error + ] +} + +export function createPurchase(payload, token) { + return axios({ + method: 'POST', + url: '/purchases', + data: payload, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data) + .catch(err => { + throw err.response.data + }) +} + +export function getPurchase(id, token){ + return axios({ + method: 'GET', + url: `/purchases/${id}`, + headers: { + 'Authorization': `Bearer ${token}` + } + }) + .then(res => res.data.data) + .catch(err => { + throw err.response.data + }) +} \ No newline at end of file diff --git a/src/views/purchases/Create.js b/src/views/purchases/Create.js new file mode 100644 index 0000000..0dc52d5 --- /dev/null +++ b/src/views/purchases/Create.js @@ -0,0 +1,261 @@ +import { + Flex, + Box, + Table, + Thead, + Tbody, + Th, + Td, + Tr, + Textarea, + Button, + Heading, + useToast +} from "@chakra-ui/react" +import { useState } from "react" +import { + Card, + FormDatePicker, + FormInput, + InputNumber, + Breadcrumb, + FormInputSelectionOpen, + useModalState, +} from "../../components/Common" +import { formatDate, formatIDR, genInvId } from "../../utils" +import { useAuth } from "../../context/AppContext" +import { searchProductByCode } from "../products/Api" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { createPurchase } from "./Api" + +import ProductSelectionModal from "../products/Modal" +import { mutate } from "swr" + +export default function Create() { + const { user } = useAuth() + const currentDate = new Date() + const invoicePrefix = genInvId() + const [invoice, setInvoice] = useState(`${invoicePrefix}/${Date.parse(currentDate)/1000}`) + const [date, setDate] = useState(currentDate) + + const [note, setNote] = useState('') + + const [productCode, setProductCode] = useState('') + const [submit, setSummit] = useState(false) + + + const toast = useToast() + + const [isProductOpen, toggleProduct] = useModalState() + + const [items, setItems] = useState([]) + + const searchProductCode = (e) => { + if(e.code === "Enter") { + searchProductByCode(productCode, user.accessToken) + .then(product => { + if(product) { + addItems(product) + } + }) + setProductCode('') + } + } + + const addItems = (product) => { + const findId = items.find(item => item.id === product.id) + if(findId) { + setItems(items.map(item => { + return { + ...item, + quantity: item.id === product.id ? +item.quantity + 1 : item.quantity + } + })) + } else { + setItems(items.concat({ + ...product, + quantity: 1 + })) + } + } + + const setItemQuantity = (itemId, value) => { + setItems(items.map(item => { + if (itemId === item.id) { + return { + ...item, + quantity: value + } + } else { + return item + } + })) + } + + const removeItem = (itemId) => { + setItems(items.filter(item => item.id !== itemId)) + } + + const totalAmount = items.reduce((mr, item) => { + return mr + +item.cost * +item.quantity + }, 0) + + const resetForm = () => { + setItems([]) + setNote('') + setInvoice(`${genInvId()}/${Date.parse(currentDate)/1000}`) + mutate(["/products?page=1&q=&withCategory=true&withStock=true", user.accessToken]) + } + + const handleCreatePurchase = () => { + if(items.length <= 0) { + return + } + setSummit(true) + createPurchase({ + officeId: user.officeid, + date: formatDate(date), + invoice, + amount: totalAmount, + discount: 0, + description: note, + items: items.map(item => { + return { + productId: item.id, + quantity: item.quantity, + cost: item.cost, + } + }) + }, user.accessToken) + .then((res) => { + toast({ + title: "success", + description: res.message, + status: "success", + isClosable: true, + duration: 6000, + position: "top-right" + }) + resetForm() + }) + .catch(err => { + toast({ + title: "error", + description: err.message, + status: "warning", + isClosable: true, + duration: 6000, + position: "top-right" + }) + }) + .finally(() => { + setSummit(false) + }) + } + + return ( + + + + + + + + + +