products done, selection input hook
parent
614a0630fd
commit
d386ef690d
@ -0,0 +1,72 @@
|
||||
import { useState } from "react"
|
||||
import {
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Table,
|
||||
Thead,
|
||||
Tr,Th,Td,
|
||||
Tbody,
|
||||
Alert,
|
||||
AlertIcon
|
||||
} from "@chakra-ui/react"
|
||||
import { Loading, Pagination, SearchInput, useDebounce } from "../../components/Common"
|
||||
import { useAuth } from "../../context/AppContext"
|
||||
import { useCategories } from "../../api"
|
||||
|
||||
export default function ModalCom(props) {
|
||||
const { isOpen, toggle, onClose } = props
|
||||
const { user } = useAuth()
|
||||
|
||||
const [page, setPage] = useState(1)
|
||||
const [search, setSearch] = useState('')
|
||||
const q = useDebounce(search, 600)
|
||||
|
||||
const [data, error] = useCategories(user, { page, q })
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={toggle}>
|
||||
<ModalOverlay />
|
||||
<ModalContent minW="40rem">
|
||||
<ModalHeader>kategori</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<SearchInput setter={[search, setSearch]}/>
|
||||
{error && (
|
||||
<Alert status="error">
|
||||
<AlertIcon />
|
||||
{error.message}
|
||||
</Alert>
|
||||
)}
|
||||
{data ? (
|
||||
<>
|
||||
<Table variant="simple" mt="2" mb="4">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>nama</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{data.categories.map((category) => (
|
||||
<Tr key={category.id} onClick={() => {
|
||||
onClose(category)
|
||||
toggle()
|
||||
}} _hover={{bg: "gray.200"}}>
|
||||
<Td>{ category.name }</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
<Pagination page={page} setPage={setPage} totalPages={data.meta.totalPages} mb="4"/>
|
||||
</>
|
||||
) : (
|
||||
<Loading/>
|
||||
)}
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
import axios from "axios";
|
||||
|
||||
export function createProduct(payload, token) {
|
||||
return axios({
|
||||
method: 'POST',
|
||||
url: '/products',
|
||||
data: payload,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
.then(res => res.data)
|
||||
.catch(err => {
|
||||
throw err.response.data
|
||||
})
|
||||
}
|
||||
|
||||
export function getProduct(id, token){
|
||||
return axios({
|
||||
method: 'GET',
|
||||
url: `/products/${id}`,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
.then(res => res.data.data)
|
||||
.catch(err => {
|
||||
throw err.response.data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateProduct(id, payload, token) {
|
||||
return axios({
|
||||
method: 'PUT',
|
||||
url: `/products/${id}`,
|
||||
data: payload,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
.then(res => res.data)
|
||||
.catch(err => {
|
||||
throw err.response.data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteProduct(id, token) {
|
||||
return axios({
|
||||
method: 'DELETE',
|
||||
url: `/products/${id}`,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
.then(res => res.data)
|
||||
.catch(err => {
|
||||
throw err.response.data
|
||||
})
|
||||
}
|
@ -1,29 +1,97 @@
|
||||
import {
|
||||
Button,
|
||||
} from "@chakra-ui/react"
|
||||
import { Alert, AlertIcon, Button, useToast } from "@chakra-ui/react"
|
||||
import { useState } from "react"
|
||||
import { Breadcrumb, Card, FormInput, FormInputNumber } from "../../components/Common"
|
||||
import {
|
||||
Breadcrumb,
|
||||
Card,
|
||||
FormInput,
|
||||
FormInputNumber,
|
||||
FormInputSelection,
|
||||
useModalState
|
||||
} from "../../components/Common"
|
||||
import { createProduct } from "./Api"
|
||||
import CategoryModalSelection from "../categories/Modal"
|
||||
import { useAuth } from "../../context/AppContext"
|
||||
|
||||
export default function Create(props) {
|
||||
const { user } = useAuth()
|
||||
|
||||
export default function Create() {
|
||||
const [name, setName] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
const [cost, setCost] = useState(0)
|
||||
const [price, setPrice] = useState(0)
|
||||
const [stock, setStock] = useState(0)
|
||||
const [category, setCategory] = useState({})
|
||||
const [category, setCategory] = useState({name: ''})
|
||||
|
||||
const toast = useToast()
|
||||
const [submit, setSubmit] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const [ isOpen, toggle ] = useModalState()
|
||||
|
||||
const handleSubmit = () => {
|
||||
setSubmit(true)
|
||||
createProduct({
|
||||
name,
|
||||
description,
|
||||
cost,
|
||||
price,
|
||||
stock,
|
||||
category_id: category ? category.id : ''
|
||||
}, user.accessToken)
|
||||
.then(res => {
|
||||
toast({
|
||||
title: res.status,
|
||||
description: "item ditambahkan",
|
||||
status: "success",
|
||||
duration: 4000,
|
||||
isClosable: true,
|
||||
position: "top-right"
|
||||
})
|
||||
props.history.push('/products')
|
||||
})
|
||||
.catch((err) => {
|
||||
setError(err.message)
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmit(false)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Breadcrumb main={["/products", "produk", "baru"]}/>
|
||||
<Card>
|
||||
{error !== null && (
|
||||
<Alert status="error" mb="5" rounded="md">
|
||||
<AlertIcon />
|
||||
{error}
|
||||
</Alert>
|
||||
)}
|
||||
<FormInput data={['nama', name, setName]}/>
|
||||
<FormInput data={['deskripsi', description, setDescription]}/>
|
||||
<FormInputNumber data={['harga beli', cost, setCost]} onClick={() => setCost('')}/>
|
||||
<FormInputNumber data={['harga jual', price, setPrice]} onClick={() => setPrice('')}/>
|
||||
<FormInputNumber data={['stok', stock, setStock]}/>
|
||||
<FormInput data={['kategori', category ? category.name : '']} readOnly={true}/>
|
||||
<Button mt="4">simpan</Button>
|
||||
<FormInputSelection
|
||||
data={['kategori', category.name]}
|
||||
readOnly={true}
|
||||
onFormClick={() => toggle()}
|
||||
/>
|
||||
<Button
|
||||
mt="4"
|
||||
isLoading={submit}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
simpan
|
||||
</Button>
|
||||
</Card>
|
||||
<CategoryModalSelection
|
||||
isOpen={isOpen}
|
||||
toggle={toggle}
|
||||
onClose={(category) => {
|
||||
setCategory(category)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export default function Detail(props) {
|
||||
const id = props.match.params.id
|
||||
|
||||
return (
|
||||
<div>Product: { id }</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
import { Alert, AlertIcon, Button, useToast } from "@chakra-ui/react"
|
||||
import { useState, useEffect } from "react"
|
||||
import {
|
||||
Breadcrumb,
|
||||
Card,
|
||||
FormInput,
|
||||
FormInputNumber,
|
||||
FormInputSelection,
|
||||
Loading,
|
||||
useModalState
|
||||
} from "../../components/Common"
|
||||
import { getProduct, updateProduct } from "./Api"
|
||||
import CategoryModalSelection from "../categories/Modal"
|
||||
import { useAuth } from "../../context/AppContext"
|
||||
import { formatIDR } from "../../utils"
|
||||
|
||||
export default function Edit(props) {
|
||||
const id = props.match.params.id
|
||||
const { user } = useAuth()
|
||||
|
||||
const [name, setName] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
const [cost, setCost] = useState(0)
|
||||
const [price, setPrice] = useState(0)
|
||||
const [stock, setStock] = useState(0)
|
||||
const [category, setCategory] = useState({name: ''})
|
||||
|
||||
const toast = useToast()
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [submit, setSubmit] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const [isOpen, toggle] = useModalState()
|
||||
|
||||
const handleSubmit = () => {
|
||||
setSubmit(true)
|
||||
updateProduct(id, {
|
||||
name,
|
||||
description,
|
||||
cost,
|
||||
price,
|
||||
stock,
|
||||
category_id: category ? category.id : ''
|
||||
}, user.accessToken)
|
||||
.then(res => {
|
||||
toast({
|
||||
title: res.status,
|
||||
description: "item diubah",
|
||||
status: "success",
|
||||
duration: 4000,
|
||||
isClosable: true,
|
||||
position: "top-right"
|
||||
})
|
||||
props.history.push('/products')
|
||||
})
|
||||
.catch((err) => {
|
||||
setError(err.message)
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmit(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
getProduct(id, user.accessToken)
|
||||
.then(res => {
|
||||
setName(res.product.name)
|
||||
setDescription(res.product.description)
|
||||
setPrice(res.product.price)
|
||||
setCost(res.product.cost)
|
||||
setStock(res.product.stock)
|
||||
setCategory({
|
||||
id: res.product.category_id,
|
||||
name: res.product.category_name
|
||||
})
|
||||
})
|
||||
.catch(err => setError(err))
|
||||
.finally(() => setLoading(false))
|
||||
return () => {}
|
||||
}, [id, user])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Breadcrumb main={["/products", "produk", "ubah"]}/>
|
||||
<Card>
|
||||
{error !== null && (
|
||||
<Alert status="error" mb="5" rounded="md">
|
||||
<AlertIcon />
|
||||
{error}
|
||||
</Alert>
|
||||
)}
|
||||
{loading ? (
|
||||
<Loading/>
|
||||
) : (
|
||||
<>
|
||||
<FormInput data={['nama', name, setName]}/>
|
||||
<FormInput data={['deskripsi', description, setDescription]}/>
|
||||
<FormInputNumber data={['harga beli', formatIDR(cost), setCost]}/>
|
||||
<FormInputNumber data={['harga jual', formatIDR(price), setPrice]}/>
|
||||
<FormInputNumber data={['stok', formatIDR(stock), setStock]}/>
|
||||
<FormInputSelection
|
||||
data={['kategori', category.name]}
|
||||
readOnly={true}
|
||||
onFormClick={() => toggle()}
|
||||
/>
|
||||
<Button
|
||||
mt="4"
|
||||
isLoading={submit}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
simpan
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
<CategoryModalSelection
|
||||
isOpen={isOpen}
|
||||
toggle={toggle}
|
||||
onClose={(category) => {
|
||||
setCategory(category)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue