codex: initiated changes

This commit is contained in:
Adnan Zahir
2026-04-01 10:14:05 +07:00
parent 7bee13124d
commit 8d92da75cf
20 changed files with 287 additions and 204 deletions
@@ -34,6 +34,7 @@ type RecordingGrowingFormSchemaType = {
}[];
depletions: {
product_warehouse_id?: number;
source_product_warehouse_id?: number;
qty?: number | string;
}[];
};
@@ -53,6 +54,7 @@ export type StockSchema = {
export type DepletionSchema = {
product_warehouse_id?: number;
source_product_warehouse_id?: number;
qty?: number | string;
};
@@ -77,6 +79,9 @@ const DepletionObjectSchema: Yup.ObjectSchema<DepletionSchema> = Yup.object({
product_warehouse_id: Yup.number()
.optional()
.typeError('Depletions harus berupa angka!'),
source_product_warehouse_id: Yup.number()
.optional()
.typeError('Gudang sumber harus berupa angka!'),
qty: Yup.number()
.optional()
.typeError('Jumlah depletions harus berupa angka!'),
@@ -259,6 +264,7 @@ export const getRecordingGrowingFormInitialValues = (
depletion: NonNullable<CreateGrowingRecordingPayload['depletions']>[0]
) => ({
product_warehouse_id: depletion.product_warehouse_id,
source_product_warehouse_id: depletion.source_product_warehouse_id,
qty: depletion.qty,
})
) ?? [
@@ -71,6 +71,10 @@ import {
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
import { formatDate, formatNumber, cn } from '@/lib/helper';
import {
getProductWarehouseOptionLabel,
isProductWarehouseSelectableForKandang,
} from '@/lib/product-warehouse';
import toast from 'react-hot-toast';
import ApprovalSteps, {
useApprovalSteps,
@@ -202,15 +206,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
useState<string>('');
const [stockProductsLocationId, setStockProductsLocationId] =
useState<string>('');
const [stockProductsKandangId, setStockProductsKandangId] =
useState<string>('');
const [depletionProductsLocationId, setDepletionProductsLocationId] =
useState<string>('');
const [depletionProductsKandangId, setDepletionProductsKandangId] =
useState<string>('');
const [eggProductsLocationId, setEggProductsLocationId] =
useState<string>('');
const [eggProductsKandangId, setEggProductsKandangId] = useState<string>('');
const [isApproveLoading, setIsApproveLoading] = useState(false);
const [isRejectLoading, setIsRejectLoading] = useState(false);
@@ -448,22 +447,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
? projectFlockKandangDetailData.data
: undefined;
const selectedProjectFlockKandangId = useMemo(() => {
if (type === 'add') {
return projectFlockKandangLookup?.project_flock_kandang_id ?? null;
const selectedKandangId = useMemo(() => {
if (!selectedKandang?.value) {
return null;
}
return (
projectFlockKandangDetail?.id ??
initialValues?.project_flock?.project_flock_kandang_id ??
null
);
}, [
type,
projectFlockKandangLookup,
projectFlockKandangDetail,
initialValues,
]);
return Number(selectedKandang.value);
}, [selectedKandang]);
// ===== TRANSITION RESTRICTION LOGIC =====
const isTransitionPeriod = useMemo(() => {
@@ -512,6 +502,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
...(depletion.source_product_warehouse_id && {
source_product_warehouse_id:
depletion.source_product_warehouse_id,
}),
qty: Number(depletion.qty) || 0,
}))
: [];
@@ -541,6 +535,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
...(depletion.source_product_warehouse_id && {
source_product_warehouse_id: depletion.source_product_warehouse_id,
}),
qty: Number(depletion.qty) || 0,
}));
@@ -602,7 +599,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}, []);
const {
options: stockProductOptions,
setInputValue: setStockProductInputValue,
rawData: stockProducts,
isLoadingOptions: isLoadingStockProducts,
@@ -610,7 +606,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', 'search', {
flags: 'PAKAN,OVK',
location_id: stockProductsLocationId,
kandang_id: stockProductsKandangId,
});
const {
@@ -619,7 +614,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
loadMore: loadMoreDepletionProducts,
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', '', {
location_id: depletionProductsLocationId,
kandang_id: depletionProductsKandangId,
type: 'AYAM',
});
@@ -686,7 +680,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', 'search', {
type: 'TELUR',
location_id: eggProductsLocationId,
kandang_id: eggProductsKandangId,
});
const approvedProjectFlockKandangsUrl = useMemo(() => {
@@ -934,39 +927,46 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
projectFlockKandangDetail,
]);
const isProductWarehouseBelongsToSelectedProjectFlockKandang = useCallback(
(productWarehouse: ProductWarehouse) => {
if (!selectedProjectFlockKandangId) return false;
const appendProductWarehouseOption = useCallback(
(options: OptionType[], productWarehouse?: ProductWarehouse | null) => {
if (!productWarehouse) {
return;
}
return (
productWarehouse.project_flock_kandang?.id ===
selectedProjectFlockKandangId
const existingOption = options.find(
(opt) => Number(opt.value) === productWarehouse.id
);
if (!existingOption) {
options.push({
value: productWarehouse.id,
label: getProductWarehouseOptionLabel(productWarehouse),
});
}
},
[selectedProjectFlockKandangId]
[]
);
const scopedStockProductIds = useMemo(() => {
if (!isResponseSuccess(stockProducts) || !selectedProjectFlockKandangId) {
return new Set<number>();
}
const data = stockProducts.data as unknown as ProductWarehouse[];
return new Set(
data
.filter(isProductWarehouseBelongsToSelectedProjectFlockKandang)
.map((product) => product.id)
);
}, [
stockProducts,
selectedProjectFlockKandangId,
isProductWarehouseBelongsToSelectedProjectFlockKandang,
]);
const buildProductWarehouseOptions = useCallback(
(productWarehouses: ProductWarehouse[]) =>
productWarehouses
.filter((productWarehouse) =>
isProductWarehouseSelectableForKandang(
productWarehouse,
selectedKandangId
)
)
.map((productWarehouse) => ({
value: productWarehouse.id,
label: getProductWarehouseOptionLabel(productWarehouse),
})),
[selectedKandangId]
);
const unifiedStockProducts = useMemo(() => {
const options = selectedProjectFlockKandangId
? stockProductOptions.filter((option) =>
scopedStockProductIds.has(Number(option.value))
const options = isResponseSuccess(stockProducts)
? buildProductWarehouseOptions(
stockProducts.data as unknown as ProductWarehouse[]
)
: [];
@@ -977,113 +977,61 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
type !== 'add'
) {
initialValues.stocks?.forEach((stock) => {
if (stock.product_warehouse && stock.product_warehouse.product) {
const existingOption = options.find(
(opt) => opt.value === stock.product_warehouse_id
);
if (!existingOption) {
options.push({
value: stock.product_warehouse_id,
label: stock.product_warehouse.product.name,
});
}
}
appendProductWarehouseOption(options, stock.product_warehouse);
});
}
return options;
}, [
stockProductOptions,
stockProducts,
buildProductWarehouseOptions,
initialValues,
type,
selectedProjectFlockKandangId,
scopedStockProductIds,
appendProductWarehouseOption,
]);
const depletionProducts = useMemo(() => {
const options: OptionType[] = [];
if (
isResponseSuccess(depletionProductsData) &&
selectedProjectFlockKandangId
) {
const data = depletionProductsData.data as unknown as ProductWarehouse[];
data
.filter(isProductWarehouseBelongsToSelectedProjectFlockKandang)
.forEach((product) => {
options.push({
value: product.id,
label: product.product.name,
});
});
}
const options = isResponseSuccess(depletionProductsData)
? buildProductWarehouseOptions(
depletionProductsData.data as unknown as ProductWarehouse[]
)
: [];
if (initialValues && initialValues.depletions && type !== 'add') {
initialValues.depletions.forEach((depletion) => {
if (
depletion.product_warehouse &&
depletion.product_warehouse.product
) {
const existingOption = options.find(
(opt) => opt.value === depletion.product_warehouse_id
);
if (!existingOption) {
options.push({
value: depletion.product_warehouse_id,
label: depletion.product_warehouse.product.name,
});
}
}
appendProductWarehouseOption(options, depletion.product_warehouse);
});
}
return options;
}, [
depletionProductsData,
buildProductWarehouseOptions,
initialValues,
type,
selectedProjectFlockKandangId,
isProductWarehouseBelongsToSelectedProjectFlockKandang,
appendProductWarehouseOption,
]);
const eggProducts = useMemo(() => {
const options: OptionType[] = [];
if (isResponseSuccess(eggProductsData) && selectedProjectFlockKandangId) {
const data = eggProductsData.data as unknown as ProductWarehouse[];
data
.filter(isProductWarehouseBelongsToSelectedProjectFlockKandang)
.forEach((product) => {
options.push({
value: product.id,
label: product.product.name,
});
});
}
const options = isResponseSuccess(eggProductsData)
? buildProductWarehouseOptions(
eggProductsData.data as unknown as ProductWarehouse[]
)
: [];
if (initialValues && initialValues.eggs && type !== 'add') {
initialValues.eggs.forEach((egg) => {
if (egg.product_warehouse && egg.product_warehouse.product) {
const existingOption = options.find(
(opt) => opt.value === egg.product_warehouse_id
);
if (!existingOption) {
options.push({
value: egg.product_warehouse_id,
label: egg.product_warehouse.product.name,
});
}
}
appendProductWarehouseOption(options, egg.product_warehouse);
});
}
return options;
}, [
eggProductsData,
buildProductWarehouseOptions,
initialValues,
type,
selectedProjectFlockKandangId,
isProductWarehouseBelongsToSelectedProjectFlockKandang,
appendProductWarehouseOption,
]);
// ===== FORMIK SETUP =====
@@ -1628,18 +1576,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}
if (selectedLocation && kandang) {
setStockProductsLocationId(selectedLocation.value.toString());
setStockProductsKandangId(kandang.value.toString());
setDepletionProductsLocationId(selectedLocation.value.toString());
setDepletionProductsKandangId(kandang.value.toString());
setEggProductsLocationId(selectedLocation.value.toString());
setEggProductsKandangId(kandang.value.toString());
} else {
setStockProductsLocationId('');
setStockProductsKandangId('');
setDepletionProductsLocationId('');
setDepletionProductsKandangId('');
setEggProductsLocationId('');
setEggProductsKandangId('');
}
formik.setFieldTouched('project_flock_kandang', true);
formik.setFieldTouched('project_flock_kandang_id', true);
@@ -1746,11 +1688,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
setSelectedKandang(kandangOption);
setStockProductsLocationId(location.id.toString());
setStockProductsKandangId(kandang.id.toString());
setDepletionProductsLocationId(location.id.toString());
setDepletionProductsKandangId(kandang.id.toString());
setEggProductsLocationId(location.id.toString());
setEggProductsKandangId(kandang.id.toString());
if (
formik.values.project_flock_kandang_id !==