feat(FE-208,212): enhance PurchaseOrder forms with onCancel functionality and UI improvements

This commit is contained in:
rstubryan
2025-11-11 15:05:05 +07:00
parent 8c17367fb6
commit ecb497430a
3 changed files with 544 additions and 505 deletions
@@ -10,6 +10,7 @@ import Table from '@/components/Table';
import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import Button from '@/components/Button'; import Button from '@/components/Button';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
import Modal from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModal from '@/components/modal/ConfirmationModal';
import SelectInput, { import SelectInput, {
OptionType, OptionType,
@@ -21,6 +22,8 @@ import TextInput from '@/components/input/TextInput';
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper'; import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
import { cn, formatDate, formatCurrency } from '@/lib/helper'; import { cn, formatDate, formatCurrency } from '@/lib/helper';
import PurchaseOrderStaffApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm';
import PurchaseOrderAcceptApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter'; import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ROWS_OPTIONS } from '@/config/constant'; import { ROWS_OPTIONS } from '@/config/constant';
@@ -108,6 +111,8 @@ const PurchaseTable = () => {
// Modal hooks // Modal hooks
const deleteModal = useModal(); const deleteModal = useModal();
const staffApprovalModal = useModal();
const acceptApprovalModal = useModal();
// Supplier modal // Supplier modal
const { const {
@@ -282,6 +287,30 @@ const PurchaseTable = () => {
Tambah Tambah
</Button> </Button>
<Button
onClick={() => staffApprovalModal.openModal()}
variant='outline'
color='info'
className='w-full sm:w-fit'
>
<Icon icon='mdi:account-check-outline' width={24} height={24} />
Staff Approval
</Button>
<Button
onClick={() => acceptApprovalModal.openModal()}
variant='outline'
color='success'
className='w-full sm:w-fit'
>
<Icon
icon='mdi:package-variant-closed-check'
width={24}
height={24}
/>
Accept Approval
</Button>
{selectedRowIds.length > 0 && ( {selectedRowIds.length > 0 && (
<Button <Button
variant='outline' variant='outline'
@@ -418,6 +447,34 @@ const PurchaseTable = () => {
onClick: confirmationModalDeleteClickHandler, onClick: confirmationModalDeleteClickHandler,
}} }}
/> />
{/* Staff Approval Modal */}
<Modal
ref={staffApprovalModal.ref}
closeOnBackdrop
className={{
modalBox: 'w-full max-w-6xl max-h-[90vh] overflow-y-auto'
}}
>
<PurchaseOrderStaffApprovalForm
type='add'
onCancel={staffApprovalModal.closeModal}
/>
</Modal>
{/* Accept Approval Modal */}
<Modal
ref={acceptApprovalModal.ref}
closeOnBackdrop
className={{
modalBox: 'w-full max-w-6xl max-h-[90vh] overflow-y-auto'
}}
>
<PurchaseOrderAcceptApprovalForm
type='add'
onCancel={acceptApprovalModal.closeModal}
/>
</Modal>
</> </>
); );
}; };
@@ -23,16 +23,16 @@ import {
Purchase, Purchase,
} from '@/types/api/purchase/purchase'; } from '@/types/api/purchase/purchase';
import Card from '@/components/Card';
interface PurchaseOrderAcceptApprovalFormProps { interface PurchaseOrderAcceptApprovalFormProps {
type?: 'add' | 'edit'; type?: 'add' | 'edit';
initialValues?: Purchase; initialValues?: Purchase;
onCancel?: () => void;
} }
const PurchaseOrderAcceptApprovalForm = ({ const PurchaseOrderAcceptApprovalForm = ({
type = 'add', type = 'add',
initialValues, initialValues,
onCancel,
}: PurchaseOrderAcceptApprovalFormProps) => { }: PurchaseOrderAcceptApprovalFormProps) => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] =
@@ -121,6 +121,7 @@ const PurchaseOrderAcceptApprovalForm = ({
return; return;
} }
toast.success(res?.message as string); toast.success(res?.message as string);
onCancel?.();
}, },
[initialValues?.id, searchParams] [initialValues?.id, searchParams]
); );
@@ -136,6 +137,7 @@ const PurchaseOrderAcceptApprovalForm = ({
return; return;
} }
toast.success(res?.message as string); toast.success(res?.message as string);
onCancel?.();
window.location.href = '/purchase'; window.location.href = '/purchase';
}, },
[] []
@@ -330,10 +332,7 @@ const PurchaseOrderAcceptApprovalForm = ({
formik.setFieldTouched(`items.${idx}.warehouse`, true); formik.setFieldTouched(`items.${idx}.warehouse`, true);
formik.setFieldValue(`items.${idx}.warehouse`, warehouse); formik.setFieldValue(`items.${idx}.warehouse`, warehouse);
formik.setFieldTouched(`items.${idx}.warehouse_id`, true); formik.setFieldTouched(`items.${idx}.warehouse_id`, true);
formik.setFieldValue( formik.setFieldValue(`items.${idx}.warehouse_id`, warehouse?.value || 0);
`items.${idx}.warehouse_id`,
warehouse?.value || 0
);
}; };
const expeditionVendorChangeHandler = ( const expeditionVendorChangeHandler = (
@@ -394,478 +393,462 @@ const PurchaseOrderAcceptApprovalForm = ({
}; };
return ( return (
<> <form onSubmit={formik.handleSubmit} className='w-full flex flex-col gap-6'>
<section className='w-full'> <div className='w-full'>
<form <h2 className='text-lg font-semibold mb-4'>
onSubmit={formik.handleSubmit} Konfirmasi Penerimaan Produk
className='w-full mt-8 flex flex-col gap-6' </h2>
> <div className='overflow-x-auto'>
<Card <table className='table'>
title='Konfirmasi Penerimaan Produk' <thead>
className={{ <tr>
wrapper: 'w-full mb-4 shadow', <th>
title: 'mb-4', Item
}} <span className='text-error'>*</span>
> </th>
<div className='overflow-x-auto'> <th>Gudang</th>
<table className='table'> <th>Produk</th>
<thead> <th>Jenis Produk</th>
<tr> <th>Jumlah</th>
<th> <th>Satuan</th>
Item <th>
<span className='text-error'>*</span> Tanggal Diterima
</th> <span className='text-error'>*</span>
<th>Gudang</th> </th>
<th>Produk</th> <th>
<th>Jenis Produk</th> Gudang Tujuan
<th>Jumlah</th> <span className='text-error'>*</span>
<th>Satuan</th> </th>
<th> <th>
Tanggal Diterima Nomor Perjalanan
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Gudang Tujuan Dokumen Perjalanan
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Nomor Perjalanan Nomor Kendaraan
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Dokumen Perjalanan Vendor Ekspedisi
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Nomor Kendaraan Jumlah Diterima
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Vendor Ekspedisi Transport/Item
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> <th>
Jumlah Diterima Total Transport
<span className='text-error'>*</span> <span className='text-error'>*</span>
</th> </th>
<th> </tr>
Transport/Item </thead>
<span className='text-error'>*</span> <tbody>
</th> {formik.values.items?.map((item, idx) => {
<th> const selectedPurchaseItem = purchaseItems.find(
Total Transport (p) => p.value === item.purchase_item_id
<span className='text-error'>*</span> );
</th> return (
<tr key={`purchase-item-${idx}`}>
<td>
<SelectInput
required
isClearable={true}
value={item.purchase_item}
key={`purchase-item-${idx}`}
onChange={(val) => purchaseItemChangeHandler(idx, val)}
options={getPurchaseItemOptions()}
isError={
getPurchaseItemError(idx, 'purchase_item_id').isError
}
errorMessage={
getPurchaseItemError(idx, 'purchase_item_id')
.errorMessage
}
placeholder='Pilih Item...'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
name={`items.${idx}.warehouse`}
type='text'
value={selectedPurchaseItem?.warehouse?.name || ''}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-32',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.product_name`}
type='text'
value={selectedPurchaseItem?.product?.name || ''}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-48',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.product_category`}
type='text'
value={
typeof selectedPurchaseItem?.product
?.product_category === 'string'
? selectedPurchaseItem.product.product_category
: selectedPurchaseItem?.product?.product_category
?.name || ''
}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-32',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.quantity`}
type='text'
value={
selectedPurchaseItem?.quantity
? selectedPurchaseItem.quantity.toLocaleString(
'id-ID'
)
: ''
}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-24',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.uom`}
type='text'
value={selectedPurchaseItem?.product?.uom?.name || ''}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-24',
}}
disabled={true}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.received_date`}
type='date'
value={item.received_date || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.received_date`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'received_date').isError
}
errorMessage={
getPurchaseItemError(idx, 'received_date')
.errorMessage
}
className={{
wrapper: 'min-w-36',
}}
/>
</td>
<td>
<SelectInput
required
isClearable={true}
value={item.warehouse}
key={`warehouse-${idx}`}
onChange={(val) => warehouseChangeHandler(idx, val)}
options={getWarehouseOptions()}
isError={
getPurchaseItemError(idx, 'warehouse_id').isError
}
errorMessage={
getPurchaseItemError(idx, 'warehouse_id').errorMessage
}
placeholder='Pilih Gudang...'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.travel_number`}
type='text'
value={item.travel_number || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.travel_number`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'travel_number').isError
}
errorMessage={
getPurchaseItemError(idx, 'travel_number')
.errorMessage
}
placeholder='Masukkan nomor perjalanan'
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.travel_document_path`}
type='text'
value={item.travel_document_path || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.travel_document_path`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'travel_document_path')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'travel_document_path')
.errorMessage
}
placeholder='Masukkan path dokumen'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.vehicle_number`}
type='text'
value={item.vehicle_number || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.vehicle_number`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'vehicle_number').isError
}
errorMessage={
getPurchaseItemError(idx, 'vehicle_number')
.errorMessage
}
placeholder='Masukkan nomor kendaraan'
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<SelectInput
required
isClearable={true}
value={item.expedition_vendor}
key={`expedition-vendor-${idx}`}
onChange={(val) =>
expeditionVendorChangeHandler(idx, val)
}
options={getExpeditionVendorOptions()}
isError={
getPurchaseItemError(idx, 'expedition_vendor_id')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'expedition_vendor_id')
.errorMessage
}
placeholder='Pilih Vendor...'
className={{
wrapper: 'min-w-40',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.received_qty`}
value={item.received_qty || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'received_qty',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan jumlah diterima'
allowNegative={false}
decimalScale={0}
thousandSeparator=','
decimalSeparator='.'
isError={
getPurchaseItemError(idx, 'received_qty').isError
}
errorMessage={
getPurchaseItemError(idx, 'received_qty').errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.transport_per_item`}
value={item.transport_per_item || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'transport_per_item',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan transport/item'
allowNegative={false}
decimalScale={2}
thousandSeparator=','
decimalSeparator='.'
inputPrefix={'Rp'}
isError={
getPurchaseItemError(idx, 'transport_per_item')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'transport_per_item')
.errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.transport_total`}
value={item.transport_total || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'transport_total',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan total transport'
allowNegative={false}
decimalScale={2}
thousandSeparator=','
decimalSeparator='.'
inputPrefix={'Rp'}
isError={
getPurchaseItemError(idx, 'transport_total').isError
}
errorMessage={
getPurchaseItemError(idx, 'transport_total')
.errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
</tr> </tr>
</thead> );
<tbody> })}
{formik.values.items?.map((item, idx) => { </tbody>
const selectedPurchaseItem = purchaseItems.find( </table>
(p) => p.value === item.purchase_item_id </div>
); <div className={'col-span-2'}>
return ( <TextInput
<tr key={`purchase-item-${idx}`}> label='Notes'
<td> name='notes'
<SelectInput value={formik.values.notes || ''}
required onChange={formik.handleChange}
isClearable={true} onBlur={formik.handleBlur}
value={item.purchase_item} isError={formik.touched.notes && Boolean(formik.errors.notes)}
key={`purchase-item-${idx}`} errorMessage={formik.errors.notes as string}
onChange={(val) => placeholder='Masukkan catatan'
purchaseItemChangeHandler(idx, val) />
} </div>
options={getPurchaseItemOptions()}
isError={
getPurchaseItemError(idx, 'purchase_item_id')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'purchase_item_id')
.errorMessage
}
placeholder='Pilih Item...'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
name={`items.${idx}.warehouse`}
type='text'
value={selectedPurchaseItem?.warehouse?.name || ''}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-32',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.product_name`}
type='text'
value={selectedPurchaseItem?.product?.name || ''}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-48',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.product_category`}
type='text'
value={
typeof selectedPurchaseItem?.product
?.product_category === 'string'
? selectedPurchaseItem.product.product_category
: selectedPurchaseItem?.product
?.product_category?.name || ''
}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-32',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.quantity`}
type='text'
value={
selectedPurchaseItem?.quantity
? selectedPurchaseItem.quantity.toLocaleString(
'id-ID'
)
: ''
}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-24',
}}
disabled={true}
/>
</td>
<td>
<TextInput
name={`items.${idx}.uom`}
type='text'
value={
selectedPurchaseItem?.product?.uom?.name || ''
}
readOnly={true}
placeholder='Pilih item terlebih dahulu'
className={{
wrapper: 'min-w-24',
}}
disabled={true}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.received_date`}
type='date'
value={item.received_date || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.received_date`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'received_date').isError
}
errorMessage={
getPurchaseItemError(idx, 'received_date')
.errorMessage
}
className={{
wrapper: 'min-w-36',
}}
/>
</td>
<td>
<SelectInput
required
isClearable={true}
value={item.warehouse}
key={`warehouse-${idx}`}
onChange={(val) => warehouseChangeHandler(idx, val)}
options={getWarehouseOptions()}
isError={
getPurchaseItemError(idx, 'warehouse_id').isError
}
errorMessage={
getPurchaseItemError(idx, 'warehouse_id')
.errorMessage
}
placeholder='Pilih Gudang...'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.travel_number`}
type='text'
value={item.travel_number || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.travel_number`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'travel_number').isError
}
errorMessage={
getPurchaseItemError(idx, 'travel_number')
.errorMessage
}
placeholder='Masukkan nomor perjalanan'
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.travel_document_path`}
type='text'
value={item.travel_document_path || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.travel_document_path`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'travel_document_path')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'travel_document_path')
.errorMessage
}
placeholder='Masukkan path dokumen'
className={{
wrapper: 'min-w-48',
}}
/>
</td>
<td>
<TextInput
required
name={`items.${idx}.vehicle_number`}
type='text'
value={item.vehicle_number || ''}
onChange={(e) =>
formik.setFieldValue(
`items.${idx}.vehicle_number`,
e.target.value
)
}
onBlur={formik.handleBlur}
isError={
getPurchaseItemError(idx, 'vehicle_number')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'vehicle_number')
.errorMessage
}
placeholder='Masukkan nomor kendaraan'
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<SelectInput
required
isClearable={true}
value={item.expedition_vendor}
key={`expedition-vendor-${idx}`}
onChange={(val) =>
expeditionVendorChangeHandler(idx, val)
}
options={getExpeditionVendorOptions()}
isError={
getPurchaseItemError(idx, 'expedition_vendor_id')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'expedition_vendor_id')
.errorMessage
}
placeholder='Pilih Vendor...'
className={{
wrapper: 'min-w-40',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.received_qty`}
value={item.received_qty || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'received_qty',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan jumlah diterima'
allowNegative={false}
decimalScale={0}
thousandSeparator=','
decimalSeparator='.'
isError={
getPurchaseItemError(idx, 'received_qty').isError
}
errorMessage={
getPurchaseItemError(idx, 'received_qty')
.errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.transport_per_item`}
value={item.transport_per_item || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'transport_per_item',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan transport/item'
allowNegative={false}
decimalScale={2}
thousandSeparator=','
decimalSeparator='.'
inputPrefix={'Rp'}
isError={
getPurchaseItemError(idx, 'transport_per_item')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'transport_per_item')
.errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
<td>
<NumberInput
required
name={`items.${idx}.transport_total`}
value={item.transport_total || ''}
onChange={(e) =>
handlePurchaseItemChange(
idx,
'transport_total',
e.target.value
)
}
onBlur={formik.handleBlur}
placeholder='Masukkan total transport'
allowNegative={false}
decimalScale={2}
thousandSeparator=','
decimalSeparator='.'
inputPrefix={'Rp'}
isError={
getPurchaseItemError(idx, 'transport_total')
.isError
}
errorMessage={
getPurchaseItemError(idx, 'transport_total')
.errorMessage
}
className={{
wrapper: 'min-w-32',
}}
/>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
<div className={'col-span-2'}>
<TextInput
label='Notes'
name='notes'
value={formik.values.notes || ''}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
isError={formik.touched.notes && Boolean(formik.errors.notes)}
errorMessage={formik.errors.notes as string}
placeholder='Masukkan catatan'
/>
</div>
{/* Action buttons */} {/* Action buttons */}
<div className='flex flex-row justify-between gap-2 flex-wrap mt-5'> <div className='flex flex-row justify-between gap-2 flex-wrap mt-5'>
<div className='flex flex-row justify-end gap-2 w-full'> <div className='flex flex-row justify-end gap-2 w-full'>
<Link href='/purchase'> <Button
<Button color='warning' className='px-4'> type='button'
Cancel color='warning'
</Button> className='px-4'
</Link> onClick={onCancel}
>
Cancel
</Button>
<Button <Button
type='submit' type='submit'
color='primary' color='primary'
className='px-4' className='px-4'
isLoading={formik.isSubmitting} isLoading={formik.isSubmitting}
disabled={!formik.isValid || formik.isSubmitting} disabled={!formik.isValid || formik.isSubmitting}
> >
Submit Submit
</Button> </Button>
</div> </div>
</div> </div>
{purchaseOrderFormErrorMessage && ( {purchaseOrderFormErrorMessage && (
<div role='alert' className='alert alert-error'> <div role='alert' className='alert alert-error'>
<Icon <Icon
icon='material-symbols:error-outline' icon='material-symbols:error-outline'
width={24} width={24}
height={24} height={24}
/> />
<span>{purchaseOrderFormErrorMessage}</span> <span>{purchaseOrderFormErrorMessage}</span>
</div> </div>
)} )}
</Card> </div>
</form> </form>
</section>
</>
); );
}; };
@@ -23,16 +23,17 @@ import {
Purchase, Purchase,
} from '@/types/api/purchase/purchase'; } from '@/types/api/purchase/purchase';
import Card from '@/components/Card';
interface PurchaseOrderStaffApprovalFormProps { interface PurchaseOrderStaffApprovalFormProps {
type?: 'add' | 'edit'; type?: 'add' | 'edit';
initialValues?: Purchase; initialValues?: Purchase;
onCancel?: () => void;
} }
const PurchaseOrderStaffApprovalForm = ({ const PurchaseOrderStaffApprovalForm = ({
type = 'add', type = 'add',
initialValues, initialValues,
onCancel,
}: PurchaseOrderStaffApprovalFormProps) => { }: PurchaseOrderStaffApprovalFormProps) => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] =
@@ -99,6 +100,7 @@ const PurchaseOrderStaffApprovalForm = ({
return; return;
} }
toast.success(res?.message as string); toast.success(res?.message as string);
onCancel?.();
}, },
[initialValues?.id, searchParams] [initialValues?.id, searchParams]
); );
@@ -117,6 +119,7 @@ const PurchaseOrderStaffApprovalForm = ({
return; return;
} }
toast.success(res?.message as string); toast.success(res?.message as string);
onCancel?.();
window.location.href = '/purchase'; window.location.href = '/purchase';
}, },
[] []
@@ -299,18 +302,12 @@ const PurchaseOrderStaffApprovalForm = ({
return ( return (
<> <>
<section className='w-full'> <form
<form onSubmit={formik.handleSubmit}
onSubmit={formik.handleSubmit} className='w-full flex flex-col gap-6'
className='w-full mt-8 flex flex-col gap-6' >
> <div className='w-full'>
<Card <h2 className='text-lg font-semibold mb-4'>Konfirmasi Approve Pembelian</h2>
title='Konfirmasi Approve Pembelian'
className={{
wrapper: 'w-full mb-4 shadow',
title: 'mb-4',
}}
>
<div className='overflow-x-auto'> <div className='overflow-x-auto'>
<table className='table'> <table className='table'>
<thead> <thead>
@@ -525,11 +522,14 @@ const PurchaseOrderStaffApprovalForm = ({
{/* Action buttons */} {/* Action buttons */}
<div className='flex flex-row justify-between gap-2 flex-wrap mt-5'> <div className='flex flex-row justify-between gap-2 flex-wrap mt-5'>
<div className='flex flex-row justify-end gap-2 w-full'> <div className='flex flex-row justify-end gap-2 w-full'>
<Link href='/purchase'> <Button
<Button color='warning' className='px-4'> type='button'
Cancel color='warning'
</Button> className='px-4'
</Link> onClick={onCancel}
>
Cancel
</Button>
<Button <Button
type='submit' type='submit'
@@ -543,19 +543,18 @@ const PurchaseOrderStaffApprovalForm = ({
</div> </div>
</div> </div>
{purchaseOrderFormErrorMessage && ( {purchaseOrderFormErrorMessage && (
<div role='alert' className='alert alert-error'> <div role='alert' className='alert alert-error'>
<Icon <Icon
icon='material-symbols:error-outline' icon='material-symbols:error-outline'
width={24} width={24}
height={24} height={24}
/> />
<span>{purchaseOrderFormErrorMessage}</span> <span>{purchaseOrderFormErrorMessage}</span>
</div> </div>
)} )}
</Card> </div>
</form> </form>
</section>
</> </>
); );
}; };