Add Waste at Product Recipe
This commit is contained in:
parent
aa2946e627
commit
fab31f1540
@ -42,6 +42,7 @@ export interface ProductRecipe {
|
|||||||
variant_id: string | null
|
variant_id: string | null
|
||||||
ingredient_id: string
|
ingredient_id: string
|
||||||
quantity: number
|
quantity: number
|
||||||
|
waste: number
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_at: string
|
updated_at: string
|
||||||
product: Product
|
product: Product
|
||||||
@ -54,6 +55,7 @@ export interface ProductRecipeRequest {
|
|||||||
ingredient_id: string
|
ingredient_id: string
|
||||||
quantity: number
|
quantity: number
|
||||||
outlet_id: string | null
|
outlet_id: string | null
|
||||||
|
waste: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IngredientUnit {
|
export interface IngredientUnit {
|
||||||
|
|||||||
@ -11,8 +11,6 @@ import Typography from '@mui/material/Typography'
|
|||||||
// Third-party Imports
|
// Third-party Imports
|
||||||
import PerfectScrollbar from 'react-perfect-scrollbar'
|
import PerfectScrollbar from 'react-perfect-scrollbar'
|
||||||
|
|
||||||
// Type Imports
|
|
||||||
|
|
||||||
// Component Imports
|
// Component Imports
|
||||||
import CustomTextField from '@core/components/mui/TextField'
|
import CustomTextField from '@core/components/mui/TextField'
|
||||||
import { Autocomplete } from '@mui/material'
|
import { Autocomplete } from '@mui/material'
|
||||||
@ -25,6 +23,7 @@ import { useOutlets } from '../../../../../services/queries/outlets'
|
|||||||
import { Product } from '../../../../../types/services/product'
|
import { Product } from '../../../../../types/services/product'
|
||||||
import { ProductRecipeRequest } from '../../../../../types/services/productRecipe'
|
import { ProductRecipeRequest } from '../../../../../types/services/productRecipe'
|
||||||
import { resetProductVariant } from '../../../../../redux-store/slices/productRecipe'
|
import { resetProductVariant } from '../../../../../redux-store/slices/productRecipe'
|
||||||
|
import { IngredientItem } from '@/types/services/ingredient'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
open: boolean
|
open: boolean
|
||||||
@ -38,7 +37,8 @@ const initialData = {
|
|||||||
product_id: '',
|
product_id: '',
|
||||||
variant_id: '',
|
variant_id: '',
|
||||||
ingredient_id: '',
|
ingredient_id: '',
|
||||||
quantity: 0
|
quantity: 0,
|
||||||
|
waste: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddRecipeDrawer = (props: Props) => {
|
const AddRecipeDrawer = (props: Props) => {
|
||||||
@ -55,23 +55,45 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
const [ingredientDebouncedInput] = useDebounce(ingredientInput, 500)
|
const [ingredientDebouncedInput] = useDebounce(ingredientInput, 500)
|
||||||
const [formData, setFormData] = useState<ProductRecipeRequest>(initialData)
|
const [formData, setFormData] = useState<ProductRecipeRequest>(initialData)
|
||||||
|
|
||||||
|
// Add state untuk menyimpan selected ingredient
|
||||||
|
const [selectedIngredient, setSelectedIngredient] = useState<IngredientItem | null>(null)
|
||||||
|
|
||||||
const { data: outlets, isLoading: outletsLoading } = useOutlets({
|
const { data: outlets, isLoading: outletsLoading } = useOutlets({
|
||||||
search: outletDebouncedInput
|
search: outletDebouncedInput
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Modifikasi query ingredients dengan enabled condition
|
||||||
const { data: ingredients, isLoading: ingredientsLoading } = useIngredients({
|
const { data: ingredients, isLoading: ingredientsLoading } = useIngredients({
|
||||||
search: ingredientDebouncedInput
|
search: ingredientDebouncedInput
|
||||||
})
|
})
|
||||||
|
|
||||||
const outletOptions = useMemo(() => outlets?.outlets || [], [outlets])
|
const outletOptions = useMemo(() => outlets?.outlets || [], [outlets])
|
||||||
const ingredientOptions = useMemo(() => ingredients?.data || [], [ingredients])
|
|
||||||
|
// Perbaiki ingredient options untuk include selected ingredient
|
||||||
|
const ingredientOptions = useMemo(() => {
|
||||||
|
const options = ingredients?.data || []
|
||||||
|
|
||||||
|
// Jika ada selected ingredient dan tidak ada di current options, tambahkan
|
||||||
|
if (selectedIngredient && !options.find(opt => opt.id === selectedIngredient.id)) {
|
||||||
|
return [selectedIngredient, ...options]
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}, [ingredients, selectedIngredient])
|
||||||
|
|
||||||
const { createProductRecipe, updateProductRecipe } = useProductRecipesMutation()
|
const { createProductRecipe, updateProductRecipe } = useProductRecipesMutation()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentProductRecipe.id) {
|
if (currentProductRecipe.id) {
|
||||||
setFormData(currentProductRecipe)
|
setFormData(currentProductRecipe)
|
||||||
|
|
||||||
|
// Set selected ingredient dari current product recipe
|
||||||
|
const currentIngredient = ingredients?.data?.find(ing => ing.id === currentProductRecipe.ingredient_id)
|
||||||
|
if (currentIngredient) {
|
||||||
|
setSelectedIngredient(currentIngredient)
|
||||||
}
|
}
|
||||||
}, [currentProductRecipe])
|
}
|
||||||
|
}, [currentProductRecipe, ingredients])
|
||||||
|
|
||||||
const handleSubmit = (e: any) => {
|
const handleSubmit = (e: any) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -101,24 +123,16 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
handleClose()
|
handleClose()
|
||||||
dispatch(resetProductVariant())
|
dispatch(resetProductVariant())
|
||||||
setFormData(initialData)
|
setFormData(initialData)
|
||||||
}
|
setSelectedIngredient(null) // Reset selected ingredient
|
||||||
|
setIngredientInput('') // Reset input
|
||||||
const handleInputChange = (e: any) => {
|
|
||||||
setFormData({
|
|
||||||
...formData,
|
|
||||||
[e.target.name]: e.target.value
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const setTitleDrawer = (recipe: any) => {
|
const setTitleDrawer = (recipe: any) => {
|
||||||
const addOrEdit = currentProductRecipe.id ? 'Edit ' : 'Add '
|
const addOrEdit = currentProductRecipe.id ? 'Edit ' : 'Add '
|
||||||
|
|
||||||
let title = 'Original'
|
let title = 'Original'
|
||||||
|
|
||||||
if (recipe?.name) {
|
if (recipe?.name) {
|
||||||
title = recipe?.name
|
title = recipe?.name
|
||||||
}
|
}
|
||||||
|
|
||||||
return addOrEdit + title
|
return addOrEdit + title
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,13 +158,14 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
<Typography color='text.primary' className='font-medium'>
|
<Typography color='text.primary' className='font-medium'>
|
||||||
Basic Information
|
Basic Information
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
options={outletOptions}
|
options={outletOptions}
|
||||||
loading={outletsLoading}
|
loading={outletsLoading}
|
||||||
getOptionLabel={option => option.name}
|
getOptionLabel={option => option.name}
|
||||||
value={outletOptions.find(p => p.id === formData.outlet_id) || null}
|
value={outletOptions.find(p => p.id === formData.outlet_id) || null}
|
||||||
onInputChange={(event, newOutlettInput) => {
|
onInputChange={(event, newOutletInput) => {
|
||||||
setOutletInput(newOutlettInput)
|
setOutletInput(newOutletInput)
|
||||||
}}
|
}}
|
||||||
onChange={(event, newValue) => {
|
onChange={(event, newValue) => {
|
||||||
setFormData({
|
setFormData({
|
||||||
@ -161,7 +176,6 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
renderInput={params => (
|
renderInput={params => (
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
{...params}
|
{...params}
|
||||||
className=''
|
|
||||||
label='Outlet'
|
label='Outlet'
|
||||||
fullWidth
|
fullWidth
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@ -171,24 +185,35 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Perbaiki Autocomplete untuk Ingredients */}
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
options={ingredientOptions || []}
|
options={ingredientOptions || []}
|
||||||
loading={ingredientsLoading}
|
loading={ingredientsLoading}
|
||||||
getOptionLabel={option => option.name}
|
getOptionLabel={option => option.name}
|
||||||
value={ingredientOptions?.find(p => p.id === formData.ingredient_id) || null}
|
value={selectedIngredient}
|
||||||
onInputChange={(event, newIngredientInput) => {
|
onInputChange={(event, newIngredientInput) => {
|
||||||
setIngredientInput(newIngredientInput)
|
setIngredientInput(newIngredientInput)
|
||||||
}}
|
}}
|
||||||
onChange={(event, newValue) => {
|
onChange={(event, newValue) => {
|
||||||
|
setSelectedIngredient(newValue) // Set selected ingredient
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
ingredient_id: newValue?.id || ''
|
ingredient_id: newValue?.id || ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Clear input search setelah selection
|
||||||
|
if (newValue) {
|
||||||
|
setIngredientInput('')
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
// Tambahkan props untuk mencegah clear on blur
|
||||||
|
clearOnBlur={false}
|
||||||
|
// Handle case ketika input kosong tapi ada selected value
|
||||||
|
inputValue={selectedIngredient ? selectedIngredient.name : ingredientInput}
|
||||||
renderInput={params => (
|
renderInput={params => (
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
{...params}
|
{...params}
|
||||||
className=''
|
|
||||||
label='Ingredient'
|
label='Ingredient'
|
||||||
fullWidth
|
fullWidth
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@ -198,6 +223,18 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Unit Field - Disabled, value from selected ingredient */}
|
||||||
|
<CustomTextField
|
||||||
|
label='Unit'
|
||||||
|
fullWidth
|
||||||
|
disabled
|
||||||
|
value={selectedIngredient?.unit?.name || ''}
|
||||||
|
InputProps={{
|
||||||
|
readOnly: true
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
type='number'
|
type='number'
|
||||||
label='Quantity'
|
label='Quantity'
|
||||||
@ -205,6 +242,15 @@ const AddRecipeDrawer = (props: Props) => {
|
|||||||
value={formData.quantity}
|
value={formData.quantity}
|
||||||
onChange={e => setFormData({ ...formData, quantity: Number(e.target.value) })}
|
onChange={e => setFormData({ ...formData, quantity: Number(e.target.value) })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<CustomTextField
|
||||||
|
type='number'
|
||||||
|
label='Waste'
|
||||||
|
fullWidth
|
||||||
|
value={formData.waste}
|
||||||
|
onChange={e => setFormData({ ...formData, waste: Number(e.target.value) })}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className='flex items-center gap-4'>
|
<div className='flex items-center gap-4'>
|
||||||
<Button
|
<Button
|
||||||
variant='contained'
|
variant='contained'
|
||||||
|
|||||||
@ -161,7 +161,7 @@ const ProductDetail = () => {
|
|||||||
<TableCell className='font-semibold text-center'>
|
<TableCell className='font-semibold text-center'>
|
||||||
<div className='flex items-center justify-center gap-2'>
|
<div className='flex items-center justify-center gap-2'>
|
||||||
<i className='tabler-package text-blue-600' />
|
<i className='tabler-package text-blue-600' />
|
||||||
Stock Available
|
Waste
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className='font-semibold text-right'>
|
<TableCell className='font-semibold text-right'>
|
||||||
@ -197,12 +197,7 @@ const ProductDetail = () => {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className='text-center'>{formatCurrency(item.ingredient.cost)}</TableCell>
|
<TableCell className='text-center'>{formatCurrency(item.ingredient.cost)}</TableCell>
|
||||||
<TableCell className='text-center'>
|
<TableCell className='text-center'>
|
||||||
<Chip
|
<Chip label={item.waste ?? 0} size='small' color={'success'} variant='outlined' />
|
||||||
label={item.ingredient.stock}
|
|
||||||
size='small'
|
|
||||||
color={item.ingredient.stock > 5 ? 'success' : 'warning'}
|
|
||||||
variant='outlined'
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className='text-right font-medium'>
|
<TableCell className='text-right font-medium'>
|
||||||
{formatCurrency(item.ingredient.cost * item.quantity)}
|
{formatCurrency(item.ingredient.cost * item.quantity)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user