mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-208): implement conditional item deletion in PurchaseOrderDetail and update form handling in PurchaseOrderStaffApprovalForm
This commit is contained in:
@@ -252,7 +252,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
(item) => item.id === purchaseItem.id
|
(item) => item.id === purchaseItem.id
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
purchase_item_id: type === 'edit' ? purchaseItem.value : undefined,
|
purchase_item_id: purchaseItem.id,
|
||||||
product_id: purchaseItem.product_id || 0,
|
product_id: purchaseItem.product_id || 0,
|
||||||
warehouse_id: purchaseItem.warehouse_id || 0,
|
warehouse_id: purchaseItem.warehouse_id || 0,
|
||||||
qty: purchaseItem.quantity || 0,
|
qty: purchaseItem.quantity || 0,
|
||||||
@@ -266,36 +266,27 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
}, [purchaseItems, type, initialValues]);
|
}, [purchaseItems, type, initialValues]);
|
||||||
|
|
||||||
// ===== PURCHASE ITEM OPERATIONS =====
|
// ===== PURCHASE ITEM OPERATIONS =====
|
||||||
const findItemIndex = (purchaseItemId: number) => {
|
|
||||||
return purchaseItems.findIndex((item) => item.id === purchaseItemId);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePurchaseItemChange = (
|
const handlePurchaseItemChange = (
|
||||||
purchaseItemId: number,
|
purchaseItemId: number,
|
||||||
field: 'price' | 'total_price',
|
field: 'price' | 'total_price',
|
||||||
value: string | number
|
value: string | number
|
||||||
) => {
|
) => {
|
||||||
const itemIndex = findItemIndex(purchaseItemId);
|
|
||||||
const formItemIndex = formik.values.items?.findIndex(
|
const formItemIndex = formik.values.items?.findIndex(
|
||||||
(item) => item.purchase_item_id === purchaseItemId
|
(item) => item.purchase_item_id === purchaseItemId
|
||||||
);
|
);
|
||||||
|
const purchaseItem = purchaseItems.find(
|
||||||
|
(item) => item.id === purchaseItemId
|
||||||
|
);
|
||||||
|
|
||||||
if (itemIndex === -1 || formItemIndex === -1) return;
|
if (formItemIndex === -1 || !purchaseItem) return;
|
||||||
|
|
||||||
if (field === 'price' || field === 'total_price') {
|
if (field === 'price' || field === 'total_price') {
|
||||||
const numValue =
|
const numValue =
|
||||||
typeof value === 'string' ? parseFloat(value) || 0 : value;
|
typeof value === 'string' ? parseFloat(value) || 0 : value;
|
||||||
formik.setFieldValue(`items.${formItemIndex}.${field}`, numValue);
|
formik.setFieldValue(`items.${formItemIndex}.${field}`, numValue);
|
||||||
|
|
||||||
const selectedItem = purchaseItems[itemIndex];
|
if (field === 'price' && purchaseItem.quantity > 0 && numValue >= 0) {
|
||||||
|
const calculatedTotal = numValue * purchaseItem.quantity;
|
||||||
if (
|
|
||||||
field === 'price' &&
|
|
||||||
selectedItem &&
|
|
||||||
selectedItem.quantity > 0 &&
|
|
||||||
numValue >= 0
|
|
||||||
) {
|
|
||||||
const calculatedTotal = numValue * selectedItem.quantity;
|
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`items.${formItemIndex}.total_price`,
|
`items.${formItemIndex}.total_price`,
|
||||||
calculatedTotal
|
calculatedTotal
|
||||||
@@ -304,11 +295,10 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
field === 'total_price' &&
|
field === 'total_price' &&
|
||||||
selectedItem &&
|
purchaseItem.quantity > 0 &&
|
||||||
selectedItem.quantity > 0 &&
|
|
||||||
numValue >= 0
|
numValue >= 0
|
||||||
) {
|
) {
|
||||||
const calculatedPrice = numValue / selectedItem.quantity;
|
const calculatedPrice = numValue / purchaseItem.quantity;
|
||||||
formik.setFieldValue(`items.${formItemIndex}.price`, calculatedPrice);
|
formik.setFieldValue(`items.${formItemIndex}.price`, calculatedPrice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,6 +352,11 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
(item) =>
|
(item) =>
|
||||||
item.purchase_item_id === purchaseItem.id
|
item.purchase_item_id === purchaseItem.id
|
||||||
);
|
);
|
||||||
|
const formItemIndex =
|
||||||
|
formik.values.items?.findIndex(
|
||||||
|
(item) =>
|
||||||
|
item.purchase_item_id === purchaseItem.id
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<tr key={`purchase-item-${purchaseItem.id}`}>
|
<tr key={`purchase-item-${purchaseItem.id}`}>
|
||||||
<td>
|
<td>
|
||||||
@@ -383,7 +378,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`items.${purchaseItem.id}.product_category`}
|
name={`items.${formItemIndex}.product_category`}
|
||||||
type='text'
|
type='text'
|
||||||
value={
|
value={
|
||||||
typeof purchaseItem?.product
|
typeof purchaseItem?.product
|
||||||
@@ -403,7 +398,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`items.${purchaseItem.id}.quantity`}
|
name={`items.${formItemIndex}.quantity`}
|
||||||
type='text'
|
type='text'
|
||||||
value={
|
value={
|
||||||
purchaseItem?.quantity
|
purchaseItem?.quantity
|
||||||
@@ -421,7 +416,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`items.${purchaseItem.id}.uom`}
|
name={`items.${formItemIndex}.uom`}
|
||||||
type='text'
|
type='text'
|
||||||
value={
|
value={
|
||||||
purchaseItem?.product?.uom?.name || ''
|
purchaseItem?.product?.uom?.name || ''
|
||||||
@@ -436,7 +431,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
<td>
|
<td>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
name={`items.${purchaseItem.id}.price`}
|
name={`items.${formItemIndex}.price`}
|
||||||
value={formItem?.price || ''}
|
value={formItem?.price || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
handlePurchaseItemChange(
|
handlePurchaseItemChange(
|
||||||
@@ -473,7 +468,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
|||||||
<td>
|
<td>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
name={`items.${purchaseItem.id}.total_price`}
|
name={`items.${formItemIndex}.total_price`}
|
||||||
value={formItem?.total_price || ''}
|
value={formItem?.total_price || ''}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
handlePurchaseItemChange(
|
handlePurchaseItemChange(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
import { ColumnDef, SortingState, Row, Table as TableType } from '@tanstack/react-table';
|
||||||
|
|
||||||
import ApprovalSteps, {
|
import ApprovalSteps, {
|
||||||
useApprovalSteps,
|
useApprovalSteps,
|
||||||
@@ -156,6 +156,11 @@ const PurchaseOrderDetail = ({
|
|||||||
const showApprovalButton =
|
const showApprovalButton =
|
||||||
approvalStep !== null && approvalStep >= 1 && approvalStep <= 3;
|
approvalStep !== null && approvalStep >= 1 && approvalStep <= 3;
|
||||||
|
|
||||||
|
const canDeleteItems = useMemo(() => {
|
||||||
|
if (!initialValues?.approval) return false;
|
||||||
|
return initialValues.approval.step_number >= 3;
|
||||||
|
}, [initialValues?.approval]);
|
||||||
|
|
||||||
const handleApprovalClick = () => {
|
const handleApprovalClick = () => {
|
||||||
if (!approvalStep) return;
|
if (!approvalStep) return;
|
||||||
|
|
||||||
@@ -186,12 +191,6 @@ const PurchaseOrderDetail = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useMemo(() => {
|
|
||||||
if (!initialValues?.approval) return false;
|
|
||||||
|
|
||||||
const currentStep = initialValues.approval.step_number;
|
|
||||||
return currentStep >= 4;
|
|
||||||
}, [initialValues?.approval]);
|
|
||||||
const canShowPurchaseOrderInvoice = useMemo(() => {
|
const canShowPurchaseOrderInvoice = useMemo(() => {
|
||||||
if (!initialValues?.approval) return false;
|
if (!initialValues?.approval) return false;
|
||||||
|
|
||||||
@@ -345,32 +344,36 @@ const PurchaseOrderDetail = ({
|
|||||||
const purchaseData = initialValues;
|
const purchaseData = initialValues;
|
||||||
|
|
||||||
const purchaseOrderColumns: ColumnDef<PurchaseItem>[] = [
|
const purchaseOrderColumns: ColumnDef<PurchaseItem>[] = [
|
||||||
{
|
...(canDeleteItems
|
||||||
id: 'select',
|
? [
|
||||||
header: ({ table }) => (
|
{
|
||||||
<div className='w-full flex flex-row justify-center'>
|
id: 'select',
|
||||||
<CheckboxInput
|
header: ({ table }: { table: TableType<PurchaseItem> }) => (
|
||||||
name='allRow'
|
<div className='w-full flex flex-row justify-center'>
|
||||||
checked={table.getIsAllRowsSelected()}
|
<CheckboxInput
|
||||||
indeterminate={table.getIsSomeRowsSelected()}
|
name='allRow'
|
||||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
checked={table.getIsAllRowsSelected()}
|
||||||
/>
|
indeterminate={table.getIsSomeRowsSelected()}
|
||||||
</div>
|
onChange={table.getToggleAllRowsSelectedHandler()}
|
||||||
),
|
/>
|
||||||
cell: ({ row }) => {
|
</div>
|
||||||
return (
|
),
|
||||||
<div>
|
cell: ({ row }: { row: Row<PurchaseItem> }) => {
|
||||||
<CheckboxInput
|
return (
|
||||||
name='row'
|
<div>
|
||||||
checked={row.getIsSelected()}
|
<CheckboxInput
|
||||||
disabled={!row.getCanSelect()}
|
name='row'
|
||||||
indeterminate={row.getIsSomeSelected()}
|
checked={row.getIsSelected()}
|
||||||
onChange={row.getToggleSelectedHandler()}
|
disabled={!row.getCanSelect()}
|
||||||
/>
|
indeterminate={row.getIsSomeSelected()}
|
||||||
</div>
|
onChange={row.getToggleSelectedHandler()}
|
||||||
);
|
/>
|
||||||
},
|
</div>
|
||||||
},
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
header: 'No',
|
header: 'No',
|
||||||
cell: (props) => props.row.index + 1,
|
cell: (props) => props.row.index + 1,
|
||||||
@@ -426,7 +429,7 @@ const PurchaseOrderDetail = ({
|
|||||||
deleteModal.openModal();
|
deleteModal.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return canDeleteItems ? (
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='error'
|
color='error'
|
||||||
@@ -435,7 +438,7 @@ const PurchaseOrderDetail = ({
|
|||||||
>
|
>
|
||||||
<Icon icon='mdi:trash-can' width={16} height={16} />
|
<Icon icon='mdi:trash-can' width={16} height={16} />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
) : null;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -738,7 +741,7 @@ const PurchaseOrderDetail = ({
|
|||||||
setSorting={setSorting}
|
setSorting={setSorting}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
setRowSelection={setRowSelection}
|
setRowSelection={setRowSelection}
|
||||||
enableRowSelection={() => true}
|
enableRowSelection={() => canDeleteItems}
|
||||||
className={{
|
className={{
|
||||||
containerClassName: 'm-0',
|
containerClassName: 'm-0',
|
||||||
tableWrapperClassName: 'overflow-x-auto',
|
tableWrapperClassName: 'overflow-x-auto',
|
||||||
@@ -755,7 +758,7 @@ const PurchaseOrderDetail = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bulk Action Buttons */}
|
{/* Bulk Action Buttons */}
|
||||||
{selectedRowIds.length > 0 && (
|
{selectedRowIds.length > 0 && canDeleteItems && (
|
||||||
<div className='flex justify-center items-center mt-4 gap-4 px-6 py-4 bg-gray-50 border-t border-gray-200'>
|
<div className='flex justify-center items-center mt-4 gap-4 px-6 py-4 bg-gray-50 border-t border-gray-200'>
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
|
|||||||
Reference in New Issue
Block a user