204 lines
6.0 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'
import { Autocomplete, CircularProgress } from '@mui/material'
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'
import { InventoryAdjustRequest } 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-06 14:41:23 +07:00
const { mutate: adjustInventory, isPending: isCreating } = useInventoriesMutation().adjustInventory
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
const [formData, setFormData] = useState<InventoryAdjustRequest>({
product_id: '',
outlet_id: '',
delta: 0,
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()
adjustInventory(
{ ...formData, delta: Number(formData.delta) },
{
onSuccess: () => {
handleReset()
}
}
)
}
const handleInputChange = (e: any) => {
setFormData({
...formData,
[e.target.name]: e.target.value
})
}
// Handle Form Reset
const handleReset = () => {
handleClose()
setFormData({
product_id: '',
outlet_id: '',
delta: 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'>Adjust Inventory</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}
</>
)
}}
/>
)}
/>
<Autocomplete
options={options}
loading={isLoading}
getOptionLabel={option => option.name}
value={options.find(p => p.id === formData.product_id) || null}
onInputChange={(event, newProductInput) => {
setProductInput(newProductInput)
}}
onChange={(event, newValue) => {
setFormData({
...formData,
product_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='Delta'
name='delta'
value={formData.delta}
onChange={handleInputChange}
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={isCreating}>
{isCreating ? 'Adjusting...' : 'Adjust'}
</Button>
<Button variant='tonal' color='error' type='reset' onClick={handleReset}>
Discard
</Button>
</div>
</form>
</div>
</Drawer>
)
}
export default AdjustmentStockDrawer