From 244d800874505b062a43f57eb5a1247532f6bf29 Mon Sep 17 00:00:00 2001 From: Adnan Zahir Date: Tue, 14 Apr 2026 13:10:53 +0700 Subject: [PATCH 1/8] codex/fix: uniformity week calculation --- .../uniformity/form/UniformityForm.schema.ts | 9 +-- .../uniformity/form/UniformityForm.tsx | 73 ------------------- .../uniformity/form/UniformityResultForm.tsx | 1 - src/services/api/uniformity.ts | 1 - src/types/api/production/uniformity.d.ts | 1 - 5 files changed, 1 insertion(+), 84 deletions(-) diff --git a/src/components/pages/production/uniformity/form/UniformityForm.schema.ts b/src/components/pages/production/uniformity/form/UniformityForm.schema.ts index 037180f0..ad2f1e61 100644 --- a/src/components/pages/production/uniformity/form/UniformityForm.schema.ts +++ b/src/components/pages/production/uniformity/form/UniformityForm.schema.ts @@ -3,7 +3,6 @@ import { Uniformity } from '@/types/api/production/uniformity'; type UniformityFormSchemaType = { date: string; - week: number; location?: { value: number; label: string; @@ -45,10 +44,6 @@ const FileSchema = Yup.mixed() export const UniformityFormSchema: Yup.ObjectSchema = Yup.object({ date: Yup.string().required('Tanggal wajib diisi!'), - week: Yup.number() - .min(1, 'Minggu ke wajib diisi!') - .required('Minggu ke wajib diisi!') - .typeError('Minggu ke wajib diisi!'), location: Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), @@ -81,7 +76,6 @@ export type UniformityFormValues = Yup.InferType; export type UniformityFormData = { date: string; - week: number; project_flock_kandang_id: number; document: File | null; document_name: string; @@ -91,8 +85,7 @@ export const getUniformityFormInitialValues = ( initialValues?: Partial ): UniformityFormValues => { return { - date: initialValues?.week ? '' : '', - week: initialValues?.week ?? 0, + date: '', location: null, location_id: 0, project_flock: null, diff --git a/src/components/pages/production/uniformity/form/UniformityForm.tsx b/src/components/pages/production/uniformity/form/UniformityForm.tsx index 80668748..46c97278 100644 --- a/src/components/pages/production/uniformity/form/UniformityForm.tsx +++ b/src/components/pages/production/uniformity/form/UniformityForm.tsx @@ -27,7 +27,6 @@ import { LocationApi } from '@/services/api/master-data'; import { ProjectFlockApi, ProjectFlockKandangApi, - RecordingApi, } from '@/services/api/production'; import { UniformityApi } from '@/services/api/uniformity'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; @@ -40,7 +39,6 @@ import { ProjectFlockKandangLookup, ProjectFlock, } from '@/types/api/production/project-flock'; -import { Recording } from '@/types/api/production/recording'; import { Kandang } from '@/types/api/master-data/kandang'; import UniformityPreviewForm from '@/components/pages/production/uniformity/form/UniformityPreviewForm'; import UniformityResultForm from '@/components/pages/production/uniformity/form/UniformityResultForm'; @@ -204,23 +202,6 @@ const UniformityForm = ({ ? projectFlockKandangLookupData.data : undefined; - // ===== RECORDINGS DATA (FOR WEEK CALCULATION) ===== - const recordingsUrl = useMemo(() => { - if (!projectFlockKandangLookup?.project_flock_kandang_id) return null; - const params = new URLSearchParams({ - page: '1', - limit: '100', - project_flock_kandang_id: - projectFlockKandangLookup.project_flock_kandang_id.toString(), - }); - return `${RecordingApi.basePath}?${params.toString()}`; - }, [projectFlockKandangLookup?.project_flock_kandang_id]); - - const { data: recordingsData } = useSWR( - recordingsUrl, - recordingsUrl ? RecordingApi.getAllFetcher : null - ); - // ===== FORM CONFIGURATION ===== const formikInitialValues = useMemo( () => getUniformityFormInitialValues(initialValues), @@ -246,7 +227,6 @@ const UniformityForm = ({ setUniformityFormData({ date: values.date, - week: values.week, project_flock_kandang_id: projectFlockKandangId, document: values.document as File, document_name: (values.document as File).name, @@ -475,59 +455,6 @@ const UniformityForm = ({ generateUniformityTemplate(population, projectFlockKandangLookup); }, [projectFlockKandangLookup]); - // ===== SIDE EFFECTS ===== - useEffect(() => { - if ( - projectFlockKandangLookup?.chick_in_date && - projectFlockKandangLookup?.project_flock_kandang_id - ) { - const chickInDate = new Date(projectFlockKandangLookup.chick_in_date); - chickInDate.setHours(0, 0, 0, 0); - - let initialWeek = 18; - - if ( - isResponseSuccess(recordingsData) && - recordingsData.data && - recordingsData.data.length > 0 - ) { - const sortedRecordings = [...recordingsData.data].sort( - (a: Recording, b: Recording) => - new Date(a.record_datetime).getTime() - - new Date(b.record_datetime).getTime() - ); - - const earliestRecording = sortedRecordings[0]; - if (earliestRecording?.project_flock?.production_standart?.week) { - initialWeek = - earliestRecording.project_flock.production_standart.week; - } - } - - if (formik.values.date) { - const selectedDate = new Date(formik.values.date); - selectedDate.setHours(0, 0, 0, 0); - - const daysDiff = Math.floor( - (selectedDate.getTime() - chickInDate.getTime()) / - (1000 * 60 * 60 * 24) - ); - - const weeksDiff = Math.floor(daysDiff / 7); - - setFieldValue('week', initialWeek + weeksDiff); - } else { - setFieldValue('week', initialWeek); - } - } - }, [ - projectFlockKandangLookup?.chick_in_date, - projectFlockKandangLookup?.project_flock_kandang_id, - recordingsData, - formik.values.date, - setFieldValue, - ]); - useEffect(() => { const unsub = subscribeValidate(() => { setIsValid(true); diff --git a/src/components/pages/production/uniformity/form/UniformityResultForm.tsx b/src/components/pages/production/uniformity/form/UniformityResultForm.tsx index 108cb4f8..a5dda1e4 100644 --- a/src/components/pages/production/uniformity/form/UniformityResultForm.tsx +++ b/src/components/pages/production/uniformity/form/UniformityResultForm.tsx @@ -63,7 +63,6 @@ const UniformityResultForm = () => { try { const payload = { date: uniformityFormData.date, - week: uniformityFormData.week, project_flock_kandang_id: uniformityFormData.project_flock_kandang_id, document: uniformityFormData.document, }; diff --git a/src/services/api/uniformity.ts b/src/services/api/uniformity.ts index 7ed8098e..dda35787 100644 --- a/src/services/api/uniformity.ts +++ b/src/services/api/uniformity.ts @@ -56,7 +56,6 @@ export class UniformityApiService extends BaseApiService< ): Promise | undefined> { const formData = new FormData(); formData.append('date', payload.date); - formData.append('week', payload.week.toString()); formData.append( 'project_flock_kandang_id', payload.project_flock_kandang_id.toString() diff --git a/src/types/api/production/uniformity.d.ts b/src/types/api/production/uniformity.d.ts index 825607d8..b4ff2ed8 100644 --- a/src/types/api/production/uniformity.d.ts +++ b/src/types/api/production/uniformity.d.ts @@ -146,7 +146,6 @@ export type CreateUniformityPayload = { date: string; project_flock_kandang_id: number; document: File; - week: number; }; export type VerifyUniformityPayload = { From 8dc62453bdf8d56653f01e602b59d2fc6b02cfaa Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 14 Apr 2026 13:31:40 +0700 Subject: [PATCH 2/8] fix(FE-form-object-missmatch): Refactor purchase item handling in approval forms and schemas --- .../order/PurchaseOrderAcceptApprovalForm.tsx | 3 +-- .../form/order/PurchaseOrderForm.schema.ts | 25 ++++--------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx index 2eacfbad..7ab0dc81 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx @@ -294,7 +294,6 @@ const PurchaseOrderAcceptApprovalForm = ({ item.expedition_vendor_id || item.expedition_vendor?.id || null; return { - purchase_item: null, purchase_item_id: item.id, received_date: item.received_date ? new Date(item.received_date).toISOString().split('T')[0] @@ -573,7 +572,7 @@ const PurchaseOrderAcceptApprovalForm = ({ expeditionVendorChangeHandler(idx, val) diff --git a/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts b/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts index 9e6f43b0..aac4fa50 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts +++ b/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts @@ -31,10 +31,6 @@ type PurchaseRequestAcceptApprovalFormSchemaType = { action: 'APPROVED' | 'REJECTED'; notes: string | null; items: { - purchase_item?: { - value: number; - label: string; - } | null; purchase_item_id: number; received_date: string; travel_number: string; @@ -68,10 +64,6 @@ export type PurchaseStaffApprovalItemSchema = { }; export type PurchaseAcceptApprovalItemSchema = { - purchase_item?: { - value: number; - label: string; - } | null; purchase_item_id: number; received_date: string; travel_number: string; @@ -160,12 +152,6 @@ const PurchaseManagerApprovalObjectSchema: Yup.ObjectSchema = Yup.object({ - purchase_item: Yup.object({ - value: Yup.number().min(1).required(), - label: Yup.string().required(), - }) - .nullable() - .optional(), purchase_item_id: Yup.number() .min(1, 'Purchase item is required!') .required('Purchase item is required!') @@ -185,9 +171,8 @@ const PurchaseAcceptApprovalItemObjectSchema: Yup.ObjectSchema - Boolean(expeditionVendor?.value), + .when('expedition_vendor_id', { + is: (expeditionVendorId?: number | null) => Boolean(expeditionVendorId), then: (schema) => schema.required('Nomor kendaraan wajib diisi!'), otherwise: (schema) => schema.optional(), }) @@ -196,6 +181,7 @@ const PurchaseAcceptApprovalItemObjectSchema: Yup.ObjectSchema() .nullable() - .when('expedition_vendor', { - is: (expeditionVendor?: { value?: number; label?: string } | null) => - Boolean(expeditionVendor?.value), + .when('expedition_vendor_id', { + is: (expeditionVendorId?: number | null) => Boolean(expeditionVendorId), then: (schema) => schema.required('Biaya transport per item wajib diisi!'), otherwise: (schema) => schema.optional(), From 2a33fdbbbe24ca2d403d9662baeff4c060c082f2 Mon Sep 17 00:00:00 2001 From: MacBook Air M1 Date: Tue, 14 Apr 2026 15:05:08 +0700 Subject: [PATCH 3/8] adjust value query param get product warehouses --- .../pages/production/recording/form/RecordingForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 2a044874..5ffa1344 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -611,7 +611,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { } = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', 'search', { flags: 'PAKAN,OVK', limit: '100', - available_only: 'true', + available_only: 'false', location_id: stockProductsLocationId, ...(selectedKandangId ? { kandang_id: selectedKandangId.toString() } : {}), }); From 5e907d7e53a24f67567d393fc5a3dc708f1ecad3 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 15 Apr 2026 16:35:35 +0700 Subject: [PATCH 4/8] feat: create expense navigation helper function --- src/lib/expense-list-navigation.ts | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/lib/expense-list-navigation.ts diff --git a/src/lib/expense-list-navigation.ts b/src/lib/expense-list-navigation.ts new file mode 100644 index 00000000..a9f24539 --- /dev/null +++ b/src/lib/expense-list-navigation.ts @@ -0,0 +1,39 @@ +type SearchParamsLike = { + get: (name: string) => string | null; +}; + +const EXPENSE_LIST_PATH = '/expense'; + +export const getExpenseListReturnTo = (searchParams: SearchParamsLike) => { + const existingReturnTo = searchParams.get('returnTo'); + + if (existingReturnTo?.startsWith(EXPENSE_LIST_PATH)) { + return existingReturnTo; + } + + const params = new URLSearchParams(); + const page = searchParams.get('page'); + const limit = searchParams.get('limit'); + + if (page) params.set('page', page); + if (limit) params.set('limit', limit); + + const queryString = params.toString(); + + return queryString + ? `${EXPENSE_LIST_PATH}?${queryString}` + : EXPENSE_LIST_PATH; +}; + +export const buildExpenseActionHref = ( + path: string, + expenseId: number | string, + searchParams: SearchParamsLike +) => { + const params = new URLSearchParams({ + expenseId: String(expenseId), + returnTo: getExpenseListReturnTo(searchParams), + }); + + return `${path}?${params.toString()}`; +}; From 7a5ee2aca1f4c6c31811c29a9b04715bb3f8ef11 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 15 Apr 2026 16:38:56 +0700 Subject: [PATCH 5/8] feat: implement return to url query param --- .../pages/expense/ExpenseDetail.tsx | 6 +- .../expense/ExpenseRealizationContent.tsx | 12 +- .../pages/expense/ExpenseRequestContent.tsx | 28 +++-- .../pages/expense/ExpensesTable.tsx | 108 +++++++++++++++--- .../expense/form/ExpenseRealizationForm.tsx | 15 ++- 5 files changed, 140 insertions(+), 29 deletions(-) diff --git a/src/components/pages/expense/ExpenseDetail.tsx b/src/components/pages/expense/ExpenseDetail.tsx index 1f43eae1..c09b168a 100644 --- a/src/components/pages/expense/ExpenseDetail.tsx +++ b/src/components/pages/expense/ExpenseDetail.tsx @@ -1,6 +1,7 @@ 'use client'; import { useMemo, useState } from 'react'; +import { useSearchParams } from 'next/navigation'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; @@ -9,6 +10,7 @@ import ExpenseRequestContent from '@/components/pages/expense/ExpenseRequestCont import ExpenseRealizationContent from '@/components/pages/expense/ExpenseRealizationContent'; import { Expense } from '@/types/api/expense'; +import { getExpenseListReturnTo } from '@/lib/expense-list-navigation'; interface ExpenseDetailProps { initialValues?: Expense; @@ -16,6 +18,8 @@ interface ExpenseDetailProps { const ExpenseDetail: React.FC = ({ initialValues }) => { const [activeTab, setActiveTab] = useState('request'); + const searchParams = useSearchParams(); + const returnTo = getExpenseListReturnTo(searchParams); const expenseDetailTabs = useMemo(() => { const validTabs = [ @@ -46,7 +50,7 @@ const ExpenseDetail: React.FC = ({ initialValues }) => {