diff --git a/src/components/pages/production/recording/form/RecordingForm.schema.ts b/src/components/pages/production/recording/form/RecordingForm.schema.ts index e4cf7a49..51d176f1 100644 --- a/src/components/pages/production/recording/form/RecordingForm.schema.ts +++ b/src/components/pages/production/recording/form/RecordingForm.schema.ts @@ -5,6 +5,7 @@ import { CreateLayingRecordingPayload, CreateEggPayload, } from '@/types/api/production/recording'; +import { getProductWarehouseOptionLabel } from '@/lib/product-warehouse'; type RecordingGrowingFormSchemaType = { record_date: string; @@ -29,11 +30,19 @@ type RecordingGrowingFormSchemaType = { } | null; project_flock_kandang_id: number; stocks: { - product_warehouse_id: number; + product_warehouse_id: + | { + value: number; + label: string; + } + | undefined; qty: number | string; }[]; depletions: { - product_warehouse_id?: number; + product_warehouse_id?: { + value: number; + label: string; + }; source_product_warehouse_id?: number; qty?: number | string; }[]; @@ -41,34 +50,48 @@ type RecordingGrowingFormSchemaType = { type RecordingLayingFormSchemaType = RecordingGrowingFormSchemaType & { eggs: { - product_warehouse_id?: number; + product_warehouse_id?: { + value: number; + label: string; + }; qty?: number | string; weight?: number | string; }[]; }; export type StockSchema = { - product_warehouse_id: number; + product_warehouse_id: { + value: number; + label: string; + }; qty: number | string; }; export type DepletionSchema = { - product_warehouse_id?: number; + product_warehouse_id?: { + value: number; + label: string; + }; source_product_warehouse_id?: number; qty?: number | string; }; export type EggSchema = { - product_warehouse_id?: number; + product_warehouse_id?: { + value: number; + label: string; + }; qty?: number | string; weight?: number | string; }; const StockObjectSchema: Yup.ObjectSchema = Yup.object({ - product_warehouse_id: Yup.number() + product_warehouse_id: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) .required('Produk wajib diisi!') - .min(1, 'Produk wajib diisi!') - .typeError('Produk harus berupa angka!'), + .typeError('Produk wajib diisi!'), qty: Yup.number() .required('Jumlah penggunaan wajib diisi!') .moreThan(0, 'Jumlah penggunaan harus lebih dari 0!') @@ -76,7 +99,10 @@ const StockObjectSchema: Yup.ObjectSchema = Yup.object({ }); const DepletionObjectSchema: Yup.ObjectSchema = Yup.object({ - product_warehouse_id: Yup.number() + product_warehouse_id: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) .optional() .typeError('Depletions harus berupa angka!'), source_product_warehouse_id: Yup.number() @@ -88,7 +114,10 @@ const DepletionObjectSchema: Yup.ObjectSchema = Yup.object({ }); const EggObjectSchema: Yup.ObjectSchema = Yup.object({ - product_warehouse_id: Yup.number() + product_warehouse_id: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) .optional() .typeError('Kondisi telur harus berupa angka!'), qty: Yup.number().optional().typeError('Jumlah telur harus berupa angka!'), @@ -248,14 +277,17 @@ export const getRecordingGrowingFormInitialValues = ( initialValues?.project_flock?.project_flock_kandang_id ?? 0, stocks: initialValues?.stocks?.map((stock) => ({ - product_warehouse_id: stock.product_warehouse_id, + product_warehouse_id: { + value: stock.product_warehouse_id, + label: getProductWarehouseOptionLabel(stock.product_warehouse), + }, qty: (stock as { qty?: number; usage_amount?: number }).qty || (stock as { qty?: number; usage_amount?: number }).usage_amount || '', })) ?? [ { - product_warehouse_id: 0, + product_warehouse_id: undefined, qty: '', }, ], @@ -263,13 +295,16 @@ export const getRecordingGrowingFormInitialValues = ( ( depletion: NonNullable[0] ) => ({ - product_warehouse_id: depletion.product_warehouse_id, + product_warehouse_id: { + value: Number(depletion.product_warehouse_id ?? 0), + label: getProductWarehouseOptionLabel(depletion.product_warehouse), + }, source_product_warehouse_id: depletion.source_product_warehouse_id, qty: depletion.qty, }) ) ?? [ { - product_warehouse_id: 0, + product_warehouse_id: undefined, qty: '', }, ], @@ -281,12 +316,15 @@ export const getRecordingLayingFormInitialValues = ( ...getRecordingGrowingFormInitialValues(initialValues), eggs: initialValues?.eggs?.map((egg: CreateEggPayload) => ({ - product_warehouse_id: egg.product_warehouse_id, + product_warehouse_id: { + value: Number(egg.product_warehouse_id ?? 0), + label: getProductWarehouseOptionLabel(egg.product_warehouse), + }, qty: egg.qty, weight: egg.weight, })) ?? [ { - product_warehouse_id: 0, + product_warehouse_id: undefined, qty: '', weight: '', }, diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 3b584cfe..ec56bba7 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -522,7 +522,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ? values.depletions ?.filter((d) => d.product_warehouse_id && d.qty) .map((depletion) => ({ - product_warehouse_id: depletion.product_warehouse_id!, + product_warehouse_id: depletion.product_warehouse_id?.value ?? 0, ...(depletion.source_product_warehouse_id && { source_product_warehouse_id: depletion.source_product_warehouse_id, @@ -533,13 +533,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const stocks = recordingRestriction.canEditStock ? (values.stocks ?? []) - .filter((s) => s.product_warehouse_id && s.qty) + .filter((s) => s.product_warehouse_id?.value && s.qty) .map((stock) => ({ // In migration mode, product_warehouse_id field holds product.id; // send it as product_id so the backend auto-creates the warehouse entry. ...(isMigrationMode - ? { product_id: stock.product_warehouse_id } - : { product_warehouse_id: stock.product_warehouse_id }), + ? { product_id: stock.product_warehouse_id?.value } + : { product_warehouse_id: stock.product_warehouse_id?.value }), qty: Number(stock.qty) || 0, })) : []; @@ -561,9 +561,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const createLayingPayload = useCallback( (values: RecordingLayingFormValues) => { const depletions = values.depletions - ?.filter((d) => d.product_warehouse_id && d.qty) + ?.filter((d) => d.product_warehouse_id?.value && d.qty) .map((depletion) => ({ - product_warehouse_id: depletion.product_warehouse_id!, + product_warehouse_id: depletion.product_warehouse_id?.value ?? 0, ...(depletion.source_product_warehouse_id && { source_product_warehouse_id: depletion.source_product_warehouse_id, }), @@ -573,7 +573,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const eggs = values.eggs ?.filter((e) => e.product_warehouse_id && e.qty && e.weight) .map((egg) => ({ - product_warehouse_id: egg.product_warehouse_id!, + product_warehouse_id: egg.product_warehouse_id?.value ?? 0, qty: Number(egg.qty) || 0, weight: typeof egg.weight === 'number' @@ -583,11 +583,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const stocks = recordingRestriction.canEditStock ? values.stocks - .filter((s) => s.product_warehouse_id && s.qty) + .filter((s) => s.product_warehouse_id?.value && s.qty) .map((stock) => ({ ...(isMigrationMode - ? { product_id: stock.product_warehouse_id } - : { product_warehouse_id: stock.product_warehouse_id }), + ? { product_id: stock.product_warehouse_id?.value } + : { product_warehouse_id: stock.product_warehouse_id?.value }), qty: Number(stock.qty) || 0, })) : []; @@ -1283,8 +1283,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { // product_warehouse object returned by the API. if (isMigrationMode && type === 'edit' && initialValues?.stocks?.length) { baseValues.stocks = initialValues.stocks.map((stock) => ({ - product_warehouse_id: - stock.product_warehouse?.product_id ?? stock.product_warehouse_id, + product_warehouse_id: { + value: Number( + stock.product_warehouse?.product_id ?? stock.product_warehouse_id + ), + label: getProductWarehouseOptionLabel(stock.product_warehouse), + }, qty: stock.usage_amount ?? '', })); } @@ -1438,8 +1442,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { formik.setFieldValue( 'stocks', initialValues.stocks.map((stock) => ({ - product_warehouse_id: - stock.product_warehouse?.product_id ?? stock.product_warehouse_id, + product_warehouse_id: { + value: Number( + stock.product_warehouse?.product_id ?? stock.product_warehouse_id + ), + label: getProductWarehouseOptionLabel(stock.product_warehouse), + }, qty: stock.usage_amount ?? '', })) ); @@ -1462,7 +1470,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { (stockIdx: number) => { if ((type as 'add' | 'edit' | 'detail') === 'detail') return null; const stock = formik.values.stocks?.[stockIdx]; - if (!stock || !stock.product_warehouse_id) return null; + if (!stock || !stock.product_warehouse_id?.value) return null; return null; }, [formik.values.stocks, type] @@ -1492,13 +1500,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const getStockUsageAdornment = useCallback( (stockIdx: number) => { const stock = formik.values.stocks?.[stockIdx]; - if (!stock || !stock.product_warehouse_id) return null; + if (!stock || !stock.product_warehouse_id?.value) return null; const isDetail = (type as 'add' | 'edit' | 'detail') === 'detail'; - const availableStock = getAvailableStock(stock.product_warehouse_id); + const availableStock = getAvailableStock( + stock.product_warehouse_id.value + ); const requestedUsage = Number(stock.qty) || 0; const remainingStock = availableStock - requestedUsage; - const { pendingQty } = getStockPendingInfo(stock.product_warehouse_id); + const { pendingQty } = getStockPendingInfo( + stock.product_warehouse_id.value + ); if (isDetail) { if (pendingQty > 0) { @@ -1605,10 +1617,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { return ( idx !== currentIdx && s.product_warehouse_id && - s.product_warehouse_id !== 0 + s.product_warehouse_id.value !== 0 ); }) - .map((s) => s.product_warehouse_id) || []; + .map((s) => s.product_warehouse_id?.value) || []; return unifiedStockProducts.filter( (opt) => !selectedProductIds.includes(Number(opt.value)) @@ -1625,10 +1637,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { return ( idx !== currentIdx && d.product_warehouse_id && - d.product_warehouse_id !== 0 + d.product_warehouse_id.value !== 0 ); }) - .map((d) => d.product_warehouse_id) || []; + .map((d) => d.product_warehouse_id?.value) || []; return depletionProducts.filter( (opt) => !selectedProductIds.includes(Number(opt.value)) @@ -1645,10 +1657,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { return ( idx !== currentIdx && e.product_warehouse_id && - e.product_warehouse_id !== 0 + e.product_warehouse_id.value !== 0 ); }) - .map((e) => e.product_warehouse_id) || []; + .map((e) => e.product_warehouse_id?.value) || []; return eggProducts.filter( (opt) => !selectedProductIds.includes(Number(opt.value)) @@ -1694,7 +1706,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { isError: touchedField && Boolean(errorField?.[column]), errorMessage: touchedField && errorField?.[column] - ? (errorField[column] as string) + ? errorField[column] instanceof Object + ? (errorField[column] as OptionType)?.label + : (errorField[column] as string) : '', }; }; @@ -2901,20 +2915,15 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { - product.value === stock.product_warehouse_id - ) || null - } + key={`stock-product-${idx}-${stock.product_warehouse_id?.value}`} + value={stock.product_warehouse_id} onInputChange={setStockInputValue} onChange={(selectedOption) => { const option = selectedOption as OptionType | null; formik.setFieldValue( `stocks.${idx}.product_warehouse_id`, - option?.value || 0 + option ); }} options={getAvailableStockProductOptions(idx)} @@ -2950,9 +2959,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { } isClearable={type !== 'detail'} inputPrefix={ - stock.product_warehouse_id + stock.product_warehouse_id?.value ? getProductFlagBadgeAdornment( - stock.product_warehouse_id + stock.product_warehouse_id.value ) : undefined } @@ -2988,7 +2997,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { inputSuffix={ stock.product_warehouse_id ? getProductUomSuffix( - stock.product_warehouse_id, + stock.product_warehouse_id.value, 'stock' ) : null @@ -3181,19 +3190,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} - product.value === - depletion.product_warehouse_id - ) || null - } + value={depletion.product_warehouse_id} onChange={(selectedOption) => { const option = selectedOption as OptionType | null; formik.setFieldValue( `depletions.${idx}.product_warehouse_id`, - option?.value || 0 + option ); }} options={getAvailableDepletionProductOptions(idx)} @@ -3256,7 +3259,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { inputSuffix={ depletion.product_warehouse_id ? getProductUomSuffix( - depletion.product_warehouse_id, + depletion.product_warehouse_id.value, 'depletion' ) : null @@ -3434,18 +3437,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} - product.value === egg.product_warehouse_id - ) || null - } + value={egg.product_warehouse_id} onChange={(selectedOption) => { const option = selectedOption as OptionType | null; formik.setFieldValue( `eggs.${idx}.product_warehouse_id`, - option?.value || 0 + option ); }} options={getAvailableEggProductOptions(idx)} diff --git a/src/types/api/production/recording.d.ts b/src/types/api/production/recording.d.ts index 04392ae4..98f56058 100644 --- a/src/types/api/production/recording.d.ts +++ b/src/types/api/production/recording.d.ts @@ -117,6 +117,7 @@ export type CreateGrowingRecordingPayload = { product_warehouse_id?: number; source_product_warehouse_id?: number; qty?: number; + product_warehouse?: ProductWarehouse; }[]; }; @@ -124,6 +125,7 @@ export type CreateEggPayload = { product_warehouse_id?: number; qty?: number; weight?: number; + product_warehouse?: ProductWarehouse; }; export type CreateLayingRecordingPayload = CreateGrowingRecordingPayload & {