From 2a71734583d436e85063558065af45d9beef0089 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 6 Nov 2025 15:26:54 +0700 Subject: [PATCH] feat(FE-188,193): add Vendor, Request Documents, and Kandang Detail Expense input --- .../pages/expense/form/ExpenseRequestForm.tsx | 174 ++++++++++++++---- 1 file changed, 140 insertions(+), 34 deletions(-) diff --git a/src/components/pages/expense/form/ExpenseRequestForm.tsx b/src/components/pages/expense/form/ExpenseRequestForm.tsx index e3a435b5..4268ca92 100644 --- a/src/components/pages/expense/form/ExpenseRequestForm.tsx +++ b/src/components/pages/expense/form/ExpenseRequestForm.tsx @@ -1,22 +1,27 @@ 'use client'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useFormik } from 'formik'; import { toast } from 'react-hot-toast'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; -import TextInput from '@/components/input/TextInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; -import SelectInput from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import DateInput from '@/components/input/DateInput'; import ExpenseKandangsTable from '@/components/pages/expense/form/ExpenseKandangsTable'; +import DropFileInput from '@/components/input/DropFileInput'; +import ExpenseRequestKandangDetailExpense from '@/components/pages/expense/form/ExpenseRequestKandangDetailExpense'; import { ExpenseRequestFormSchema, ExpenseRequestFormValues, + getExpenseFormInitialValues, UpdateExpenseRequestFormSchema, } from '@/components/pages/expense/form/ExpenseRequestForm.schema'; import { isResponseError } from '@/lib/api-helper'; @@ -27,6 +32,9 @@ import { } from '@/types/api/expense'; import { ExpenseApi } from '@/services/api/expense'; import { cn, sleep } from '@/lib/helper'; +import { LocationApi, SupplierApi } from '@/services/api/master-data'; +import { ACCEPTED_FILE_TYPE } from '@/config/constant'; +import { Supplier } from '@/types/api/master-data/supplier'; interface ExpenseFormProps { type?: 'add' | 'edit' | 'detail'; @@ -49,7 +57,9 @@ const ExpenseRequestForm = ({ const createExpenseHandler = useCallback( async (payload: CreateExpensePayload) => { - const createExpenseRes = await ExpenseApi.create(payload); + const createExpenseRes = await ExpenseApi.create( + ExpenseApi.convertPayloadToFormData(payload) + ); if (isResponseError(createExpenseRes)) { setExpenseFormErrorMessage(createExpenseRes.message); @@ -64,7 +74,10 @@ const ExpenseRequestForm = ({ const updateExpenseHandler = useCallback( async (expenseId: number, payload: UpdateExpensePayload) => { - const updateExpenseRes = await ExpenseApi.update(expenseId, payload); + const updateExpenseRes = await ExpenseApi.update( + expenseId, + ExpenseApi.convertPayloadToFormData(payload) + ); if (updateExpenseRes?.status === 'error') { setExpenseFormErrorMessage(updateExpenseRes.message); @@ -78,14 +91,8 @@ const ExpenseRequestForm = ({ [router] ); - const formikInitialValues = useMemo(() => { - return { - name: initialValues?.name ?? '', - }; - }, [initialValues]); - const formik = useFormik({ - initialValues: formikInitialValues, + initialValues: getExpenseFormInitialValues(initialValues), validationSchema: type === 'edit' ? UpdateExpenseRequestFormSchema @@ -94,7 +101,22 @@ const ExpenseRequestForm = ({ setExpenseFormErrorMessage(''); const expensePayload: CreateExpensePayload = { - name: values.name, + locationId: values.location?.value as number, + kandangIds: values.kandangs + ? values.kandangs.map((item) => item.id) + : [], + transaction_date: values.transaction_date as string, + vendorId: values.vendor?.value as number, + request_documents: values.request_documents as File[], + kandang_expenses: values.kandangExpenses.map((kandangExpense) => ({ + kandangId: kandangExpense.kandangId, + expenses: kandangExpense.expenses.map((expenseItem) => ({ + nonstockId: expenseItem.nonstock?.value as number, + total_quantity: expenseItem.totalQuantity as number, + total_expense: expenseItem.totalExpense as number, + notes: expenseItem.notes, + })), + })), }; switch (type) { @@ -114,6 +136,58 @@ const ExpenseRequestForm = ({ const { setValues: formikSetValues } = formik; + const { + setInputValue: setLocationInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + } = useSelect(LocationApi.basePath, 'id', 'name'); + + const { + setInputValue: setVendorInputValue, + options: vendorOptions, + isLoadingOptions: isLoadingVendorOptions, + } = useSelect(SupplierApi.basePath, 'id', 'name'); + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('location', true); + formik.setFieldValue('location', val); + }; + + const kandangsChangeHandler = (kandangs: { id: number; name: string }[]) => { + formik.setFieldTouched('kandangs', true); + formik.setFieldValue('kandangs', kandangs); + + kandangs.forEach((kandangItem) => { + const isKandangExistInKandangExpense = formik.values.kandangExpenses.find( + (kandangExpenseItem) => kandangExpenseItem.kandangId === kandangItem.id + ); + + if (isKandangExistInKandangExpense) return; + + formik.values.kandangExpenses.push({ + kandangId: kandangItem.id, + expenses: [ + { + nonstock: undefined, + totalExpense: undefined, + totalQuantity: undefined, + notes: '', + }, + ], + }); + }); + }; + + const vendorChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('vendor', true); + formik.setFieldValue('vendor', val); + }; + + const requestDocumentsChangeHandler = (val: File[]) => { + formik.setFieldTouched('request_documents', true); + formik.setFieldValue('request_documents', val); + }; + const deleteExpenseClickHandler = () => { deleteModal.openModal(); }; @@ -141,8 +215,12 @@ const ExpenseRequestForm = ({ }; useEffect(() => { - formikSetValues(formikInitialValues); - }, [formikSetValues, formikInitialValues]); + formikSetValues(getExpenseFormInitialValues(initialValues)); + }, [formikSetValues, getExpenseFormInitialValues, initialValues]); + + useEffect(() => { + formik.setFieldValue('kandangs', undefined); + }, [formik.values.location]); return ( <> @@ -172,30 +250,22 @@ const ExpenseRequestForm = ({
- {/* */} - + + + + + +
@@ -287,7 +393,7 @@ const ExpenseRequestForm = ({