236 lines
6.9 KiB
TypeScript
Raw Normal View History

2025-08-06 03:57:45 +07:00
// 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'
2025-08-14 03:09:00 +07:00
import { Autocomplete, CircularProgress, MenuItem } from '@mui/material'
2025-08-06 03:57:45 +07:00
import { useDebounce } from 'use-debounce'
2025-08-07 14:31:42 +07:00
import { useInventoriesMutation } from '../../../../../services/mutations/inventories'
import { useOutlets } from '../../../../../services/queries/outlets'
import { useProducts } from '../../../../../services/queries/products'
2025-08-14 03:09:00 +07:00
import { InventoryRestockRequest, Item } from '../../../../../types/services/inventory'
2025-08-06 03:57:45 +07:00
type Props = {
open: boolean
handleClose: () => void
}
const AdjustmentStockDrawer = (props: Props) => {
// Props
const { open, handleClose } = props
2025-08-14 03:09:00 +07:00
const { restockInventory } = useInventoriesMutation()
2025-08-06 03:57:45 +07:00
// 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
2025-08-14 03:09:00 +07:00
const [formData, setFormData] = useState<InventoryRestockRequest>({
2025-08-06 03:57:45 +07:00
outlet_id: '',
2025-08-14 03:09:00 +07:00
items: [
{
item_id: '',
item_type: '',
quantity: 0
}
],
2025-08-06 03:57:45 +07:00
reason: ''
})
2025-08-06 14:41:23 +07:00
const { data: outlets, isLoading: outletsLoading } = useOutlets({
2025-08-06 03:57:45 +07:00
search: outletDebouncedInput
})
2025-08-06 14:41:23 +07:00
const { data: products, isLoading } = useProducts({
2025-08-06 03:57:45 +07:00
search: productDebouncedInput
})
const outletOptions = useMemo(() => outlets?.outlets || [], [outlets])
const options = useMemo(() => products?.products || [], [products])
// Handle Form Submit
const handleFormSubmit = (e: any) => {
e.preventDefault()
2025-08-14 03:09:00 +07:00
restockInventory.mutate(formData, {
onSuccess: () => {
handleReset()
2025-08-06 03:57:45 +07:00
}
2025-08-14 03:09:00 +07:00
})
2025-08-06 03:57:45 +07:00
}
const handleInputChange = (e: any) => {
setFormData({
...formData,
[e.target.name]: e.target.value
})
}
// Handle Form Reset
const handleReset = () => {
handleClose()
setFormData({
outlet_id: '',
2025-08-14 03:09:00 +07:00
items: [
{
item_id: '',
item_type: '',
quantity: 0
}
],
2025-08-06 03:57:45 +07:00
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'>
2025-08-14 01:29:40 +07:00
<Typography variant='h5'>Re Stock</Typography>
2025-08-06 03:57:45 +07:00
<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}
</>
)
}}
/>
)}
/>
2025-08-14 03:09:00 +07:00
<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>
2025-08-06 03:57:45 +07:00
<Autocomplete
options={options}
loading={isLoading}
getOptionLabel={option => option.name}
2025-08-14 03:09:00 +07:00
value={options.find(p => p.id === formData.items[0].item_id) || null}
2025-08-06 03:57:45 +07:00
onInputChange={(event, newProductInput) => {
setProductInput(newProductInput)
}}
onChange={(event, newValue) => {
setFormData({
...formData,
2025-08-14 03:09:00 +07:00
items: [
{
...formData.items[0],
item_id: newValue?.id || ''
}
]
2025-08-06 03:57:45 +07:00
})
}}
renderInput={params => (
<CustomTextField
{...params}
className=''
label='Product'
fullWidth
InputProps={{
...params.InputProps,
endAdornment: (
<>
{isLoading && <CircularProgress size={18} />}
{params.InputProps.endAdornment}
</>
)
}}
/>
)}
/>
<CustomTextField
fullWidth
2025-08-14 03:09:00 +07:00
label='Quantity'
name='quantity'
value={formData.items[0].quantity}
onChange={e =>
setFormData({
...formData,
items: [
{
...formData.items[0],
quantity: e.target.value
}
]
})
}
2025-08-06 03:57:45 +07:00
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'>
2025-08-14 03:09:00 +07:00
<Button variant='contained' type='submit' disabled={restockInventory.isPending}>
{restockInventory.isPending ? 'Saving...' : 'Save'}
2025-08-06 03:57:45 +07:00
</Button>
<Button variant='tonal' color='error' type='reset' onClick={handleReset}>
Discard
</Button>
</div>
</form>
</div>
</Drawer>
)
}
export default AdjustmentStockDrawer