mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-62,65): refactor MovementForm schema and component for improved product and ekspedisi handling
This commit is contained in:
@@ -1,6 +1,72 @@
|
|||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { Movement } from '@/types/api/inventory/movement';
|
import { Movement } from '@/types/api/inventory/movement';
|
||||||
|
|
||||||
|
export type ProductSchema = {
|
||||||
|
product: {
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null;
|
||||||
|
product_id: number;
|
||||||
|
qty_product: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EkspedisiSchema = {
|
||||||
|
product: {
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null;
|
||||||
|
product_id: number;
|
||||||
|
qty: number;
|
||||||
|
supplier: {
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null;
|
||||||
|
supplier_id: number;
|
||||||
|
plat_nomor: string;
|
||||||
|
no_surat_jalan: string;
|
||||||
|
dokumen: string | File;
|
||||||
|
biaya_ekspedisi: number;
|
||||||
|
nama_sopir: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define schemas for nested objects
|
||||||
|
const ProductObjectSchema: Yup.ObjectSchema<ProductSchema> = Yup.object({
|
||||||
|
product: Yup.object({
|
||||||
|
value: Yup.number().min(1).required(),
|
||||||
|
label: Yup.string().required(),
|
||||||
|
}).nullable(),
|
||||||
|
product_id: Yup.number().required('Produk wajib diisi!'),
|
||||||
|
qty_product: Yup.number()
|
||||||
|
.required('Qty wajib diisi!')
|
||||||
|
.min(1, 'Qty minimal 1!')
|
||||||
|
.typeError('Qty harus berupa angka!'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const EkspedisiObjectSchema: Yup.ObjectSchema<EkspedisiSchema> = Yup.object({
|
||||||
|
product: Yup.object({
|
||||||
|
value: Yup.number().min(1).required(),
|
||||||
|
label: Yup.string().required(),
|
||||||
|
}).nullable(),
|
||||||
|
product_id: Yup.number().required('Produk wajib diisi!'),
|
||||||
|
qty: Yup.number()
|
||||||
|
.required('Qty wajib diisi!')
|
||||||
|
.min(1, 'Qty minimal 1!')
|
||||||
|
.typeError('Qty harus berupa angka!'),
|
||||||
|
supplier: Yup.object({
|
||||||
|
value: Yup.number().min(1).required(),
|
||||||
|
label: Yup.string().required(),
|
||||||
|
}).nullable(),
|
||||||
|
supplier_id: Yup.number().required('Supplier wajib diisi!'),
|
||||||
|
plat_nomor: Yup.string().required('Plat nomor wajib diisi!'),
|
||||||
|
no_surat_jalan: Yup.string().required('No surat jalan wajib diisi!'),
|
||||||
|
dokumen: Yup.mixed<string | File>().required('Dokumen wajib diisi!'),
|
||||||
|
biaya_ekspedisi: Yup.number()
|
||||||
|
.required('Biaya ekspedisi wajib diisi!')
|
||||||
|
.min(0, 'Biaya minimal 0!')
|
||||||
|
.typeError('Biaya harus berupa angka!'),
|
||||||
|
nama_sopir: Yup.string().required('Nama sopir wajib diisi!'),
|
||||||
|
});
|
||||||
|
|
||||||
export const MovementFormSchema = Yup.object({
|
export const MovementFormSchema = Yup.object({
|
||||||
alasan_transfer: Yup.string().required('Alasan transfer wajib diisi!'),
|
alasan_transfer: Yup.string().required('Alasan transfer wajib diisi!'),
|
||||||
tanggal_transfer: Yup.string().required('Tanggal transfer wajib diisi!'),
|
tanggal_transfer: Yup.string().required('Tanggal transfer wajib diisi!'),
|
||||||
@@ -19,49 +85,9 @@ export const MovementFormSchema = Yup.object({
|
|||||||
.required('Gudang tujuan wajib diisi!')
|
.required('Gudang tujuan wajib diisi!')
|
||||||
.typeError('Gudang tujuan wajib diisi!'),
|
.typeError('Gudang tujuan wajib diisi!'),
|
||||||
product: Yup.array()
|
product: Yup.array()
|
||||||
.of(
|
.of(ProductObjectSchema)
|
||||||
Yup.object({
|
|
||||||
product: Yup.object({
|
|
||||||
value: Yup.number().min(1).required(),
|
|
||||||
label: Yup.string().required(),
|
|
||||||
}).nullable(),
|
|
||||||
product_id: Yup.number().required('Produk wajib diisi!'),
|
|
||||||
qty_product: Yup.number()
|
|
||||||
.required('Qty wajib diisi!')
|
|
||||||
.min(1, 'Qty minimal 1!')
|
|
||||||
.typeError('Qty harus berupa angka!'),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.min(1, 'Minimal harus ada 1 produk!'),
|
.min(1, 'Minimal harus ada 1 produk!'),
|
||||||
ekspedisi: Yup.array()
|
ekspedisi: Yup.array().of(EkspedisiObjectSchema).optional().default([]),
|
||||||
.of(
|
|
||||||
Yup.object({
|
|
||||||
product: Yup.object({
|
|
||||||
value: Yup.number().min(1).required(),
|
|
||||||
label: Yup.string().required(),
|
|
||||||
}).nullable(),
|
|
||||||
product_id: Yup.number().required('Produk wajib diisi!'),
|
|
||||||
qty: Yup.number()
|
|
||||||
.required('Qty wajib diisi!')
|
|
||||||
.min(1, 'Qty minimal 1!')
|
|
||||||
.typeError('Qty harus berupa angka!'),
|
|
||||||
supplier: Yup.object({
|
|
||||||
value: Yup.number().min(1).required(),
|
|
||||||
label: Yup.string().required(),
|
|
||||||
}).nullable(),
|
|
||||||
supplier_id: Yup.number().required('Supplier wajib diisi!'),
|
|
||||||
plat_nomor: Yup.string().required('Plat nomor wajib diisi!'),
|
|
||||||
no_surat_jalan: Yup.string().required('No surat jalan wajib diisi!'),
|
|
||||||
dokumen: Yup.mixed().required('Dokumen wajib diisi!'),
|
|
||||||
biaya_ekspedisi: Yup.number()
|
|
||||||
.required('Biaya ekspedisi wajib diisi!')
|
|
||||||
.min(0, 'Biaya minimal 0!')
|
|
||||||
.typeError('Biaya harus berupa angka!'),
|
|
||||||
nama_sopir: Yup.string().required('Nama sopir wajib diisi!'),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.optional()
|
|
||||||
.default([]),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const UpdateMovementFormSchema = MovementFormSchema;
|
export const UpdateMovementFormSchema = MovementFormSchema;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { FieldArray, FormikProvider, useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
MovementFormValues,
|
MovementFormValues,
|
||||||
UpdateMovementFormSchema,
|
UpdateMovementFormSchema,
|
||||||
getMovementFormInitialValues,
|
getMovementFormInitialValues,
|
||||||
|
ProductSchema,
|
||||||
|
EkspedisiSchema,
|
||||||
} from '@/components/pages/inventory/movement/form/MovementForm.schema';
|
} from '@/components/pages/inventory/movement/form/MovementForm.schema';
|
||||||
import { useMovementFormHandlers } from './useMovementFormHandlers';
|
import { useMovementFormHandlers } from './useMovementFormHandlers';
|
||||||
import {
|
import {
|
||||||
@@ -91,6 +93,72 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const addProduct = () => {
|
||||||
|
const newProducts = [
|
||||||
|
...(formik.values.product || []),
|
||||||
|
{
|
||||||
|
product: null,
|
||||||
|
product_id: 0,
|
||||||
|
qty_product: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
formik.setFieldValue('product', newProducts);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeProduct = (index: number) => {
|
||||||
|
const newProducts = formik.values.product?.filter(
|
||||||
|
(_, idx) => idx !== index
|
||||||
|
);
|
||||||
|
formik.setFieldValue('product', newProducts);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addEkspedisi = () => {
|
||||||
|
const newEkspedisi = [
|
||||||
|
...(formik.values.ekspedisi || []),
|
||||||
|
{
|
||||||
|
product: null,
|
||||||
|
product_id: 0,
|
||||||
|
qty: 0,
|
||||||
|
supplier: null,
|
||||||
|
supplier_id: 0,
|
||||||
|
plat_nomor: '',
|
||||||
|
no_surat_jalan: '',
|
||||||
|
dokumen: '',
|
||||||
|
biaya_ekspedisi: 0,
|
||||||
|
nama_sopir: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
formik.setFieldValue('ekspedisi', newEkspedisi);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeEkspedisi = (index: number) => {
|
||||||
|
const newEkspedisi = formik.values.ekspedisi?.filter(
|
||||||
|
(_, idx) => idx !== index
|
||||||
|
);
|
||||||
|
formik.setFieldValue('ekspedisi', newEkspedisi);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isRepeaterInputError = <T extends 'product' | 'ekspedisi'>(
|
||||||
|
arrayName: T,
|
||||||
|
column: T extends 'product' ? keyof ProductSchema : keyof EkspedisiSchema,
|
||||||
|
idx: number
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
!formik.touched[arrayName] ||
|
||||||
|
!Array.isArray(formik.touched[arrayName])
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const touchedField = formik.touched[arrayName]?.[idx]?.[column as string];
|
||||||
|
const errorField = formik.errors[arrayName]?.[idx] as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>;
|
||||||
|
|
||||||
|
return touchedField && Boolean(errorField?.[column as string]);
|
||||||
|
};
|
||||||
|
|
||||||
// Warehouse selection
|
// Warehouse selection
|
||||||
const [warehouseSelectInputValue, setWarehouseSelectInputValue] =
|
const [warehouseSelectInputValue, setWarehouseSelectInputValue] =
|
||||||
useState('');
|
useState('');
|
||||||
@@ -139,7 +207,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
title='Movement'
|
title='Movement'
|
||||||
backUrl='/inventory/movement'
|
backUrl='/inventory/movement'
|
||||||
/>
|
/>
|
||||||
<FormikProvider value={formik}>
|
|
||||||
<form
|
<form
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={formik.handleSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
@@ -243,34 +310,29 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<div className='card bg-base-100 shadow mb-4'>
|
<div className='card bg-base-100 shadow mb-4'>
|
||||||
<div className='card-body'>
|
<div className='card-body'>
|
||||||
<h2 className='card-title mb-4'>Produk</h2>
|
<h2 className='card-title mb-4'>Produk</h2>
|
||||||
<FieldArray name='product'>
|
<div className='overflow-x-auto'>
|
||||||
{({ push, remove }) => (
|
|
||||||
<>
|
|
||||||
<table className='table'>
|
<table className='table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Produk</th>
|
<th>Produk</th>
|
||||||
<th>Qty</th>
|
<th>Qty</th>
|
||||||
<th>Aksi</th>
|
{type !== 'detail' && <th>Aksi</th>}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{formik.values.product?.map((_, index) => (
|
{formik.values.product?.map((product, idx) => (
|
||||||
<tr key={index}>
|
<tr key={idx}>
|
||||||
<td>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
value={
|
value={product.product ?? undefined}
|
||||||
formik.values.product?.[index]?.product ??
|
|
||||||
undefined
|
|
||||||
}
|
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`product.${index}.product`,
|
`product.${idx}.product`,
|
||||||
val
|
val
|
||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`product.${index}.product_id`,
|
`product.${idx}.product_id`,
|
||||||
(val as OptionType)?.value
|
(val as OptionType)?.value
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@@ -279,61 +341,63 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
isLoading={isLoadingProducts}
|
isLoading={isLoadingProducts}
|
||||||
isDisabled={type === 'detail'}
|
isDisabled={type === 'detail'}
|
||||||
isClearable
|
isClearable
|
||||||
|
isError={isRepeaterInputError(
|
||||||
|
'product',
|
||||||
|
'product',
|
||||||
|
idx
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
required
|
required
|
||||||
name={`product.${index}.qty_product`}
|
|
||||||
type='number'
|
type='number'
|
||||||
value={
|
name={`product.${idx}.qty_product`}
|
||||||
formik.values.product?.[index]
|
value={product.qty_product ?? ''}
|
||||||
?.qty_product ?? ''
|
onChange={formik.handleChange}
|
||||||
}
|
onBlur={formik.handleBlur}
|
||||||
onChange={(e) =>
|
isError={isRepeaterInputError(
|
||||||
formik.setFieldValue(
|
'product',
|
||||||
`product.${index}.qty_product`,
|
'qty_product',
|
||||||
e.target.value
|
idx
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
|
<td>
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='error'
|
color='error'
|
||||||
onClick={() => remove(index)}
|
onClick={() => removeProduct(idx)}
|
||||||
>
|
>
|
||||||
<Icon icon='material-symbols:delete-outline' />
|
<Icon
|
||||||
|
icon='material-symbols:delete-outline-rounded'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
|
||||||
</td>
|
</td>
|
||||||
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
)) ?? []}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='primary'
|
color='success'
|
||||||
onClick={() =>
|
onClick={addProduct}
|
||||||
push({
|
className='w-fit mx-auto mt-4'
|
||||||
product: null,
|
|
||||||
product_id: 0,
|
|
||||||
qty_product: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Icon icon='ic:round-plus' />
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
Tambah Produk
|
Tambah Produk
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</FieldArray>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -341,9 +405,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<div className='card bg-base-100 shadow mb-4'>
|
<div className='card bg-base-100 shadow mb-4'>
|
||||||
<div className='card-body'>
|
<div className='card-body'>
|
||||||
<h2 className='card-title mb-4'>Ekspedisi</h2>
|
<h2 className='card-title mb-4'>Ekspedisi</h2>
|
||||||
<FieldArray name='ekspedisi'>
|
<div className='overflow-x-auto'>
|
||||||
{({ push, remove }) => (
|
|
||||||
<>
|
|
||||||
<table className='table'>
|
<table className='table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -355,26 +417,23 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<th>Dokumen</th>
|
<th>Dokumen</th>
|
||||||
<th>Biaya Ekspedisi</th>
|
<th>Biaya Ekspedisi</th>
|
||||||
<th>Nama Sopir</th>
|
<th>Nama Sopir</th>
|
||||||
<th>Aksi</th>
|
{type !== 'detail' && <th>Aksi</th>}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{formik.values.ekspedisi?.map((ekspedisi, index) => (
|
{formik.values.ekspedisi?.map((ekspedisi, idx) => (
|
||||||
<tr key={index}>
|
<tr key={idx}>
|
||||||
<td>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
value={
|
value={ekspedisi.product ?? undefined}
|
||||||
formik.values.ekspedisi?.[index]?.product ??
|
|
||||||
undefined
|
|
||||||
}
|
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`ekspedisi.${index}.product`,
|
`ekspedisi.${idx}.product`,
|
||||||
val
|
val
|
||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`ekspedisi.${index}.product_id`,
|
`ekspedisi.${idx}.product_id`,
|
||||||
(val as OptionType)?.value
|
(val as OptionType)?.value
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@@ -383,39 +442,43 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
isLoading={isLoadingProducts}
|
isLoading={isLoadingProducts}
|
||||||
isDisabled={type === 'detail'}
|
isDisabled={type === 'detail'}
|
||||||
isClearable
|
isClearable
|
||||||
|
isError={isRepeaterInputError(
|
||||||
|
'ekspedisi',
|
||||||
|
'product',
|
||||||
|
idx
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.qty`}
|
|
||||||
required
|
required
|
||||||
type='number'
|
type='number'
|
||||||
value={
|
name={`ekspedisi.${idx}.qty`}
|
||||||
formik.values.ekspedisi?.[index]?.qty ?? ''
|
value={ekspedisi.qty ?? ''}
|
||||||
}
|
onChange={formik.handleChange}
|
||||||
onChange={(e) =>
|
onBlur={formik.handleBlur}
|
||||||
formik.setFieldValue(
|
isError={isRepeaterInputError(
|
||||||
`ekspedisi.${index}.qty`,
|
'ekspedisi',
|
||||||
e.target.value
|
'qty',
|
||||||
)
|
idx
|
||||||
}
|
)}
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
value={
|
value={ekspedisi.supplier ?? undefined}
|
||||||
formik.values.ekspedisi?.[index]
|
|
||||||
?.supplier ?? undefined
|
|
||||||
}
|
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`ekspedisi.${index}.supplier`,
|
`ekspedisi.${idx}.supplier`,
|
||||||
val
|
val
|
||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`ekspedisi.${index}.supplier_id`,
|
`ekspedisi.${idx}.supplier_id`,
|
||||||
(val as OptionType)?.value
|
(val as OptionType)?.value
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@@ -424,136 +487,142 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
isLoading={isLoadingSuppliers}
|
isLoading={isLoadingSuppliers}
|
||||||
isDisabled={type === 'detail'}
|
isDisabled={type === 'detail'}
|
||||||
isClearable
|
isClearable
|
||||||
|
isError={isRepeaterInputError(
|
||||||
|
'ekspedisi',
|
||||||
|
'supplier',
|
||||||
|
idx
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.plat_nomor`}
|
|
||||||
required
|
required
|
||||||
value={
|
name={`ekspedisi.${idx}.plat_nomor`}
|
||||||
formik.values.ekspedisi?.[index]
|
value={ekspedisi.plat_nomor ?? ''}
|
||||||
?.plat_nomor ?? ''
|
onChange={formik.handleChange}
|
||||||
}
|
onBlur={formik.handleBlur}
|
||||||
onChange={(e) =>
|
isError={isRepeaterInputError(
|
||||||
formik.setFieldValue(
|
'ekspedisi',
|
||||||
`ekspedisi.${index}.plat_nomor`,
|
'plat_nomor',
|
||||||
e.target.value
|
idx
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.no_surat_jalan`}
|
|
||||||
required
|
required
|
||||||
value={
|
name={`ekspedisi.${idx}.no_surat_jalan`}
|
||||||
formik.values.ekspedisi?.[index]
|
value={ekspedisi.no_surat_jalan ?? ''}
|
||||||
?.no_surat_jalan ?? ''
|
onChange={formik.handleChange}
|
||||||
}
|
onBlur={formik.handleBlur}
|
||||||
onChange={(e) =>
|
isError={isRepeaterInputError(
|
||||||
formik.setFieldValue(
|
'ekspedisi',
|
||||||
`ekspedisi.${index}.no_surat_jalan`,
|
'no_surat_jalan',
|
||||||
e.target.value
|
idx
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.dokumen`}
|
|
||||||
required
|
required
|
||||||
type='file'
|
type='file'
|
||||||
|
name={`ekspedisi.${idx}.dokumen`}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`ekspedisi.${index}.dokumen`,
|
`ekspedisi.${idx}.dokumen`,
|
||||||
file
|
file
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
isError={isRepeaterInputError(
|
||||||
|
'ekspedisi',
|
||||||
|
'dokumen',
|
||||||
|
idx
|
||||||
|
)}
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.biaya_ekspedisi`}
|
|
||||||
required
|
required
|
||||||
type='number'
|
type='number'
|
||||||
value={
|
name={`ekspedisi.${idx}.biaya_ekspedisi`}
|
||||||
formik.values.ekspedisi?.[index]
|
value={ekspedisi.biaya_ekspedisi ?? ''}
|
||||||
?.biaya_ekspedisi ?? ''
|
onChange={formik.handleChange}
|
||||||
}
|
onBlur={formik.handleBlur}
|
||||||
onChange={(e) =>
|
isError={isRepeaterInputError(
|
||||||
formik.setFieldValue(
|
'ekspedisi',
|
||||||
`ekspedisi.${index}.biaya_ekspedisi`,
|
'biaya_ekspedisi',
|
||||||
e.target.value
|
idx
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`ekspedisi.${index}.nama_sopir`}
|
|
||||||
required
|
required
|
||||||
value={
|
name={`ekspedisi.${idx}.nama_sopir`}
|
||||||
formik.values.ekspedisi?.[index]
|
value={ekspedisi.nama_sopir ?? ''}
|
||||||
?.nama_sopir ?? ''
|
onChange={formik.handleChange}
|
||||||
}
|
onBlur={formik.handleBlur}
|
||||||
onChange={(e) =>
|
isError={isRepeaterInputError(
|
||||||
formik.setFieldValue(
|
'ekspedisi',
|
||||||
`ekspedisi.${index}.nama_sopir`,
|
'nama_sopir',
|
||||||
e.target.value
|
idx
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full min-w-24',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
|
<td>
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='error'
|
color='error'
|
||||||
onClick={() => remove(index)}
|
onClick={() => removeEkspedisi(idx)}
|
||||||
>
|
>
|
||||||
<Icon icon='material-symbols:delete-outline' />
|
<Icon
|
||||||
|
icon='material-symbols:delete-outline-rounded'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
|
||||||
</td>
|
</td>
|
||||||
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
)) ?? []}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='primary'
|
color='success'
|
||||||
onClick={() =>
|
onClick={addEkspedisi}
|
||||||
push({
|
className='w-fit mx-auto mt-4'
|
||||||
product: null,
|
|
||||||
product_id: 0,
|
|
||||||
qty: 0,
|
|
||||||
supplier: null,
|
|
||||||
supplier_id: 0,
|
|
||||||
plat_nomor: '',
|
|
||||||
no_surat_jalan: '',
|
|
||||||
dokumen: '',
|
|
||||||
biaya_ekspedisi: 0,
|
|
||||||
nama_sopir: '',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className='mt-4'
|
|
||||||
>
|
>
|
||||||
<Icon icon='ic:round-plus' />
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
Tambah Ekspedisi
|
Tambah Ekspedisi
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</FieldArray>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -580,7 +649,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</FormikProvider>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{type !== 'add' && (
|
{type !== 'add' && (
|
||||||
|
|||||||
Reference in New Issue
Block a user