refactor(FE-114): streamline cost field validation messages and enhance layout with FieldMessage component

This commit is contained in:
rstubryan
2025-10-20 18:54:31 +07:00
parent 1bcfd9bbb4
commit e0ce571000
2 changed files with 85 additions and 79 deletions
@@ -61,32 +61,24 @@ const DeliveryObjectSchema: Yup.ObjectSchema<DeliverySchema> = Yup.object({
.transform((value) => (isNaN(value) || value === 0 ? undefined : value))
.min(1, 'Biaya minimal 1!')
.typeError('Biaya harus berupa angka!')
.test(
'one-of-cost-fields',
'Biaya pengiriman atau biaya per item wajib diisi!',
function (value) {
const { delivery_cost_per_item } = this.parent;
return (
(value !== undefined && value > 0) ||
(delivery_cost_per_item !== undefined && delivery_cost_per_item > 0)
);
}
),
.test('one-of-cost-fields', 'Wajib diisi salah satu!', function (value) {
const { delivery_cost_per_item } = this.parent;
return (
(value !== undefined && value > 0) ||
(delivery_cost_per_item !== undefined && delivery_cost_per_item > 0)
);
}),
delivery_cost_per_item: Yup.number()
.transform((value) => (isNaN(value) || value === 0 ? undefined : value))
.min(1, 'Biaya per item minimal 1!')
.typeError('Biaya per item harus berupa angka!')
.test(
'one-of-cost-fields',
'Biaya pengiriman atau biaya per item wajib diisi!',
function (value) {
const { delivery_cost } = this.parent;
return (
(value !== undefined && value > 0) ||
(delivery_cost !== undefined && delivery_cost > 0)
);
}
),
.test('one-of-cost-fields', 'Wajib diisi salah satu!', function (value) {
const { delivery_cost } = this.parent;
return (
(value !== undefined && value > 0) ||
(delivery_cost !== undefined && delivery_cost > 0)
);
}),
document_path: Yup.string().optional(),
document_index: Yup.number().optional(),
document: Yup.mixed<File | string>()
@@ -8,7 +8,6 @@ import { Icon } from '@iconify/react';
import Button from '@/components/Button';
import TextInput from '@/components/input/TextInput';
import SelectInput, { OptionType } from '@/components/input/SelectInput';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import { FormHeader } from '@/components/helper/form/FormHeader';
import { FormActions } from '@/components/helper/form/FormActions';
import {
@@ -29,6 +28,7 @@ import { SupplierApi, WarehouseApi } from '@/services/api/master-data';
import { ProductWarehouseApi } from '@/services/api/inventory';
import { toast } from 'react-hot-toast';
import FileInput from '@/components/input/FileInput';
import FieldMessage from '@/components/helper/FieldMessage';
interface MovementFormProps {
type?: 'add' | 'edit' | 'detail';
@@ -863,23 +863,26 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
<tr key={`product-row-${idx}-${product.product_id}`}>
{type !== 'detail' && (
<td>
<input
type='checkbox'
className='checkbox'
checked={selectedProducts.includes(idx)}
onChange={(e) => {
if (e.target.checked) {
setSelectedProducts([
...selectedProducts,
idx,
]);
} else {
setSelectedProducts(
selectedProducts.filter((i) => i !== idx)
);
}
}}
/>
<div className='flex flex-col items-start gap-2'>
<input
type='checkbox'
className='checkbox'
checked={selectedProducts.includes(idx)}
onChange={(e) => {
if (e.target.checked) {
setSelectedProducts([
...selectedProducts,
idx,
]);
} else {
setSelectedProducts(
selectedProducts.filter((i) => i !== idx)
);
}
}}
/>
<FieldMessage message={null} isVisible={false} />
</div>
</td>
)}
<td>
@@ -954,17 +957,20 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td>
{type !== 'detail' && (
<td>
<Button
type='button'
color='error'
onClick={() => removeProduct(idx)}
>
<Icon
icon='material-symbols:delete-outline-rounded'
width={24}
height={24}
/>
</Button>
<div className='flex flex-col items-start gap-2'>
<Button
type='button'
color='error'
onClick={() => removeProduct(idx)}
>
<Icon
icon='material-symbols:delete-outline-rounded'
width={24}
height={24}
/>
</Button>
<FieldMessage message={null} isVisible={false} />
</div>
</td>
)}
</tr>
@@ -1051,23 +1057,28 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
<tr key={`delivery-row-${idx}`}>
{type !== 'detail' && (
<td>
<input
type='checkbox'
className='checkbox'
checked={selectedDeliveries.includes(idx)}
onChange={(e) => {
if (e.target.checked) {
setSelectedDeliveries([
...selectedDeliveries,
idx,
]);
} else {
setSelectedDeliveries(
selectedDeliveries.filter((i) => i !== idx)
);
}
}}
/>
<div className='flex flex-col items-start gap-2'>
<input
type='checkbox'
className='checkbox'
checked={selectedDeliveries.includes(idx)}
onChange={(e) => {
if (e.target.checked) {
setSelectedDeliveries([
...selectedDeliveries,
idx,
]);
} else {
setSelectedDeliveries(
selectedDeliveries.filter(
(i) => i !== idx
)
);
}
}}
/>
<FieldMessage message={null} isVisible={false} />
</div>
</td>
)}
<td>
@@ -1267,17 +1278,20 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td>
{type !== 'detail' && (
<td>
<Button
type='button'
color='error'
onClick={() => removeDelivery(idx)}
>
<Icon
icon='material-symbols:delete-outline-rounded'
width={24}
height={24}
/>
</Button>
<div className='flex flex-col items-start gap-2'>
<Button
type='button'
color='error'
onClick={() => removeDelivery(idx)}
>
<Icon
icon='material-symbols:delete-outline-rounded'
width={24}
height={24}
/>
</Button>
<FieldMessage message={null} isVisible={false} />
</div>
</td>
)}
</tr>