mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-114,136): update RecordingForm validation and input handling for feed and vaccination data
This commit is contained in:
@@ -49,20 +49,19 @@ export const RecordingFormSchema = Yup.object({
|
|||||||
.of(
|
.of(
|
||||||
Yup.object({
|
Yup.object({
|
||||||
feed_id: Yup.string().required('Nama pakan wajib diisi!'),
|
feed_id: Yup.string().required('Nama pakan wajib diisi!'),
|
||||||
feed_qty: Yup.number()
|
feed_qty: Yup.mixed<number | ''>().notRequired(),
|
||||||
.required('Qty pakan wajib diisi!')
|
|
||||||
.min(1, 'Qty minimal 1!')
|
|
||||||
.typeError('Qty pakan wajib diisi!'),
|
|
||||||
feed_stock: Yup.number()
|
feed_stock: Yup.number()
|
||||||
.required('Stock pakan wajib diisi!')
|
.required('Jumlah pakan yang digunakan wajib diisi!')
|
||||||
.min(1, 'Stock minimal 1!')
|
.min(1, 'Jumlah pakan minimal 1 kg!')
|
||||||
.typeError('Stock pakan wajib diisi!')
|
.typeError('Jumlah pakan yang digunakan harus berupa angka!')
|
||||||
.test(
|
.test(
|
||||||
'is-not-exceed-qty',
|
'is-not-exceed-qty',
|
||||||
'Feed stock tidak boleh melebihi feed qty yang tersedia!',
|
'Jumlah pakan yang digunakan tidak boleh melebihi stok tersedia!',
|
||||||
function (value) {
|
function (value) {
|
||||||
const { feed_qty } = this.parent;
|
const { feed_qty } = this.parent;
|
||||||
return value === undefined || value <= feed_qty;
|
if (value === undefined) return true;
|
||||||
|
if (feed_qty === undefined || feed_qty === '' || typeof feed_qty !== 'number') return true;
|
||||||
|
return value <= feed_qty;
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -74,13 +73,16 @@ export const RecordingFormSchema = Yup.object({
|
|||||||
Yup.object({
|
Yup.object({
|
||||||
chicken_weight: Yup.number()
|
chicken_weight: Yup.number()
|
||||||
.required('Berat ayam wajib diisi!')
|
.required('Berat ayam wajib diisi!')
|
||||||
.min(1, 'Berat minimal 1!'),
|
.min(1, 'Berat ayam minimal 1 gram!')
|
||||||
|
.typeError('Berat ayam harus berupa angka!'),
|
||||||
chicken_count: Yup.number()
|
chicken_count: Yup.number()
|
||||||
.required('Jumlah ayam wajib diisi!')
|
.required('Jumlah ayam wajib diisi!')
|
||||||
.min(1, 'Jumlah minimal 1!'),
|
.min(1, 'Jumlah ayam minimal 1 ekor!')
|
||||||
|
.typeError('Jumlah ayam harus berupa angka!'),
|
||||||
average_chicken_weight: Yup.number()
|
average_chicken_weight: Yup.number()
|
||||||
.required('Rata-rata berat ayam wajib diisi!')
|
.required('Rata-rata berat ayam wajib diisi!')
|
||||||
.min(1, 'Rata-rata minimal 1!'),
|
.min(1, 'Rata-rata berat ayam minimal 1 gram!')
|
||||||
|
.typeError('Rata-rata berat ayam harus berupa angka!'),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.min(1, 'Minimal harus ada 1 data bobot badan!')
|
.min(1, 'Minimal harus ada 1 data bobot badan!')
|
||||||
@@ -89,20 +91,19 @@ export const RecordingFormSchema = Yup.object({
|
|||||||
.of(
|
.of(
|
||||||
Yup.object({
|
Yup.object({
|
||||||
vaccine_id: Yup.string().required('Nama vaksin wajib diisi!'),
|
vaccine_id: Yup.string().required('Nama vaksin wajib diisi!'),
|
||||||
total_stock: Yup.number()
|
total_stock: Yup.mixed<number | ''>().notRequired(),
|
||||||
.required('Total stock wajib diisi!')
|
|
||||||
.min(1, 'Total stock minimal 1!')
|
|
||||||
.typeError('Total stock wajib diisi!'),
|
|
||||||
used_stock: Yup.number()
|
used_stock: Yup.number()
|
||||||
.required('Jumlah stock wajib diisi!')
|
.required('Jumlah vaksin yang digunakan wajib diisi!')
|
||||||
.min(1, 'Jumlah stock minimal 1!')
|
.min(1, 'Jumlah vaksin minimal 1!')
|
||||||
.typeError('Jumlah stock wajib diisi!')
|
.typeError('Jumlah vaksin yang digunakan harus berupa angka!')
|
||||||
.test(
|
.test(
|
||||||
'is-not-exceed-total',
|
'is-not-exceed-total',
|
||||||
'Used stock tidak boleh melebihi total stock yang tersedia!',
|
'Jumlah vaksin yang digunakan tidak boleh melebihi stok tersedia!',
|
||||||
function (value) {
|
function (value) {
|
||||||
const { total_stock } = this.parent;
|
const { total_stock } = this.parent;
|
||||||
return value === undefined || value <= total_stock;
|
if (value === undefined) return true;
|
||||||
|
if (total_stock === undefined || total_stock === '' || typeof total_stock !== 'number') return true;
|
||||||
|
return value <= total_stock;
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -119,8 +120,9 @@ export const RecordingFormSchema = Yup.object({
|
|||||||
)
|
)
|
||||||
.required('Kondisi wajib diisi!'),
|
.required('Kondisi wajib diisi!'),
|
||||||
count: Yup.number()
|
count: Yup.number()
|
||||||
.required('Jumlah wajib diisi!')
|
.required('Jumlah mortalitas wajib diisi!')
|
||||||
.min(1, 'Jumlah minimal 1!'),
|
.min(1, 'Jumlah mortalitas minimal 1 ekor!')
|
||||||
|
.typeError('Jumlah mortalitas harus berupa angka!'),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.min(1, 'Minimal harus ada 1 data mortalitas!')
|
.min(1, 'Minimal harus ada 1 data mortalitas!')
|
||||||
@@ -167,7 +169,7 @@ export const getRecordingFormInitialValues = (
|
|||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
feed_id: '',
|
feed_id: '',
|
||||||
feed_qty: 0,
|
feed_qty: '',
|
||||||
feed_stock: 0,
|
feed_stock: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -187,7 +189,7 @@ export const getRecordingFormInitialValues = (
|
|||||||
: [
|
: [
|
||||||
{
|
{
|
||||||
vaccine_id: '',
|
vaccine_id: '',
|
||||||
total_stock: 0,
|
total_stock: '',
|
||||||
used_stock: 0,
|
used_stock: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
: '',
|
: '',
|
||||||
feed_data: (values.feed_data ?? []).map((p) => ({
|
feed_data: (values.feed_data ?? []).map((p) => ({
|
||||||
feed_id: p.feed_id,
|
feed_id: p.feed_id,
|
||||||
feed_qty: p.feed_qty,
|
feed_qty: typeof p.feed_qty === 'number' ? p.feed_qty : 0,
|
||||||
feed_stock: p.feed_stock,
|
feed_stock: p.feed_stock,
|
||||||
})),
|
})),
|
||||||
body_weight: (values.body_weight ?? []).map((b) => ({
|
body_weight: (values.body_weight ?? []).map((b) => ({
|
||||||
@@ -84,7 +84,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
})),
|
})),
|
||||||
vaccination: (values.vaccination ?? []).map((v) => ({
|
vaccination: (values.vaccination ?? []).map((v) => ({
|
||||||
vaccine_id: v.vaccine_id,
|
vaccine_id: v.vaccine_id,
|
||||||
total_stock: v.total_stock,
|
total_stock: typeof v.total_stock === 'number' ? v.total_stock : 0,
|
||||||
used_stock: v.used_stock,
|
used_stock: v.used_stock,
|
||||||
})),
|
})),
|
||||||
mortality: (values.mortality ?? []).map((m) => ({
|
mortality: (values.mortality ?? []).map((m) => ({
|
||||||
@@ -132,8 +132,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
// Create stock mapping for pakan (Feed)
|
// Create stock mapping for pakan (Feed)
|
||||||
const pakanStockMap = useMemo(() => {
|
const pakanStockMap = useMemo(() => {
|
||||||
if (!isResponseSuccess(pakanProducts)) return new Map<number, number>();
|
if (!isResponseSuccess(pakanProducts))
|
||||||
const map = new Map<number, number>();
|
return new Map<number, number | ''>();
|
||||||
|
const map = new Map<number, number | ''>();
|
||||||
pakanProducts.data.forEach((product) => {
|
pakanProducts.data.forEach((product) => {
|
||||||
map.set(product.id, product.quantity);
|
map.set(product.id, product.quantity);
|
||||||
});
|
});
|
||||||
@@ -155,8 +156,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
// Create stock mapping for OVK (Vaccination)
|
// Create stock mapping for OVK (Vaccination)
|
||||||
const ovkStockMap = useMemo(() => {
|
const ovkStockMap = useMemo(() => {
|
||||||
if (!isResponseSuccess(ovkProducts)) return new Map<number, number>();
|
if (!isResponseSuccess(ovkProducts)) return new Map<number, number | ''>();
|
||||||
const map = new Map<number, number>();
|
const map = new Map<number, number | ''>();
|
||||||
ovkProducts.data.forEach((product) => {
|
ovkProducts.data.forEach((product) => {
|
||||||
map.set(product.id, product.quantity);
|
map.set(product.id, product.quantity);
|
||||||
});
|
});
|
||||||
@@ -256,8 +257,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
...(formik.values.feed_data || []),
|
...(formik.values.feed_data || []),
|
||||||
{
|
{
|
||||||
feed: null,
|
feed: null,
|
||||||
feed_id: 0,
|
feed_id: '',
|
||||||
feed_qty: 0,
|
feed_qty: '',
|
||||||
feed_stock: 0,
|
feed_stock: 0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -311,8 +312,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
...(formik.values.vaccination || []),
|
...(formik.values.vaccination || []),
|
||||||
{
|
{
|
||||||
vaccine: null,
|
vaccine: null,
|
||||||
vaccine_id: 0,
|
vaccine_id: '',
|
||||||
total_stock: 0,
|
total_stock: '',
|
||||||
used_stock: 0,
|
used_stock: 0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -532,10 +533,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
const productWarehouseId =
|
const productWarehouseId =
|
||||||
(val as OptionType)?.value ?? 0;
|
(val as OptionType)?.value ?? 0;
|
||||||
const stock =
|
const stock = productWarehouseId
|
||||||
pakanStockMap.get(
|
? (pakanStockMap.get(
|
||||||
productWarehouseId as number
|
productWarehouseId as number
|
||||||
) ?? 0;
|
) ?? '')
|
||||||
|
: '';
|
||||||
|
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`feed_data.${idx}.feed`,
|
`feed_data.${idx}.feed`,
|
||||||
@@ -543,12 +545,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`feed_data.${idx}.feed_id`,
|
`feed_data.${idx}.feed_id`,
|
||||||
productWarehouseId
|
productWarehouseId || ''
|
||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`feed_data.${idx}.feed_qty`,
|
`feed_data.${idx}.feed_qty`,
|
||||||
stock
|
stock
|
||||||
);
|
);
|
||||||
|
// Reset feed_stock when changing feed
|
||||||
|
formik.setFieldValue(
|
||||||
|
`feed_data.${idx}.feed_stock`,
|
||||||
|
0
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
options={pakanOptions}
|
options={pakanOptions}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
@@ -569,21 +576,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
required
|
type='text'
|
||||||
type='number'
|
|
||||||
name={`feed_data.${idx}.feed_qty`}
|
name={`feed_data.${idx}.feed_qty`}
|
||||||
value={feed.feed_qty}
|
value={
|
||||||
|
feed.feed_qty === '' ||
|
||||||
|
feed.feed_qty === undefined
|
||||||
|
? ''
|
||||||
|
: String(feed.feed_qty)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
isError={
|
|
||||||
isRepeaterInputError('feed_data', 'feed_qty', idx)
|
|
||||||
.isError
|
|
||||||
}
|
|
||||||
errorMessage={
|
|
||||||
isRepeaterInputError('feed_data', 'feed_qty', idx)
|
|
||||||
.errorMessage
|
|
||||||
}
|
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
|
placeholder='Pilih pakan terlebih dahulu'
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full min-w-24',
|
wrapper: 'w-full min-w-24',
|
||||||
}}
|
}}
|
||||||
@@ -946,9 +950,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
const productWarehouseId =
|
const productWarehouseId =
|
||||||
(val as OptionType)?.value ?? 0;
|
(val as OptionType)?.value ?? 0;
|
||||||
const stock =
|
const stock = productWarehouseId
|
||||||
ovkStockMap.get(productWarehouseId as number) ??
|
? (ovkStockMap.get(
|
||||||
0;
|
productWarehouseId as number
|
||||||
|
) ?? '')
|
||||||
|
: '';
|
||||||
|
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`vaccination.${idx}.vaccine`,
|
`vaccination.${idx}.vaccine`,
|
||||||
@@ -956,12 +962,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`vaccination.${idx}.vaccine_id`,
|
`vaccination.${idx}.vaccine_id`,
|
||||||
productWarehouseId
|
productWarehouseId || ''
|
||||||
);
|
);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`vaccination.${idx}.total_stock`,
|
`vaccination.${idx}.total_stock`,
|
||||||
stock
|
stock
|
||||||
);
|
);
|
||||||
|
// Reset used_stock when changing vaccine
|
||||||
|
formik.setFieldValue(
|
||||||
|
`vaccination.${idx}.used_stock`,
|
||||||
|
0
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
options={ovkOptions}
|
options={ovkOptions}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
@@ -988,27 +999,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<TextInput
|
||||||
required
|
type='text'
|
||||||
type='number'
|
|
||||||
name={`vaccination.${idx}.total_stock`}
|
name={`vaccination.${idx}.total_stock`}
|
||||||
value={vaccine.total_stock}
|
value={
|
||||||
|
vaccine.total_stock === '' ||
|
||||||
|
vaccine.total_stock === undefined
|
||||||
|
? ''
|
||||||
|
: String(vaccine.total_stock)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
isError={
|
|
||||||
isRepeaterInputError(
|
|
||||||
'vaccination',
|
|
||||||
'total_stock',
|
|
||||||
idx
|
|
||||||
).isError
|
|
||||||
}
|
|
||||||
errorMessage={
|
|
||||||
isRepeaterInputError(
|
|
||||||
'vaccination',
|
|
||||||
'total_stock',
|
|
||||||
idx
|
|
||||||
).errorMessage
|
|
||||||
}
|
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
|
placeholder='Pilih vaksin terlebih dahulu'
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full min-w-24',
|
wrapper: 'w-full min-w-24',
|
||||||
}}
|
}}
|
||||||
@@ -1189,13 +1191,15 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TextInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
type='number'
|
|
||||||
name={`mortality.${idx}.count`}
|
name={`mortality.${idx}.count`}
|
||||||
value={mortality.count}
|
value={mortality.count}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
onBlur={formik.handleBlur}
|
onBlur={formik.handleBlur}
|
||||||
|
maskType='number'
|
||||||
|
decimals={0}
|
||||||
|
min={0}
|
||||||
isError={
|
isError={
|
||||||
isRepeaterInputError('mortality', 'count', idx)
|
isRepeaterInputError('mortality', 'count', idx)
|
||||||
.isError
|
.isError
|
||||||
|
|||||||
Reference in New Issue
Block a user