diff --git a/src/components/pages/finance/add/FormFinanceAdd.tsx b/src/components/pages/finance/add/FormFinanceAdd.tsx index 9b8259be..f7fdf446 100644 --- a/src/components/pages/finance/add/FormFinanceAdd.tsx +++ b/src/components/pages/finance/add/FormFinanceAdd.tsx @@ -39,6 +39,12 @@ interface FormFinanceAddProps { initialValues?: Finance; } +interface PartyCommonProps { + id: number; + name: string; + account_number: string; +} + const FormFinanceAdd = ({ type = 'add', initialValues, @@ -52,10 +58,12 @@ const FormFinanceAdd = ({ FINANCE_PARTY_TYPE_OPTIONS.find( (option) => option.value === initialValues?.party.type ) || null, - party_id_option: { - label: initialValues?.party.name || '', - value: initialValues?.party.id || 0, - }, + party_id_option: initialValues?.party + ? { + label: initialValues?.party.name || '', + value: initialValues?.party.id || 0, + } + : null, payment_date: initialValues?.payment_date || '', payment_method_option: FINANCE_PAYMENT_METHOD_OPTIONS.find( @@ -97,16 +105,19 @@ const FormFinanceAdd = ({ }); // ===== Options ===== - const { options: partyOptions, isLoadingOptions: isLoadingPartyOptions } = - useSelect( - formik.values.party_type_option?.value === 'CUSTOMER' - ? CustomerApi.basePath - : SupplierApi.basePath, - 'id', - 'name', - '', - { limit: 'limit' } - ); + const { + options: partyOptions, + isLoadingOptions: isLoadingPartyOptions, + rawData: partyRawData, + } = useSelect( + formik.values.party_type_option?.value === 'CUSTOMER' + ? CustomerApi.basePath + : SupplierApi.basePath, + 'id', + 'name', + '', + { limit: 'limit' } + ); const { options: bankOptions, rawData: bankRawData, @@ -204,6 +215,14 @@ const FormFinanceAdd = ({ value={formik.values.party_id_option} onChange={(value) => { formik.setFieldValue('party_id_option', value); + if (isResponseSuccess(partyRawData) && value) { + formik.setFieldValue( + 'party_account_number', + partyRawData.data?.find( + (item) => item.id === (value as OptionType)?.value + )?.account_number || '' + ); + } }} isLoading={isLoadingPartyOptions} isError={Boolean( @@ -312,6 +331,7 @@ const FormFinanceAdd = ({ : '' } required + readOnly /> - {/* - {JSON.stringify(exisitingValues)} - - - {JSON.stringify(formik.values)} - */} - {/* - {JSON.stringify(formik.errors)} - -
- {JSON.stringify(formik.values.marketing_product)} -
*/} - {formikErrorMessage && (
setFormErrorMessage('')} className='my-3 w-full'> {formikErrorMessage} diff --git a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx index ad50a927..75aa3ba6 100644 --- a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx +++ b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx @@ -11,7 +11,7 @@ import SelectInput, { useSelect, } from '@/components/input/SelectInput'; import { Kandang } from '@/types/api/master-data/kandang'; -import { KandangApi } from '@/services/api/master-data'; +import { KandangApi, WarehouseApi } from '@/services/api/master-data'; import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; import { ProductWarehouseApi } from '@/services/api/inventory'; import NumberInput from '@/components/input/NumberInput'; @@ -61,7 +61,7 @@ const SalesOrderProductForm = ({ const { options: kandangSourceOptions, isLoadingOptions: isLoadingKandangSourceOptions, - } = useSelect(KandangApi.basePath, 'id', 'name'); + } = useSelect(WarehouseApi.basePath, 'id', 'name'); const { options: warehouseSourceOptions, diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx index 47875902..af72f22f 100644 --- a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx @@ -79,14 +79,14 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { uomId: initialValues?.uom_id ?? 0, uom: initialValues?.uom ? { - value: initialValues?.uom.id, - label: initialValues?.uom.name, + value: initialValues?.uom?.id, + label: initialValues?.uom?.name, } : null, supplierIds: - initialValues?.suppliers.map((supplier) => supplier.id) ?? [], + initialValues?.suppliers?.map((supplier) => supplier.id) ?? [], suppliers: - initialValues?.suppliers.map((supplier) => ({ + initialValues?.suppliers?.map((supplier) => ({ value: supplier.id, label: supplier.name, })) ?? [], diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts index 6fc3799b..55e68039 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts @@ -68,7 +68,9 @@ export const createProductionStandardRepeaterFormSchema = ( export const createProductionStandardFormSchema = (category: string) => { return Yup.object({ name: Yup.string().required('Nama wajib diisi!'), - project_category: Yup.string().required('Kategori proyek wajib diisi!'), + project_category: Yup.string() + .min(1, 'Kategori proyek wajib diisi!') + .required('Kategori proyek wajib diisi!'), details: Yup.array().of( createProductionStandardRepeaterFormSchema(category) ), diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx index 99edb852..fe424838 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx @@ -29,6 +29,7 @@ import toast from 'react-hot-toast'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; import RequirePermission from '@/components/helper/RequirePermission'; +import Tooltip from '@/components/Tooltip'; type TableRowsType = { customRow: boolean; @@ -175,13 +176,15 @@ const ProductionStandardForm = ({ } = useFormStore(); // ===== Formik ===== + // Initial values - only recalculate when initialValue changes (for edit/detail mode) + // For add mode, we load from cache via useEffect instead to avoid race conditions const formikInitialValues = useMemo(() => { - // For add mode, merge cached data with initial values - if (formType === 'add' && formData) { + if (formType === 'add') { + // Don't use formData here - will be loaded via useEffect return { - name: formData.name || '', - project_category: formData.project_category || '', - details: formData.details || [], + name: '', + project_category: '', + details: [], } as ProductionStandardFormValues; } @@ -190,10 +193,11 @@ const ProductionStandardForm = ({ project_category: initialValue?.project_category || '', details: convertStandardValueToFormValues(initialValue?.details || []), } as ProductionStandardFormValues; - }, [initialValue, formData, formType]); + }, [initialValue, formType]); const formik = useFormik({ initialValues: formikInitialValues as ProductionStandardFormValues, - enableReinitialize: true, + // Only enable reinitialize for edit/detail mode, not add mode + enableReinitialize: formType !== 'add', onSubmit: (values) => { switch (formType) { case 'add': @@ -255,36 +259,38 @@ const ProductionStandardForm = ({ const { setValues: repeaterFormikSetValues } = repeaterFormik; // ===== Effect ===== - // Load initial values only when component mounts or when initialValue changes (for edit mode) - // This allows: - // 1. Add mode: Load cached data from formData store - // 2. Edit mode: Load existing data from initialValue - // We use initialValue?.id as dependency to avoid infinite loops + // Load cached data only once on mount for add mode + const [isInitialized, setIsInitialized] = useState(false); + useEffect(() => { - if (formType === 'add' && formData) { - // For add mode, load from cache + if (formType === 'add' && formData && !isInitialized) { + // For add mode, load from cache only on initial mount formikSetValues({ name: formData.name || '', project_category: formData.project_category || '', details: formData.details || [], } as ProductionStandardFormValues); - } else if (formType === 'detail' && initialValue) { - // For detail mode, load from initialValue and convert the details + setIsInitialized(true); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // Only run once on mount + + // For edit/detail mode, update when initialValue changes + useEffect(() => { + if (formType === 'detail' && initialValue) { formikSetValues({ name: initialValue.name || '', project_category: initialValue.project_category || '', details: convertStandardValueToFormValues(initialValue.details || []), } as ProductionStandardFormValues); } else if (formType === 'edit' && initialValue) { - // For edit mode, load from initialValue and convert the details formikSetValues({ name: initialValue.name || '', project_category: initialValue.project_category || '', details: convertStandardValueToFormValues(initialValue.details || []), } as ProductionStandardFormValues); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formData, initialValue?.id]); // Trigger when formData or initialValue.id changes + }, [initialValue?.id, formType]); // ===== Data Table ===== const tableRows = useMemo(() => { @@ -323,11 +329,6 @@ const ProductionStandardForm = ({ }, [formik.values.details]); const columns = useMemo[]>(() => { const baseColumns: ColumnDef[] = [ - { - header: 'No', - accessorFn: (row, index) => index + 1, - enableSorting: false, - }, { header: 'Minggu', accessorKey: 'week', @@ -407,6 +408,7 @@ const ProductionStandardForm = ({ variant='outline' color='warning' className='p-2' + type='button' onClick={() => handleEditClick(row.row.original.week)} > @@ -415,6 +417,7 @@ const ProductionStandardForm = ({ variant='outline' color='error' className='p-2' + type='button' onClick={() => handleRemoveRow(row.row.original.week)} > @@ -430,7 +433,7 @@ const ProductionStandardForm = ({ ...uniformityColumns, ...(formType !== 'detail' ? [actionColumn] : []), ]; - }, [formik.values.project_category, formType]); + }, [formik.values, formType]); // ===== Handler ===== const handleAddRow = async ( @@ -488,9 +491,11 @@ const ProductionStandardForm = ({ setIsAddingRow(false); }; - const handleRemoveRow = (week: number) => { - const newValues = (formik.values.details || []).filter( - (detail) => detail.week !== week + const handleRemoveRow = async (week: number) => { + // Access formik.values directly to get the latest values + const currentDetails = formik.values.details || []; + const newValues = currentDetails.filter( + (detail) => Number(detail.week) !== Number(week) ); const updatedFormValues = { @@ -745,6 +750,7 @@ const ProductionStandardForm = ({ } required isDisabled={formType === 'detail'} + isClearable />
@@ -1105,16 +1111,27 @@ const ProductionStandardForm = ({ Batal )} - + + {/* Should not be absolute */}