'use client'; import Button from '@/components/Button'; import Card from '@/components/Card'; import { FormHeader } from '@/components/helper/form/FormHeader'; import DateInput from '@/components/input/DateInput'; import NumberInput from '@/components/input/NumberInput'; import SelectInput, { OptionType, useSelect, } from '@/components/input/SelectInput'; import TextArea from '@/components/input/TextArea'; import TextInput from '@/components/input/TextInput'; import { FinanceFormSchema, FinanceFormValues, } from '@/components/pages/finance/add/FormFinanceAdd.schema'; import { FINANCE_PARTY_TYPE_OPTIONS, FINANCE_PAYMENT_METHOD_OPTIONS, } from '@/config/constant'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { formatDate, formatTitleCase } from '@/lib/helper'; import { FinanceApi } from '@/services/api/finance'; import { BankApi, CustomerApi, SupplierApi } from '@/services/api/master-data'; import { CreateFinancePayment, Finance, UpdateFinancePayment, } from '@/types/api/finance/finance'; import { Bank } from '@/types/api/master-data/bank'; import { useFormik } from 'formik'; import { useRouter } from 'next/navigation'; import { useCallback, useMemo } from 'react'; import toast from 'react-hot-toast'; interface FormFinanceAddProps { type?: 'add' | 'edit'; initialValues?: Finance; } const FormFinanceAdd = ({ type = 'add', initialValues, }: FormFinanceAddProps) => { const router = useRouter(); // ===== Formik ===== const formikInitialValues = useMemo((): FinanceFormValues => { return { party_type_option: FINANCE_PARTY_TYPE_OPTIONS.find( (option) => option.value === initialValues?.party.type ) || null, party_id_option: { label: initialValues?.party.name || '', value: initialValues?.party.id || 0, }, payment_date: initialValues?.payment_date || '', payment_method_option: FINANCE_PAYMENT_METHOD_OPTIONS.find( (option) => option.value === initialValues?.payment_method ) || null, bank_id_option: initialValues?.bank ? { label: initialValues.bank.name, value: initialValues.bank.id, } : null, party_account_number: initialValues?.party.account_number || '', reference_number: initialValues?.reference_number || '', nominal: initialValues?.nominal.toString() || '', notes: initialValues?.notes || '', }; }, [initialValues]); const formik = useFormik({ initialValues: formikInitialValues, validationSchema: FinanceFormSchema, validateOnChange: true, validateOnBlur: true, onSubmit: async (values) => { const payload = transformFormValuesToPayload(values); switch (type) { case 'add': await createFinance(payload); break; case 'edit': if (initialValues?.id) { await updateFinance(initialValues.id, payload); } break; } }, }); // ===== Options ===== const { options: partyOptions, isLoadingOptions: isLoadingPartyOptions } = useSelect( formik.values.party_type_option?.value === 'CUSTOMER' ? CustomerApi.basePath : SupplierApi.basePath, 'id', 'name', '', { limit: 'limit' } ); const { options: bankOptions, rawData: bankRawData, isLoadingOptions: isLoadingBankOptions, } = useSelect(BankApi.basePath, 'id', 'name', '', { limit: 'limit' }); // ===== Helper Functions ===== const transformFormValuesToPayload = ( values: FinanceFormValues ): CreateFinancePayment => { return { party_id: Number(values.party_id_option?.value) || 0, party_type: (values.party_type_option?.value as string) || '', payment_date: formatDate(values.payment_date, 'YYYY-MM-DD'), payment_method: (values.payment_method_option?.value as string) || '', bank_id: Number(values.bank_id_option?.value) || 0, reference_number: values.reference_number, nominal: Number(values.nominal.replace(/\D/g, '')) || 0, notes: values.notes, }; }; // ===== Handler ===== const createFinance = useCallback( async (payload: CreateFinancePayment) => { const response = await FinanceApi.create(payload); if (isResponseError(response)) { toast.error(response.message); return; } toast.success('Data berhasil ditambahkan'); router.refresh(); router.push('/finance'); }, [router] ); const updateFinance = useCallback( async (financeId: number, payload: UpdateFinancePayment) => { const response = await FinanceApi.update(financeId, payload); if (isResponseError(response)) { toast.error(response.message); return; } toast.success('Data berhasil diperbarui'); router.refresh(); router.push('/finance'); }, [router] ); return ( <>
{ formik.setFieldValue('party_type_option', value); }} isError={Boolean( formik.touched.party_type_option && formik.errors.party_type_option )} errorMessage={ formik.touched.party_type_option && formik.errors.party_type_option ? formik.errors.party_type_option : '' } required isClearable /> { formik.setFieldValue('party_id_option', value); }} isLoading={isLoadingPartyOptions} isError={Boolean( formik.touched.party_id_option && formik.errors.party_id_option )} errorMessage={ formik.touched.party_id_option && formik.errors.party_id_option ? formik.errors.party_id_option : '' } required isClearable isDisabled={!formik.values.party_type_option?.value} /> { formik.setFieldValue('payment_method_option', value); }} isError={Boolean( formik.touched.payment_method_option && formik.errors.payment_method_option )} errorMessage={ formik.touched.payment_method_option && formik.errors.payment_method_option ? formik.errors.payment_method_option : '' } required isClearable /> ({ label: bankRawData.data?.find( (item) => item.id === option.value )?.alias + ' - ' + bankRawData.data?.find( (item) => item.id === option.value )?.account_number + ' - ' + bankRawData.data?.find( (item) => item.id === option.value )?.owner, value: option.value, })) : [] } value={formik.values.bank_id_option} onChange={(value) => { formik.setFieldValue('bank_id_option', value); }} isLoading={isLoadingBankOptions} isError={Boolean( formik.touched.bank_id_option && formik.errors.bank_id_option )} errorMessage={ formik.touched.bank_id_option && formik.errors.bank_id_option ? formik.errors.bank_id_option : '' } required isClearable />