refactor(FE-208): rename PurchaseRequestForm to PurchaseRequisitionsForm and update related components

This commit is contained in:
rstubryan
2025-11-08 09:53:21 +07:00
parent 53751d566c
commit 10dca5c692
5 changed files with 300 additions and 506 deletions
+4 -4
View File
@@ -1,11 +1,11 @@
import PurchaseRequestForm from '@/components/pages/purchase/form/request/PurchaseRequestForm';
import PurchaseRequisitionsForm from '@/components/pages/purchase/form/request/PurchaseRequisitionsForm';
const AddPurchaseRequest = () => {
const AddPurchaseRequisitions = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<PurchaseRequestForm />
<PurchaseRequisitionsForm />
</div>
);
};
export default AddPurchaseRequest;
export default AddPurchaseRequisitions;
+6 -244
View File
@@ -2,243 +2,9 @@
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import PurchaseRequestForm from '@/components/pages/purchase/form/request/PurchaseRequestForm';
import PurchaseRequisitionsForm from '@/components/pages/purchase/form/request/PurchaseRequisitionsForm';
import { PurchaseApi } from '@/services/api/purchase';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { Purchase } from '@/types/api/purchase/purchase';
// TODO: delete dummy data
const DUMMY_PURCHASE_EDIT: Purchase = {
id: 1,
pr_number: 'PR-001',
po_number: 'PO-001',
po_date: '2024-01-15',
supplier: {
id: 1,
name: 'Supplier A',
address: '123 Main St, Cityville',
account_number: 'ACC-12345',
alias: 'SupA',
category: 'Electronics',
type: 'Local',
phone: '555-1234',
email: 'email@.com',
npwp: '12.345.678.9-012.345',
pic: 'John Doe',
balance: 1000000,
hatchery: 'N/A',
due_date: 30,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
credit_term: 30,
due_date: '2024-02-14',
grand_total: 1500000,
notes: 'Urgent delivery required',
deleted_at: null,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_by: 2,
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
purchase_items: [
{
id: 1,
product_warehouse: {
id: 1,
product_id: 1,
warehouse_id: 1,
quantity: 100,
product: {
id: 1,
name: 'Product A',
brand: 'Brand A',
sku: 'PROD-A-001',
product_price: 500000,
expiry_period: 0,
uom: {
id: 1,
name: 'pcs',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
product_category: {
id: 1,
code: 'CAT-1',
name: 'Electronics',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
suppliers: [
{
id: 1,
name: 'Supplier A',
alias: 'SupA',
pic: 'John Doe',
type: 'Local',
category: 'Electronics',
hatchery: 'N/A',
phone: '555-1234',
email: 'email@.com',
address: '123 Main St, Cityville',
npwp: '12.345.678.9-012.345',
account_number: 'ACC-12345',
due_date: 30,
balance: 1000000,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
],
flags: [],
created_at: '2024-01-05T09:00:00Z',
updated_at: '2024-01-07T11:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
warehouse: {
id: 1,
name: 'Main Warehouse',
type: 'AREA',
area: { id: 1, name: 'Area 1' },
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
created_at: '2024-01-05T09:00:00Z',
updated_at: '2024-01-07T11:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
product: {
id: 1,
name: 'Product A',
brand: 'Brand A',
sku: 'PROD-A-001',
product_price: 500000,
expiry_period: 0,
uom: {
id: 1,
name: 'pcs',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
product_category: {
id: 1,
code: 'CAT-1',
name: 'Electronics',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
suppliers: [
{
id: 1,
name: 'Supplier A',
alias: 'SupA',
pic: 'John Doe',
type: 'Local',
category: 'Electronics',
hatchery: 'N/A',
phone: '555-1234',
email: 'email@.com',
address: '123 Main St, Cityville',
npwp: '12.345.678.9-012.345',
account_number: 'ACC-12345',
due_date: 30,
balance: 1000000,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
],
flags: [],
created_at: '2024-01-05T09:00:00Z',
updated_at: '2024-01-07T11:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
warehouse: {
id: 1,
name: 'Main Warehouse',
type: 'AREA',
area: { id: 1, name: 'Area 1' },
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
sub_qty: 3,
},
],
};
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
const PurchaseEdit = () => {
const router = useRouter();
@@ -261,11 +27,7 @@ const PurchaseEdit = () => {
);
}
// TODO: remove dummy data and integrate with real API
if (
!isLoadingPurchase &&
(!purchase || (isResponseError(purchase) && !DUMMY_PURCHASE_EDIT))
) {
if (!isLoadingPurchase && (!purchase || isResponseError(purchase))) {
router.replace('/404');
return;
}
@@ -275,9 +37,9 @@ const PurchaseEdit = () => {
{isLoadingPurchase && (
<span className='loading loading-spinner loading-xl' />
)}
{/* DEBUG TEMP: force dummy to verify form mapping/rendering */}
<PurchaseRequestForm type='edit' initialValues={DUMMY_PURCHASE_EDIT} />
{!isLoadingPurchase && isResponseSuccess(purchase) && (
<PurchaseRequisitionsForm type='edit' initialValues={purchase.data} />
)}
</div>
);
};
+6 -66
View File
@@ -2,59 +2,9 @@
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import PurchaseRequestForm from '@/components/pages/purchase/form/request/PurchaseRequestForm';
import PurchaseRequisitionsForm from '@/components/pages/purchase/form/request/PurchaseRequisitionsForm';
import { PurchaseApi } from '@/services/api/purchase';
import { isResponseError } from '@/lib/api-helper';
import { Purchase } from '@/types/api/purchase/purchase';
// TODO: delete dummy data
const DUMMY_PURCHASE_DETAIL: Purchase = {
id: 1,
pr_number: 'PR-001',
po_number: 'PO-001',
po_date: '2024-01-15',
supplier: {
id: 1,
name: 'Supplier A',
address: '123 Main St, Cityville',
account_number: 'ACC-12345',
alias: 'SupA',
category: 'Electronics',
type: 'Local',
phone: '555-1234',
email: 'email@.com',
npwp: '12.345.678.9-012.345',
pic: 'John Doe',
balance: 1000000,
hatchery: 'N/A',
due_date: 30,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
},
credit_term: 30,
due_date: '2024-02-14',
grand_total: 1500000,
notes: 'Urgent delivery required',
deleted_at: null,
created_at: '2024-01-10T10:00:00Z',
updated_at: '2024-01-12T12:00:00Z',
created_by: 2,
created_user: {
id: 2,
id_user: 2,
email: 'a@email.com',
name: 'Admin User',
},
};
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
const PurchaseDetail = () => {
const router = useRouter();
@@ -77,11 +27,7 @@ const PurchaseDetail = () => {
);
}
// TODO: remove dummy data and integrate with real API
if (
!isLoadingPurchase &&
(!purchase || (isResponseError(purchase) && !DUMMY_PURCHASE_DETAIL))
) {
if (!isLoadingPurchase && (!purchase || isResponseError(purchase))) {
router.replace('/404');
return;
}
@@ -91,15 +37,9 @@ const PurchaseDetail = () => {
{isLoadingPurchase && (
<span className='loading loading-spinner loading-xl' />
)}
{/* {!isLoadingPurchase && isResponseSuccess(purchase) && (
<PurchaseRequestForm type='detail' initialValues={purchase.data} />
)} */}
{/* TODO: remove this dummy data and integrate to real API */}
<PurchaseRequestForm
type='detail'
initialValues={DUMMY_PURCHASE_DETAIL}
/>
{!isLoadingPurchase && isResponseSuccess(purchase) && (
<PurchaseRequisitionsForm type='detail' initialValues={purchase.data} />
)}
</div>
);
};
@@ -149,9 +149,12 @@ const PurchaseTable = () => {
cell: (props) => props.row.original.supplier.name,
},
{
accessorKey: 'created_user',
accessorKey: 'created_by',
header: 'Nama Pengaju',
cell: (props) => props.row.original.created_user.name,
cell: (props) => {
const purchase = props.row.original;
return purchase.created_user?.name || `User ID: ${purchase.created_by}`;
},
},
{
accessorKey: 'po_date',
@@ -172,8 +175,9 @@ const PurchaseTable = () => {
{
header: 'Aging',
cell: (props) => {
if (!props.row.original.po_date) return '-';
const poDate = new Date(props.row.original.po_date);
const purchase = props.row.original;
if (!purchase.po_date) return '-';
const poDate = new Date(purchase.po_date);
const today = new Date();
const diffTime = Math.abs(today.getTime() - poDate.getTime());
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
@@ -17,11 +17,11 @@ import ConfirmationModal from '@/components/modal/ConfirmationModal';
import { useModal } from '@/components/Modal';
import {
PurchaseRequestFormSchema,
PurchaseRequestFormValues,
getPurchaseRequestFormInitialValues,
UpdatePurchaseRequestFormSchema,
} from './PurchaseRequestForm.schema';
PurchaseRequisitionsFormSchema,
PurchaseRequisitionsFormValues,
getPurchaseRequisitionsFormInitialValues,
UpdatePurchaseRequisitionsFormSchema,
} from './PurchaseRequisitionsForm.schema';
import {
SupplierApi,
AreaApi,
@@ -37,7 +37,7 @@ import { PurchaseApi } from '@/services/api/purchase';
import Card from '@/components/Card';
import {
CreatePurchaseRequestPayload,
CreatePurchaseRequisitionsPayload,
Purchase,
} from '@/types/api/purchase/purchase';
@@ -46,7 +46,7 @@ interface PurchaseRequestFormProps {
initialValues?: Purchase;
}
const PurchaseRequestForm = ({
const PurchaseRequisitionsForm = ({
type = 'add',
initialValues,
}: PurchaseRequestFormProps) => {
@@ -72,10 +72,10 @@ const PurchaseRequestForm = ({
// ===== UTILITY FUNCTIONS =====
const getPurchaseItemError = (
idx: number,
field: 'warehouse_id' | 'product_warehouse_id' | 'product_id' | 'sub_qty'
field: 'warehouse_id' | 'product_warehouse_id' | 'product_id' | 'quantity'
): { isError: boolean; errorMessage: string } => {
const touchedItem = formik.touched.purchase_items?.[idx];
const errorItem = formik.errors.purchase_items?.[idx] as
const touchedItem = formik.touched.items?.[idx];
const errorItem = formik.errors.items?.[idx] as
| Record<string, string>
| undefined;
@@ -103,7 +103,7 @@ const PurchaseRequestForm = ({
// ===== SUBMISSION HANDLERS =====
const createPurchaseRequestHandler = useCallback(
async (payload: CreatePurchaseRequestPayload) => {
async (payload: CreatePurchaseRequisitionsPayload) => {
const res = await PurchaseApi.create(payload);
if (isResponseError(res)) {
setPurchaseRequestFormErrorMessage(res.message);
@@ -118,7 +118,7 @@ const PurchaseRequestForm = ({
const updatePurchaseRequestHandler = useCallback(
async (
purchaseRequestId: number,
payload: CreatePurchaseRequestPayload
payload: CreatePurchaseRequisitionsPayload
) => {
const res = await PurchaseApi.update(purchaseRequestId, payload);
if (isResponseError(res)) {
@@ -170,47 +170,51 @@ const PurchaseRequestForm = ({
} = useSelect(WarehouseApi.basePath, 'id', 'name', 'search');
// ===== FORM CONFIGURATION =====
const formikInitialValues = useMemo<PurchaseRequestFormValues>(
() => getPurchaseRequestFormInitialValues(initialValues),
const formikInitialValues = useMemo<PurchaseRequisitionsFormValues>(
() => getPurchaseRequisitionsFormInitialValues(initialValues),
[initialValues]
);
const formik = useFormik<PurchaseRequestFormValues>({
const formik = useFormik<PurchaseRequisitionsFormValues>({
initialValues: formikInitialValues,
validationSchema:
type === 'edit'
? UpdatePurchaseRequestFormSchema
: PurchaseRequestFormSchema,
? UpdatePurchaseRequisitionsFormSchema
: PurchaseRequisitionsFormSchema,
validateOnChange: true,
validateOnBlur: true,
onSubmit: async (values) => {
const payload: CreatePurchaseRequestPayload = {
const payload: CreatePurchaseRequisitionsPayload = {
supplier_id:
typeof values.supplier_id === 'string'
? parseInt(values.supplier_id) || 0
: values.supplier_id || 0,
credit_term:
typeof values.credit_term === 'string'
? parseInt(values.credit_term) || 0
: values.credit_term || 0,
notes: values.notes || '',
purchase_items: (values.purchase_items || []).map((item) => ({
warehouse_id:
typeof item.warehouse_id === 'string'
? parseInt(item.warehouse_id) || 0
: item.warehouse_id || 0,
product_id:
typeof item.product_id === 'string'
? parseInt(item.product_id) || 0
: item.product_id || 0,
area_id:
typeof values.area_id === 'string'
? parseInt(values.area_id) || 0
: values.area_id || 0,
location_id:
typeof values.location_id === 'string'
? parseInt(values.location_id) || 0
: values.location_id || 0,
warehouse_id:
typeof values.warehouse_id === 'string'
? parseInt(values.warehouse_id) || 0
: values.warehouse_id || 0,
items: (values.items || []).map((item) => ({
product_warehouse_id:
typeof item.product_warehouse_id === 'string'
? parseInt(item.product_warehouse_id) || 0
: item.product_warehouse_id || 0,
sub_qty:
typeof item.sub_qty === 'string'
? parseFloat(item.sub_qty) || 0
: item.sub_qty || 0,
product_id:
typeof item.product_id === 'string'
? parseInt(item.product_id) || 0
: item.product_id || 0,
quantity:
typeof item.quantity === 'string'
? parseFloat(item.quantity) || 0
: item.quantity || 0,
})),
};
@@ -261,7 +265,7 @@ const PurchaseRequestForm = ({
const productUrl = useMemo(() => {
const productIds =
formik.values.purchase_items
formik.values.items
?.filter(
(item) => item.product_id && typeof item.product_id === 'number'
)
@@ -272,7 +276,7 @@ const PurchaseRequestForm = ({
id: productIds.join(','),
}).toString()}`
: null;
}, [formik.values.purchase_items]);
}, [formik.values.items]);
const { data: productsResponse } = useSWR(
productUrl,
@@ -392,16 +396,12 @@ const PurchaseRequestForm = ({
setLocationSelectInputValue('');
// Reset area dependent fields in all purchase items
if (formik.values.purchase_items) {
formik.values.purchase_items.forEach((_, idx) => {
formik.setFieldValue(`purchase_items.${idx}.warehouse`, null);
formik.setFieldValue(`purchase_items.${idx}.warehouse_id`, '');
formik.setFieldValue(`purchase_items.${idx}.product_warehouse`, null);
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse_id`,
null
);
formik.setFieldValue(`purchase_items.${idx}.product_id`, '');
if (formik.values.items) {
formik.values.items.forEach((_, idx) => {
formik.setFieldValue(`items.${idx}.product_warehouse`, null);
formik.setFieldValue(`items.${idx}.product_warehouse_id`, null);
formik.setFieldValue(`items.${idx}.product`, null);
formik.setFieldValue(`items.${idx}.product_id`, '');
});
}
};
@@ -414,16 +414,12 @@ const PurchaseRequestForm = ({
formik.setFieldValue('location_id', (location as OptionType)?.value || 0);
// Reset location dependent fields in all purchase items
if (formik.values.purchase_items) {
formik.values.purchase_items.forEach((_, idx) => {
formik.setFieldValue(`purchase_items.${idx}.warehouse`, null);
formik.setFieldValue(`purchase_items.${idx}.warehouse_id`, '');
formik.setFieldValue(`purchase_items.${idx}.product_warehouse`, null);
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse_id`,
null
);
formik.setFieldValue(`purchase_items.${idx}.product_id`, '');
if (formik.values.items) {
formik.values.items.forEach((_, idx) => {
formik.setFieldValue(`items.${idx}.product_warehouse`, null);
formik.setFieldValue(`items.${idx}.product_warehouse_id`, null);
formik.setFieldValue(`items.${idx}.product`, null);
formik.setFieldValue(`items.${idx}.product_id`, '');
});
}
};
@@ -431,48 +427,43 @@ const PurchaseRequestForm = ({
// Purchase Items Handlers
const addPurchaseItem = () => {
const newPurchaseItems = [
...(formik.values.purchase_items || []),
...(formik.values.items || []),
{
warehouse: null,
warehouse_id: '',
product: null,
product_id: '',
product_warehouse: null,
product_warehouse_id: null,
sub_qty: '',
product: null,
product_id: '',
quantity: '',
},
];
formik.setFieldValue('purchase_items', newPurchaseItems);
formik.setFieldValue('items', newPurchaseItems);
};
const removePurchaseItem = (idx: number) => {
const updatedPurchaseItems = formik.values.purchase_items?.filter(
const updatedPurchaseItems = formik.values.items?.filter(
(_, i) => i !== idx
);
formik.setFieldValue('purchase_items', updatedPurchaseItems);
formik.setFieldValue('items', updatedPurchaseItems);
};
const removeSelectedPurchaseItems = () => {
const updatedPurchaseItems = formik.values.purchase_items?.filter(
const updatedPurchaseItems = formik.values.items?.filter(
(_, idx) => !selectedPurchaseItems.includes(idx)
);
formik.setFieldValue('purchase_items', updatedPurchaseItems);
formik.setFieldValue('items', updatedPurchaseItems);
setSelectedPurchaseItems([]);
};
// ===== PURCHASE ITEM OPERATIONS =====
const handlePurchaseItemChange = (
idx: number,
field: 'sub_qty' | 'price',
field: 'quantity',
value: string | number
) => {
if (field === 'sub_qty') {
const numValue = typeof value === 'string' ? parseInt(value) || 0 : value;
formik.setFieldValue(`purchase_items.${idx}.sub_qty`, numValue);
} else if (field === 'price') {
if (field === 'quantity') {
const numValue =
typeof value === 'string' ? parseFloat(value) || 0 : value;
formik.setFieldValue(`purchase_items.${idx}.price`, numValue);
formik.setFieldValue(`items.${idx}.quantity`, numValue);
}
};
@@ -525,28 +516,28 @@ const PurchaseRequestForm = ({
isClearable
/>
<NumberInput
required={!!formik.values.supplier_id}
label='Jatuh tempo (hari)'
name='credit_term'
value={formik.values.credit_term || ''}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
isError={
formik.touched.credit_term &&
Boolean(formik.errors.credit_term)
}
errorMessage={formik.errors.credit_term as string}
readOnly={type === 'detail' || !formik.values.supplier_id}
disabled={type === 'detail' || !formik.values.supplier_id}
allowNegative={false}
decimalScale={0}
placeholder={
!formik.values.supplier_id
? 'Pilih Vendor terlebih dahulu'
: 'Masukkan jumlah hari jatuh tempo'
}
/>
{/*<NumberInput*/}
{/* required={!!formik.values.supplier_id}*/}
{/* label='Jatuh tempo (hari)'*/}
{/* name='credit_term'*/}
{/* value={formik.values.credit_term || ''}*/}
{/* onChange={formik.handleChange}*/}
{/* onBlur={formik.handleBlur}*/}
{/* isError={*/}
{/* formik.touched.credit_term &&*/}
{/* Boolean(formik.errors.credit_term)*/}
{/* }*/}
{/* errorMessage={formik.errors.credit_term as string}*/}
{/* readOnly={type === 'detail' || !formik.values.supplier_id}*/}
{/* disabled={type === 'detail' || !formik.values.supplier_id}*/}
{/* allowNegative={false}*/}
{/* decimalScale={0}*/}
{/* placeholder={*/}
{/* !formik.values.supplier_id*/}
{/* ? 'Pilih Vendor terlebih dahulu'*/}
{/* : 'Masukkan jumlah hari jatuh tempo'*/}
{/* }*/}
{/*/>*/}
<SelectInput
label='Area'
@@ -583,6 +574,59 @@ const PurchaseRequestForm = ({
key={`location-${formik.values.area_id}`}
/>
<SelectInput
label='Gudang'
placeholder={
!formik.values.area_id || !formik.values.location_id
? 'Pilih Area dan Lokasi terlebih dahulu'
: 'Pilih Gudang...'
}
value={formik.values.warehouse}
onChange={(val) => {
const warehouse = val as OptionType | null;
formik.setFieldTouched('warehouse', true);
formik.setFieldValue('warehouse', warehouse);
formik.setFieldTouched('warehouse_id', true);
formik.setFieldValue(
'warehouse_id',
(warehouse as OptionType)?.value || 0
);
if (formik.values.items) {
formik.values.items.forEach((_, idx) => {
formik.setFieldValue(
`items.${idx}.product_warehouse`,
null
);
formik.setFieldValue(
`items.${idx}.product_warehouse_id`,
null
);
formik.setFieldValue(`items.${idx}.product`, null);
formik.setFieldValue(`items.${idx}.product_id`, '');
});
}
}}
options={warehouseOptions}
onInputChange={setWarehouseSelectInputValue}
isLoading={isLoadingWarehouses}
isError={
formik.touched.warehouse &&
Boolean(formik.errors.warehouse_id)
}
errorMessage={formik.errors.warehouse_id as string}
isDisabled={
type === 'detail' ||
!formik.values.area_id ||
!formik.values.location_id
}
isClearable={
type !== 'detail' &&
!!formik.values.area_id &&
!!formik.values.location_id
}
key={`warehouse-${formik.values.area_id}-${formik.values.location_id}`}
/>
<div className={'col-span-2'}>
<TextInput
label='Notes'
@@ -618,16 +662,14 @@ const PurchaseRequestForm = ({
type='checkbox'
className='checkbox checkbox-sm'
checked={
formik.values.purchase_items?.length ===
formik.values.items?.length ===
selectedPurchaseItems.length &&
formik.values.purchase_items?.length > 0
formik.values.items?.length > 0
}
onChange={(e) => {
if (e.target.checked) {
setSelectedPurchaseItems(
formik.values.purchase_items?.map(
(_, idx) => idx
) ?? []
formik.values.items?.map((_, idx) => idx) ?? []
);
} else {
setSelectedPurchaseItems([]);
@@ -636,10 +678,6 @@ const PurchaseRequestForm = ({
/>
</th>
)}
<th>
Gudang
<span className='text-error'>*</span>
</th>
<th>
Item
<span className='text-error'>*</span>
@@ -654,7 +692,7 @@ const PurchaseRequestForm = ({
</tr>
</thead>
<tbody>
{formik.values.purchase_items?.map((item, idx) => (
{formik.values.items?.map((item, idx) => (
<tr key={`purchase-item-${idx}`}>
{type !== 'detail' && (
<td className='!align-middle'>
@@ -677,91 +715,141 @@ const PurchaseRequestForm = ({
/>
</td>
)}
<td>
<SelectInput
required
value={item.warehouse}
key={`warehouse-${idx}`}
onChange={(val) => {
const warehouse = val as OptionType | null;
formik.setFieldValue(
`purchase_items.${idx}.warehouse`,
warehouse
);
formik.setFieldValue(
`purchase_items.${idx}.warehouse_id`,
(warehouse as OptionType)?.value || 0
);
formik.setFieldTouched(
`purchase_items.${idx}.product_warehouse`,
false
);
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse`,
null
);
formik.setFieldTouched(
`purchase_items.${idx}.product_warehouse_id`,
false
);
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse_id`,
0
);
formik.setFieldTouched(
`purchase_items.${idx}.product_id`,
false
);
formik.setFieldValue(
`purchase_items.${idx}.product_id`,
0
);
}}
options={warehouseOptions}
onInputChange={setWarehouseSelectInputValue}
isLoading={isLoadingWarehouses}
isError={
getPurchaseItemError(idx, 'warehouse_id').isError
}
errorMessage={
getPurchaseItemError(idx, 'warehouse_id')
.errorMessage
}
isDisabled={type === 'detail'}
isClearable
placeholder='Pilih Gudang'
className={{
wrapper: 'min-w-32',
}}
/>
</td>
{/*<td>*/}
{/* <SelectInput*/}
{/* required*/}
{/* value={item.warehouse}*/}
{/* key={`warehouse-${idx}`}*/}
{/* onChange={(val) => {*/}
{/* const warehouse = val as OptionType | null;*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.warehouse`,*/}
{/* warehouse*/}
{/* );*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.warehouse_id`,*/}
{/* (warehouse as OptionType)?.value || 0*/}
{/* );*/}
{/* formik.setFieldTouched(*/}
{/* `purchase_items.${idx}.product_warehouse`,*/}
{/* false*/}
{/* );*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_warehouse`,*/}
{/* null*/}
{/* );*/}
{/* formik.setFieldTouched(*/}
{/* `purchase_items.${idx}.product_warehouse_id`,*/}
{/* false*/}
{/* );*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_warehouse_id`,*/}
{/* 0*/}
{/* );*/}
{/* formik.setFieldTouched(*/}
{/* `purchase_items.${idx}.product_id`,*/}
{/* false*/}
{/* );*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_id`,*/}
{/* 0*/}
{/* );*/}
{/* }}*/}
{/* options={warehouseOptions}*/}
{/* onInputChange={setWarehouseSelectInputValue}*/}
{/* isLoading={isLoadingWarehouses}*/}
{/* isError={*/}
{/* getPurchaseItemError(idx, 'warehouse_id').isError*/}
{/* }*/}
{/* errorMessage={*/}
{/* getPurchaseItemError(idx, 'warehouse_id')*/}
{/* .errorMessage*/}
{/* }*/}
{/* isDisabled={type === 'detail'}*/}
{/* isClearable*/}
{/* placeholder='Pilih Gudang'*/}
{/* className={{*/}
{/* wrapper: 'min-w-32',*/}
{/* }}*/}
{/* />*/}
{/*</td>*/}
{/*<td>*/}
{/* <SelectInput*/}
{/* required*/}
{/* value={item.product_warehouse}*/}
{/* key={`product-warehouse-${idx}-${item.warehouse_id}`}*/}
{/* onChange={(val) => {*/}
{/* const productWarehouse =*/}
{/* val as ProductWarehouseOptionType | null;*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_warehouse`,*/}
{/* productWarehouse*/}
{/* );*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_warehouse_id`,*/}
{/* (productWarehouse as ProductWarehouseOptionType)*/}
{/* ?.value || 0*/}
{/* );*/}
{/* const productId =*/}
{/* (productWarehouse as ProductWarehouseOptionType)*/}
{/* ?.product_id || 0;*/}
{/* formik.setFieldValue(*/}
{/* `purchase_items.${idx}.product_id`,*/}
{/* productId*/}
{/* );*/}
{/* }}*/}
{/* options={getProductWarehouseOptionsForItem(*/}
{/* item.warehouse_id*/}
{/* )}*/}
{/* isLoading={isLoadingProductWarehouses}*/}
{/* isError={*/}
{/* getPurchaseItemError(idx, 'product_warehouse_id')*/}
{/* .isError*/}
{/* }*/}
{/* errorMessage={*/}
{/* getPurchaseItemError(idx, 'product_warehouse_id')*/}
{/* .errorMessage*/}
{/* }*/}
{/* isDisabled={type === 'detail' || !item.warehouse_id}*/}
{/* isClearable={type !== 'detail' && !!item.warehouse_id}*/}
{/* placeholder={*/}
{/* !item.warehouse_id*/}
{/* ? 'Pilih Gudang terlebih dahulu'*/}
{/* : 'Pilih Produk'*/}
{/* }*/}
{/* className={{*/}
{/* wrapper: 'min-w-32',*/}
{/* }}*/}
{/* />*/}
{/*</td>*/}
<td>
<SelectInput
required
value={item.product_warehouse}
key={`product-warehouse-${idx}-${item.warehouse_id}`}
key={`product-warehouse-${idx}-${formik.values.warehouse_id}`}
onChange={(val) => {
const productWarehouse =
val as ProductWarehouseOptionType | null;
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse`,
`items.${idx}.product_warehouse`,
productWarehouse
);
formik.setFieldValue(
`purchase_items.${idx}.product_warehouse_id`,
`items.${idx}.product_warehouse_id`,
(productWarehouse as ProductWarehouseOptionType)
?.value || 0
);
const productId =
(productWarehouse as ProductWarehouseOptionType)
?.product_id || 0;
formik.setFieldValue(
`purchase_items.${idx}.product_id`,
`items.${idx}.product_id`,
productId
);
}}
options={getProductWarehouseOptionsForItem(
item.warehouse_id
formik.values.warehouse_id
)}
isLoading={isLoadingProductWarehouses}
isError={
@@ -772,10 +860,14 @@ const PurchaseRequestForm = ({
getPurchaseItemError(idx, 'product_warehouse_id')
.errorMessage
}
isDisabled={type === 'detail' || !item.warehouse_id}
isClearable={type !== 'detail' && !!item.warehouse_id}
isDisabled={
type === 'detail' || !formik.values.warehouse_id
}
isClearable={
type !== 'detail' && !!formik.values.warehouse_id
}
placeholder={
!item.warehouse_id
!formik.values.warehouse_id
? 'Pilih Gudang terlebih dahulu'
: 'Pilih Produk'
}
@@ -787,12 +879,12 @@ const PurchaseRequestForm = ({
<td>
<NumberInput
required
name={`purchase_items.${idx}.sub_qty`}
value={item.sub_qty || ''}
name={`items.${idx}.quantity`}
value={item.quantity || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'sub_qty',
'quantity',
e.target.value
)
}
@@ -801,9 +893,11 @@ const PurchaseRequestForm = ({
readOnly={type === 'detail'}
allowNegative={false}
decimalScale={0}
isError={getPurchaseItemError(idx, 'sub_qty').isError}
isError={
getPurchaseItemError(idx, 'quantity').isError
}
errorMessage={
getPurchaseItemError(idx, 'sub_qty').errorMessage
getPurchaseItemError(idx, 'quantity').errorMessage
}
className={{
wrapper: 'min-w-24',
@@ -813,24 +907,18 @@ const PurchaseRequestForm = ({
<td>
<TextInput
required
name={`purchase_items.${idx}.price`}
name={`items.${idx}.price`}
value={
item.product_id && productData[item.product_id]
? (
productData[item.product_id].product_price *
(parseFloat(
item.sub_qty?.toString() || '0'
item.quantity?.toString() || '0'
) || 0)
).toLocaleString('en-US')
: ''
}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'price',
e.target.value
)
}
onChange={(e) => {}}
onBlur={formik.handleBlur}
type='text'
className={{
@@ -856,7 +944,7 @@ const PurchaseRequestForm = ({
<td>
<TextInput
required
name={`purchase_items.${idx}.uom`}
name={`items.${idx}.uom`}
value={
item.product_id && productData[item.product_id]
? productData[item.product_id].uom.name
@@ -1011,4 +1099,4 @@ const PurchaseRequestForm = ({
);
};
export default PurchaseRequestForm;
export default PurchaseRequisitionsForm;