236 lines
6.9 KiB
TypeScript
236 lines
6.9 KiB
TypeScript
// React Imports
|
|
import { useMemo, useState } from 'react'
|
|
|
|
// MUI Imports
|
|
import Button from '@mui/material/Button'
|
|
import Divider from '@mui/material/Divider'
|
|
import Drawer from '@mui/material/Drawer'
|
|
import IconButton from '@mui/material/IconButton'
|
|
import Typography from '@mui/material/Typography'
|
|
|
|
// Third-party Imports
|
|
|
|
// Type Imports
|
|
|
|
// Components Imports
|
|
import CustomTextField from '@core/components/mui/TextField'
|
|
import { Autocomplete, CircularProgress, MenuItem } from '@mui/material'
|
|
import { useDebounce } from 'use-debounce'
|
|
import { useInventoriesMutation } from '../../../../../services/mutations/inventories'
|
|
import { useOutlets } from '../../../../../services/queries/outlets'
|
|
import { useProducts } from '../../../../../services/queries/products'
|
|
import { InventoryRestockRequest, Item } from '../../../../../types/services/inventory'
|
|
|
|
type Props = {
|
|
open: boolean
|
|
handleClose: () => void
|
|
}
|
|
|
|
const AdjustmentStockDrawer = (props: Props) => {
|
|
// Props
|
|
const { open, handleClose } = props
|
|
|
|
const { restockInventory } = useInventoriesMutation()
|
|
|
|
// States
|
|
const [productInput, setProductInput] = useState('')
|
|
const [productDebouncedInput] = useDebounce(productInput, 500) // debounce for better UX
|
|
const [outletInput, setOutletInput] = useState('')
|
|
const [outletDebouncedInput] = useDebounce(outletInput, 500) // debounce for better UX
|
|
const [formData, setFormData] = useState<InventoryRestockRequest>({
|
|
outlet_id: '',
|
|
items: [
|
|
{
|
|
item_id: '',
|
|
item_type: '',
|
|
quantity: 0
|
|
}
|
|
],
|
|
reason: ''
|
|
})
|
|
|
|
const { data: outlets, isLoading: outletsLoading } = useOutlets({
|
|
search: outletDebouncedInput
|
|
})
|
|
const { data: products, isLoading } = useProducts({
|
|
search: productDebouncedInput
|
|
})
|
|
|
|
const outletOptions = useMemo(() => outlets?.outlets || [], [outlets])
|
|
const options = useMemo(() => products?.products || [], [products])
|
|
|
|
// Handle Form Submit
|
|
const handleFormSubmit = (e: any) => {
|
|
e.preventDefault()
|
|
|
|
restockInventory.mutate(formData, {
|
|
onSuccess: () => {
|
|
handleReset()
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleInputChange = (e: any) => {
|
|
setFormData({
|
|
...formData,
|
|
[e.target.name]: e.target.value
|
|
})
|
|
}
|
|
|
|
// Handle Form Reset
|
|
const handleReset = () => {
|
|
handleClose()
|
|
setFormData({
|
|
outlet_id: '',
|
|
items: [
|
|
{
|
|
item_id: '',
|
|
item_type: '',
|
|
quantity: 0
|
|
}
|
|
],
|
|
reason: ''
|
|
})
|
|
}
|
|
|
|
return (
|
|
<Drawer
|
|
open={open}
|
|
anchor='right'
|
|
variant='temporary'
|
|
onClose={handleReset}
|
|
ModalProps={{ keepMounted: true }}
|
|
sx={{ '& .MuiDrawer-paper': { width: { xs: 300, sm: 400 } } }}
|
|
>
|
|
<div className='flex items-center justify-between pli-6 plb-5'>
|
|
<Typography variant='h5'>Re Stock</Typography>
|
|
<IconButton size='small' onClick={handleReset}>
|
|
<i className='tabler-x text-textSecondary text-2xl' />
|
|
</IconButton>
|
|
</div>
|
|
<Divider />
|
|
<div className='p-6'>
|
|
<form onSubmit={handleFormSubmit} className='flex flex-col gap-5'>
|
|
<Autocomplete
|
|
options={outletOptions}
|
|
loading={outletsLoading}
|
|
getOptionLabel={option => option.name}
|
|
value={outletOptions.find(p => p.id === formData.outlet_id) || null}
|
|
onInputChange={(event, newOutlettInput) => {
|
|
setOutletInput(newOutlettInput)
|
|
}}
|
|
onChange={(event, newValue) => {
|
|
setFormData({
|
|
...formData,
|
|
outlet_id: newValue?.id || ''
|
|
})
|
|
}}
|
|
renderInput={params => (
|
|
<CustomTextField
|
|
{...params}
|
|
className=''
|
|
label='Outlet'
|
|
fullWidth
|
|
InputProps={{
|
|
...params.InputProps,
|
|
endAdornment: (
|
|
<>
|
|
{outletsLoading && <CircularProgress size={18} />}
|
|
{params.InputProps.endAdornment}
|
|
</>
|
|
)
|
|
}}
|
|
/>
|
|
)}
|
|
/>
|
|
<CustomTextField
|
|
select
|
|
fullWidth
|
|
label='Item Type'
|
|
value={formData.items[0]?.item_type || ''}
|
|
onChange={e => setFormData({ ...formData, items: [{ ...formData.items[0], item_type: e.target.value }] })}
|
|
>
|
|
<MenuItem value='PRODUCT'>Product</MenuItem>
|
|
<MenuItem value='IGREDIENT'>Ingredient</MenuItem>
|
|
</CustomTextField>
|
|
<Autocomplete
|
|
options={options}
|
|
loading={isLoading}
|
|
getOptionLabel={option => option.name}
|
|
value={options.find(p => p.id === formData.items[0].item_id) || null}
|
|
onInputChange={(event, newProductInput) => {
|
|
setProductInput(newProductInput)
|
|
}}
|
|
onChange={(event, newValue) => {
|
|
setFormData({
|
|
...formData,
|
|
items: [
|
|
{
|
|
...formData.items[0],
|
|
item_id: newValue?.id || ''
|
|
}
|
|
]
|
|
})
|
|
}}
|
|
renderInput={params => (
|
|
<CustomTextField
|
|
{...params}
|
|
className=''
|
|
label='Product'
|
|
fullWidth
|
|
InputProps={{
|
|
...params.InputProps,
|
|
endAdornment: (
|
|
<>
|
|
{isLoading && <CircularProgress size={18} />}
|
|
{params.InputProps.endAdornment}
|
|
</>
|
|
)
|
|
}}
|
|
/>
|
|
)}
|
|
/>
|
|
<CustomTextField
|
|
fullWidth
|
|
label='Quantity'
|
|
name='quantity'
|
|
value={formData.items[0].quantity}
|
|
onChange={e =>
|
|
setFormData({
|
|
...formData,
|
|
items: [
|
|
{
|
|
...formData.items[0],
|
|
quantity: e.target.value
|
|
}
|
|
]
|
|
})
|
|
}
|
|
placeholder='0'
|
|
/>
|
|
<CustomTextField
|
|
fullWidth
|
|
label='Reason'
|
|
value={formData.reason}
|
|
name='reason'
|
|
onChange={handleInputChange}
|
|
multiline
|
|
rows={4}
|
|
placeholder='Write a Comment...'
|
|
/>
|
|
<div className='flex items-center gap-4'>
|
|
<Button variant='contained' type='submit' disabled={restockInventory.isPending}>
|
|
{restockInventory.isPending ? 'Saving...' : 'Save'}
|
|
</Button>
|
|
<Button variant='tonal' color='error' type='reset' onClick={handleReset}>
|
|
Discard
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</Drawer>
|
|
)
|
|
}
|
|
|
|
export default AdjustmentStockDrawer
|