refactor(FE-208,212,213): update PurchaseOrderForm and PurchaseOrderStaffApprovalForm to allow optional product and warehouse fields and control visibility of action buttons based on approval step

This commit is contained in:
rstubryan
2025-11-22 00:52:23 +07:00
parent 5b28067203
commit 30ab69ae21
2 changed files with 56 additions and 41 deletions
@@ -9,12 +9,12 @@ type PurchaseRequestStaffApprovalFormSchemaType = {
product_id?: number | null; product_id?: number | null;
warehouse_id?: number | null; warehouse_id?: number | null;
product?: { product?: {
value: number; value?: number;
label: string; label?: string;
} | null; } | null;
warehouse?: { warehouse?: {
value: number; value?: number;
label: string; label?: string;
} | null; } | null;
qty: number; qty: number;
price: number | string; price: number | string;
@@ -54,12 +54,12 @@ export type PurchaseStaffApprovalItemSchema = {
product_id?: number | null; product_id?: number | null;
warehouse_id?: number | null; warehouse_id?: number | null;
product?: { product?: {
value: number; value?: number;
label: string; label?: string;
} | null; } | null;
warehouse?: { warehouse?: {
value: number; value?: number;
label: string; label?: string;
} | null; } | null;
qty: number; qty: number;
price: number | string; price: number | string;
@@ -97,8 +97,8 @@ const PurchaseStaffApprovalItemObjectSchema: Yup.ObjectSchema<PurchaseStaffAppro
.min(0, 'Purchase item ID tidak valid!') .min(0, 'Purchase item ID tidak valid!')
.typeError('Purchase item ID harus berupa angka!'), .typeError('Purchase item ID harus berupa angka!'),
product: Yup.object({ product: Yup.object({
value: Yup.number().required(), value: Yup.number(),
label: Yup.string().required(), label: Yup.string(),
}) })
.nullable() .nullable()
.optional(), .optional(),
@@ -107,8 +107,8 @@ const PurchaseStaffApprovalItemObjectSchema: Yup.ObjectSchema<PurchaseStaffAppro
.nullable() .nullable()
.typeError('Product ID harus berupa angka!'), .typeError('Product ID harus berupa angka!'),
warehouse: Yup.object({ warehouse: Yup.object({
value: Yup.number().required(), value: Yup.number(),
label: Yup.string().required(), label: Yup.string(),
}) })
.nullable() .nullable()
.optional(), .optional(),
@@ -68,9 +68,20 @@ const PurchaseOrderStaffApprovalForm = ({
if (!initialValues?.approval) return false; if (!initialValues?.approval) return false;
const currentStep = initialValues.approval.step_number; const currentStep = initialValues.approval.step_number;
// Allow editing from step 3 onwards
// Hide delete/add buttons from step 4 onwards
return currentStep >= 3; return currentStep >= 3;
}, [initialValues?.approval]); }, [initialValues?.approval]);
const canShowDeleteAddButtons = useMemo(() => {
if (!initialValues?.approval) return false;
const currentStep = initialValues.approval.step_number;
// Show delete/add buttons only up to step 3
// Hide from step 4 onwards
return currentStep < 4;
}, [initialValues?.approval]);
const isRepeaterInputError = ( const isRepeaterInputError = (
idx: number, idx: number,
field: 'price' | 'total_price' | 'product_id' | 'warehouse_id' field: 'price' | 'total_price' | 'product_id' | 'warehouse_id'
@@ -344,6 +355,7 @@ const PurchaseOrderStaffApprovalForm = ({
notes: values.notes || null, notes: values.notes || null,
items: updateItemsPayload, items: updateItemsPayload,
}; };
await updateStaffApprovalHandler( await updateStaffApprovalHandler(
initialValues?.id as number, initialValues?.id as number,
updatePayload updatePayload
@@ -556,7 +568,7 @@ const PurchaseOrderStaffApprovalForm = ({
Total (Rp.) Total (Rp.)
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th>Action</th> {canShowDeleteAddButtons && <th>Action</th>}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -725,22 +737,23 @@ const PurchaseOrderStaffApprovalForm = ({
</td> </td>
<td> <td>
<div className='flex justify-center'> <div className='flex justify-center'>
{canUpdatePurchaseItems && ( {canUpdatePurchaseItems &&
<Button canShowDeleteAddButtons && (
type='button' <Button
color='error' type='button'
onClick={() => color='error'
removePurchaseItem(formItemIndex) onClick={() =>
} removePurchaseItem(formItemIndex)
title='Hapus item' }
> title='Hapus item'
<Icon >
icon='mdi:trash-can' <Icon
width={16} icon='mdi:trash-can'
height={16} width={16}
/> height={16}
</Button> />
)} </Button>
)}
</div> </div>
</td> </td>
</tr> </tr>
@@ -757,7 +770,7 @@ const PurchaseOrderStaffApprovalForm = ({
<td> <td>
<SelectInput <SelectInput
required required
value={formItem.product} value={formItem.product as OptionType | null}
onChange={(val) => onChange={(val) =>
handleProductChange(idx, val) handleProductChange(idx, val)
} }
@@ -916,17 +929,19 @@ const PurchaseOrderStaffApprovalForm = ({
</div> </div>
{/* Add Item Button */} {/* Add Item Button */}
<div className='flex justify-center items-center mt-4'> {canShowDeleteAddButtons && (
<Button <div className='flex justify-center items-center mt-4'>
type='button' <Button
color='success' type='button'
onClick={addPurchaseItem} color='success'
className='w-fit' onClick={addPurchaseItem}
> className='w-fit'
<Icon icon='ic:round-plus' width={24} height={24} /> >
Tambah Item Baru <Icon icon='ic:round-plus' width={24} height={24} />
</Button> Tambah Item Baru
</div> </Button>
</div>
)}
{/* Add divider after table except for last item */} {/* Add divider after table except for last item */}
{index < groupedPurchaseItems.length - 1 && ( {index < groupedPurchaseItems.length - 1 && (