mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-212): enhance PurchaseOrderStaffApprovalForm to dynamically determine form type and validate product selection for duplicates
This commit is contained in:
@@ -33,6 +33,7 @@ import {
|
||||
Purchase,
|
||||
} from '@/types/api/purchase/purchase';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useApprovalSteps } from '@/components/pages/ApprovalSteps';
|
||||
|
||||
interface PurchaseOrderStaffApprovalFormProps {
|
||||
type?: 'add' | 'edit';
|
||||
@@ -44,13 +45,43 @@ interface PurchaseOrderStaffApprovalFormProps {
|
||||
}
|
||||
|
||||
const PurchaseOrderStaffApprovalForm = ({
|
||||
type = 'add',
|
||||
type: propType,
|
||||
initialValues,
|
||||
onCancel,
|
||||
refreshApprovals,
|
||||
onModalClose,
|
||||
onRefetchData,
|
||||
}: PurchaseOrderStaffApprovalFormProps) => {
|
||||
const { rawDataApprovals } = useApprovalSteps({
|
||||
latestApproval: initialValues?.approval,
|
||||
approvalLines: [],
|
||||
moduleName: 'PURCHASES',
|
||||
moduleId: initialValues?.id?.toString() ?? '',
|
||||
params: {
|
||||
limit: 100,
|
||||
group_step_number: true,
|
||||
},
|
||||
});
|
||||
|
||||
const type = useMemo(() => {
|
||||
if (propType && (propType === 'add' || propType === 'edit')) {
|
||||
return propType;
|
||||
}
|
||||
|
||||
if (!rawDataApprovals || rawDataApprovals.length === 0) {
|
||||
return 'add';
|
||||
}
|
||||
|
||||
const firstApproval = rawDataApprovals[0];
|
||||
const hasOnlyInitialStep =
|
||||
rawDataApprovals.length === 1 &&
|
||||
firstApproval?.step_number === 1 &&
|
||||
'action' in firstApproval &&
|
||||
firstApproval.action === 'CREATED';
|
||||
|
||||
return hasOnlyInitialStep ? 'add' : 'edit';
|
||||
}, [rawDataApprovals, propType]);
|
||||
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const deleteModal = useModal();
|
||||
@@ -68,8 +99,6 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
if (!initialValues?.approval) return false;
|
||||
|
||||
const currentStep = initialValues.approval.step_number;
|
||||
// Allow editing from step 3 onwards
|
||||
// Hide delete/add buttons from step 4 onwards
|
||||
return currentStep >= 3;
|
||||
}, [initialValues?.approval]);
|
||||
|
||||
@@ -77,8 +106,6 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
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]);
|
||||
|
||||
@@ -231,18 +258,31 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
(url: string) => SupplierApi.getSingle(Number(url.split('/').pop()))
|
||||
);
|
||||
|
||||
const supplierProductOptions = useMemo(() => {
|
||||
const baseSupplierProductOptions: OptionType[] = useMemo(() => {
|
||||
if (!supplierData || !isResponseSuccess(supplierData)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const supplier = supplierData.data as SupplierProducts;
|
||||
const products = supplier.products || [];
|
||||
|
||||
if (type === 'edit' && initialValues?.items) {
|
||||
const currentProductIds = initialValues.items.map(
|
||||
(item) => item.product_id
|
||||
);
|
||||
return products
|
||||
.filter((product) => currentProductIds.includes(product.id))
|
||||
.map((product) => ({
|
||||
value: product.id,
|
||||
label: product.name,
|
||||
}));
|
||||
}
|
||||
|
||||
return products.map((product) => ({
|
||||
value: product.id,
|
||||
label: product.name,
|
||||
}));
|
||||
}, [supplierData]);
|
||||
}, [supplierData, type, initialValues?.items]);
|
||||
|
||||
// ===== FORM CONFIGURATION =====
|
||||
const formikInitialValues = useMemo(() => {
|
||||
@@ -364,6 +404,8 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
},
|
||||
});
|
||||
|
||||
const supplierProductOptions = baseSupplierProductOptions;
|
||||
|
||||
// ===== API DATA FETCHING =====
|
||||
const purchaseItems = useMemo(() => {
|
||||
if (initialValues?.items) {
|
||||
@@ -426,6 +468,10 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
const itemData = {
|
||||
purchase_item_id: purchaseItem.id,
|
||||
product_id: purchaseItem.product_id || 0,
|
||||
product: {
|
||||
value: purchaseItem.product_id || 0,
|
||||
label: purchaseItem.product?.name || '',
|
||||
},
|
||||
warehouse_id: purchaseItem.warehouse_id || 0,
|
||||
qty: originalItem?.qty || purchaseItem.quantity || 0,
|
||||
price: type === 'edit' && originalItem ? originalItem.price : '',
|
||||
@@ -493,6 +539,34 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
const product = val as OptionType | null;
|
||||
const productId = (product as OptionType)?.value || 0;
|
||||
|
||||
if (Number(productId) > 0) {
|
||||
const currentItem = formik.values.items?.[idx];
|
||||
const warehouseId = currentItem?.warehouse_id || 0;
|
||||
|
||||
const isDuplicate = formik.values.items?.some(
|
||||
(item, itemIdx) =>
|
||||
itemIdx !== idx &&
|
||||
item.product_id === productId &&
|
||||
item.warehouse_id === warehouseId
|
||||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
const existingItem = formik.values.items?.find(
|
||||
(item, itemIdx) =>
|
||||
itemIdx !== idx &&
|
||||
item.product_id === productId &&
|
||||
item.warehouse_id === warehouseId
|
||||
);
|
||||
const existingProductName =
|
||||
existingItem?.product?.label || 'produk ini';
|
||||
|
||||
toast.error(
|
||||
`Tidak bisa menambahkan item yang sama. ${existingProductName} sudah ada di gudang ini.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
formik.setFieldTouched(`items.${idx}.product`, true);
|
||||
formik.setFieldValue(`items.${idx}.product`, product);
|
||||
formik.setFieldTouched(`items.${idx}.product_id`, true);
|
||||
@@ -568,7 +642,9 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
Total (Rp.)
|
||||
<span className='text-error'>*</span>
|
||||
</th>
|
||||
{canShowDeleteAddButtons && <th>Action</th>}
|
||||
{canShowDeleteAddButtons && type === 'edit' && (
|
||||
<th>Action</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -595,14 +671,16 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
<td>
|
||||
<SelectInput
|
||||
key={`product-${purchaseItem.id}`}
|
||||
value={{
|
||||
value: purchaseItem?.product_id || 0,
|
||||
label:
|
||||
purchaseItem?.product?.name || '',
|
||||
}}
|
||||
value={
|
||||
formItem?.product as OptionType | null
|
||||
}
|
||||
onChange={(val) =>
|
||||
handleProductChange(formItemIndex, val)
|
||||
}
|
||||
options={supplierProductOptions}
|
||||
isClearable={false}
|
||||
isSearchable={false}
|
||||
isDisabled={type === 'add'}
|
||||
className={{
|
||||
wrapper:
|
||||
'min-w-52 md:min-w-72 lg:min-w-80',
|
||||
@@ -770,7 +848,9 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
<td>
|
||||
<SelectInput
|
||||
required
|
||||
value={formItem.product as OptionType | null}
|
||||
value={
|
||||
formItem.product as OptionType | null
|
||||
}
|
||||
onChange={(val) =>
|
||||
handleProductChange(idx, val)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user