refactor(FE): Make delivery fields nullable and optional

This commit is contained in:
rstubryan
2026-01-29 09:48:43 +07:00
parent 0bdf27de2c
commit 737d8e943c
2 changed files with 72 additions and 84 deletions
@@ -27,12 +27,12 @@ type MovementFormSchemaType = {
product_qty: number | string; product_qty: number | string;
}[]; }[];
deliveries: { deliveries: {
delivery_cost?: number | string; delivery_cost?: number | string | null;
delivery_cost_per_item?: number | string; delivery_cost_per_item?: number | string | null;
document?: File | MovementDocument | null; document?: File | MovementDocument | null;
document_path?: string | null; document_path?: string | null;
driver_name: string; driver_name?: string | null;
vehicle_plate: string; vehicle_plate?: string | null;
supplier?: { supplier?: {
value: number; value: number;
label: string; label: string;
@@ -59,12 +59,12 @@ export type ProductSchema = {
}; };
export type DeliverySchema = { export type DeliverySchema = {
delivery_cost?: number | string; delivery_cost?: number | string | null;
delivery_cost_per_item?: number | string; delivery_cost_per_item?: number | string | null;
document?: File | MovementDocument | null; document?: File | MovementDocument | null;
document_path?: string | null; document_path?: string | null;
driver_name: string; driver_name?: string | null;
vehicle_plate: string; vehicle_plate?: string | null;
supplier?: { supplier?: {
value: number; value: number;
label: string; label: string;
@@ -120,32 +120,26 @@ const DeliveryDocumentSchema = Yup.mixed<File | MovementDocument>()
const DeliveryObjectSchema: Yup.ObjectSchema<DeliverySchema> = Yup.object({ const DeliveryObjectSchema: Yup.ObjectSchema<DeliverySchema> = Yup.object({
delivery_cost: Yup.number() delivery_cost: Yup.number()
.transform((value) => (isNaN(value) || value === 0 ? undefined : value)) .transform((value) =>
isNaN(value) || value === '' || value === null ? undefined : value
)
.optional()
.nullable()
.min(1, 'Biaya minimal 1!') .min(1, 'Biaya minimal 1!')
.typeError('Biaya harus berupa angka!') .typeError('Biaya harus berupa angka!'),
.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() delivery_cost_per_item: Yup.number()
.transform((value) => (isNaN(value) || value === 0 ? undefined : value)) .transform((value) =>
isNaN(value) || value === '' || value === null ? undefined : value
)
.optional()
.nullable()
.min(1, 'Biaya per item minimal 1!') .min(1, 'Biaya per item minimal 1!')
.typeError('Biaya per item harus berupa angka!') .typeError('Biaya per item harus berupa angka!'),
.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().nullable().optional(), document_path: Yup.string().nullable().optional(),
document_index: Yup.number().optional(), document_index: Yup.number().optional(),
document: DeliveryDocumentSchema, document: DeliveryDocumentSchema,
driver_name: Yup.string().required('Nama sopir wajib diisi!'), driver_name: Yup.string().optional().nullable(),
vehicle_plate: Yup.string().required('Plat nomor wajib diisi!'), vehicle_plate: Yup.string().optional().nullable(),
supplier: Yup.object({ supplier: Yup.object({
value: Yup.number().min(1).required(), value: Yup.number().min(1).required(),
label: Yup.string().required(), label: Yup.string().required(),
@@ -279,12 +273,12 @@ export const getMovementFormInitialValues = (
}) ?? [], }) ?? [],
})) ?? [ })) ?? [
{ {
delivery_cost: undefined, delivery_cost: null,
delivery_cost_per_item: undefined, delivery_cost_per_item: null,
document: null, document: null,
document_path: null, document_path: null,
driver_name: '', driver_name: null,
vehicle_plate: '', vehicle_plate: null,
supplier: null, supplier: null,
supplier_id: 0, supplier_id: 0,
products: [ products: [
@@ -228,19 +228,49 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
} }
} }
return { const deliveryObj: {
delivery_cost: parseInt((d.delivery_cost || '').toString()) || 0, products: Array<{ product_id: number; product_qty: number }>;
delivery_cost_per_item: delivery_cost?: number;
parseInt((d.delivery_cost_per_item || '').toString()) || 0, delivery_cost_per_item?: number;
document_index: documentIndex, document_index?: number;
driver_name: d.driver_name, driver_name?: string;
vehicle_plate: d.vehicle_plate, vehicle_plate?: string;
supplier_id: d.supplier_id, supplier_id?: number;
} = {
products: d.products.map((p) => ({ products: d.products.map((p) => ({
product_id: p.product_id, product_id: p.product_id,
product_qty: parseInt(p.product_qty.toString()) || 0, product_qty: parseInt(p.product_qty.toString()) || 0,
})), })),
}; };
const deliveryCost = parseInt((d.delivery_cost || '').toString()) || 0;
if (deliveryCost > 0) {
deliveryObj.delivery_cost = deliveryCost;
}
const deliveryCostPerItem =
parseInt((d.delivery_cost_per_item || '').toString()) || 0;
if (deliveryCostPerItem > 0) {
deliveryObj.delivery_cost_per_item = deliveryCostPerItem;
}
if (documentIndex >= 0) {
deliveryObj.document_index = documentIndex;
}
if (d.driver_name) {
deliveryObj.driver_name = d.driver_name;
}
if (d.vehicle_plate) {
deliveryObj.vehicle_plate = d.vehicle_plate;
}
if (d.supplier_id) {
deliveryObj.supplier_id = d.supplier_id;
}
return deliveryObj;
}); });
const payload: CreateMovementPayload = { const payload: CreateMovementPayload = {
@@ -1647,43 +1677,11 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</span> </span>
</th> </th>
<th>Supplier</th> <th>Supplier</th>
<th> <th>Plat Nomor</th>
Plat Nomor
<span
className='tooltip tooltip-error tooltip-bottom z-9999'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>Dokumen</th> <th>Dokumen</th>
<th> <th>Biaya Pengiriman (Rp.)</th>
Biaya Pengiriman (Rp.) <th>Biaya Per Item (Rp.)</th>
<span <th>Nama Sopir</th>
className='tooltip tooltip-error tooltip-bottom z-9999'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>
Biaya Per Item (Rp.)
<span
className='tooltip tooltip-error tooltip-bottom z-9999'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>
Nama Sopir
<span
className='tooltip tooltip-error tooltip-bottom z-9999'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
{type !== 'detail' && <th>Aksi</th>} {type !== 'detail' && <th>Aksi</th>}
</tr> </tr>
</thead> </thead>
@@ -1780,10 +1778,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td> </td>
<td> <td>
<TextInput <TextInput
required
name={`deliveries.${idx}.vehicle_plate`} name={`deliveries.${idx}.vehicle_plate`}
placeholder='Masukkan plat nomor...' placeholder='Masukkan plat nomor...'
value={delivery.vehicle_plate} value={delivery.vehicle_plate ?? ''}
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
{...isRepeaterInputError( {...isRepeaterInputError(
@@ -1871,10 +1868,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td> </td>
<td> <td>
<NumberInput <NumberInput
required
name={`deliveries.${idx}.delivery_cost`} name={`deliveries.${idx}.delivery_cost`}
placeholder='Masukkan biaya pengiriman...' placeholder='Masukkan biaya pengiriman...'
value={delivery.delivery_cost || ''} value={delivery.delivery_cost ?? ''}
onChange={handleDeliveryCostChangeWrapper(idx)} onChange={handleDeliveryCostChangeWrapper(idx)}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
decimalScale={0} decimalScale={0}
@@ -1895,10 +1891,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td> </td>
<td> <td>
<NumberInput <NumberInput
required
name={`deliveries.${idx}.delivery_cost_per_item`} name={`deliveries.${idx}.delivery_cost_per_item`}
placeholder='Masukkan biaya per item...' placeholder='Masukkan biaya per item...'
value={delivery.delivery_cost_per_item || ''} value={delivery.delivery_cost_per_item ?? ''}
onChange={handleDeliveryCostPerItemChangeWrapper(idx)} onChange={handleDeliveryCostPerItemChangeWrapper(idx)}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
decimalScale={0} decimalScale={0}
@@ -1919,10 +1914,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
</td> </td>
<td> <td>
<TextInput <TextInput
required
name={`deliveries.${idx}.driver_name`} name={`deliveries.${idx}.driver_name`}
placeholder='Masukkan nama sopir...' placeholder='Masukkan nama sopir...'
value={delivery.driver_name} value={delivery.driver_name ?? ''}
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
{...isRepeaterInputError( {...isRepeaterInputError(