mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-438): Add Project Flock selection and lookup
This commit is contained in:
@@ -8,7 +8,12 @@ type UniformityFormSchemaType = {
|
||||
label: string;
|
||||
} | null;
|
||||
location_id: number;
|
||||
project_flock_kandang_id: number;
|
||||
project_flock?: {
|
||||
value: number;
|
||||
label: string;
|
||||
} | null;
|
||||
project_flock_id: number;
|
||||
project_flock_kandang_id: number | null;
|
||||
kandang?: {
|
||||
value: number;
|
||||
label: string;
|
||||
@@ -46,9 +51,14 @@ export const UniformityFormSchema: Yup.ObjectSchema<UniformityFormSchemaType> =
|
||||
location_id: Yup.number()
|
||||
.required('Location wajib diisi!')
|
||||
.typeError('Location wajib diisi!'),
|
||||
project_flock_kandang_id: Yup.number()
|
||||
.required('Project flock kandang wajib diisi!')
|
||||
.typeError('Project flock kandang wajib diisi!'),
|
||||
project_flock: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
}).nullable(),
|
||||
project_flock_id: Yup.number()
|
||||
.required('Project flock wajib diisi!')
|
||||
.typeError('Project flock wajib diisi!'),
|
||||
project_flock_kandang_id: Yup.number().optional().nullable().default(null),
|
||||
kandang: Yup.object({
|
||||
value: Yup.number().min(1).required(),
|
||||
label: Yup.string().required(),
|
||||
@@ -73,6 +83,13 @@ export const getUniformityFormInitialValues = (
|
||||
}
|
||||
: null,
|
||||
location_id: initialValues?.location?.id ?? 0,
|
||||
project_flock: initialValues?.project_flock
|
||||
? {
|
||||
value: initialValues.project_flock.id,
|
||||
label: initialValues.project_flock.flock_name,
|
||||
}
|
||||
: null,
|
||||
project_flock_id: initialValues?.project_flock?.id ?? 0,
|
||||
project_flock_kandang_id: initialValues?.project_flock_kandang_id ?? 0,
|
||||
kandang: initialValues?.kandang
|
||||
? {
|
||||
|
||||
@@ -21,14 +21,22 @@ import {
|
||||
UniformityFormValues,
|
||||
getUniformityFormInitialValues,
|
||||
} from '@/components/pages/uniformity/form/UniformityForm.schema';
|
||||
import { LocationApi, KandangApi } from '@/services/api/master-data';
|
||||
import { LocationApi } from '@/services/api/master-data';
|
||||
import {
|
||||
ProjectFlockApi,
|
||||
ProjectFlockKandangApi,
|
||||
} from '@/services/api/production';
|
||||
import { UniformityApi } from '@/services/api/uniformity';
|
||||
import { isResponseError } from '@/lib/api-helper';
|
||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||
import {
|
||||
Uniformity,
|
||||
CreateUniformityPayload,
|
||||
} from '@/types/api/uniformity/uniformity';
|
||||
import { type BaseApiResponse } from '@/types/api/api-general';
|
||||
import { ProjectFlockKandangLookup } from '@/types/api/production/project-flock';
|
||||
import { Kandang } from '@/types/api/master-data/kandang';
|
||||
import ExpandedDrawerForm from '@/components/pages/uniformity/form/ExpandedDrawerForm';
|
||||
import useSWR from 'swr';
|
||||
|
||||
interface UniformityFormProps {
|
||||
formType?: 'add' | 'edit';
|
||||
@@ -50,17 +58,142 @@ const UniformityForm = ({
|
||||
useState('');
|
||||
|
||||
// ===== SELECT INPUT DATA =====
|
||||
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const [projectFlockSearchValue, setProjectFlockSearchValue] = useState('');
|
||||
const [selectedProjectFlock, setSelectedProjectFlock] =
|
||||
useState<OptionType | null>(null);
|
||||
|
||||
const [selectedKandang, setSelectedKandang] = useState<OptionType | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const {
|
||||
setInputValue: setLocationSelectInputValue,
|
||||
options: locationOptions,
|
||||
isLoadingOptions: isLoadingLocations,
|
||||
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
setInputValue: setKandangSelectInputValue,
|
||||
options: kandangOptions,
|
||||
isLoadingOptions: isLoadingKandangs,
|
||||
} = useSelect(KandangApi.basePath, 'id', 'name', 'search');
|
||||
// ===== FETCH PROJECT FLOCKS DATA =====
|
||||
const projectFlocksUrl = useMemo(() => {
|
||||
const params = new URLSearchParams({
|
||||
search: projectFlockSearchValue || '',
|
||||
limit: '100',
|
||||
});
|
||||
if (selectedLocation) {
|
||||
params.append('location_id', selectedLocation.value.toString());
|
||||
}
|
||||
return `${ProjectFlockApi.basePath}?${params.toString()}`;
|
||||
}, [projectFlockSearchValue, selectedLocation]);
|
||||
|
||||
const { data: projectFlocksData, isLoading: isLoadingProjectFlocks } = useSWR(
|
||||
projectFlocksUrl,
|
||||
ProjectFlockApi.getAllFetcher
|
||||
);
|
||||
|
||||
const projectFlocksDataList =
|
||||
projectFlocksData?.status === 'success'
|
||||
? projectFlocksData.data
|
||||
: undefined;
|
||||
|
||||
// ===== PROJECT FLOCK OPTIONS =====
|
||||
const projectFlockOptions = useMemo(() => {
|
||||
let options: OptionType[] = [];
|
||||
|
||||
if (isResponseSuccess(projectFlocksData)) {
|
||||
const flockOptions =
|
||||
projectFlocksData?.data.map((projectFlock) => ({
|
||||
value: projectFlock.id,
|
||||
label: projectFlock.flock_name || '',
|
||||
})) || [];
|
||||
options = options.concat(flockOptions);
|
||||
}
|
||||
|
||||
return options;
|
||||
}, [projectFlocksData]);
|
||||
|
||||
// ===== APPROVED PROJECT FLOCK KANDANGS =====
|
||||
const approvedProjectFlockKandangsUrl = useMemo(() => {
|
||||
const params = new URLSearchParams({
|
||||
step_name: 'Disetujui',
|
||||
limit: '100',
|
||||
});
|
||||
return `${ProjectFlockKandangApi.basePath}?${params.toString()}`;
|
||||
}, []);
|
||||
|
||||
const { data: approvedProjectFlockKandangsData } = useSWR(
|
||||
approvedProjectFlockKandangsUrl,
|
||||
ProjectFlockKandangApi.getAllFetcher
|
||||
);
|
||||
|
||||
const approvedProjectFlockKandangs = useMemo(() => {
|
||||
if (!isResponseSuccess(approvedProjectFlockKandangsData)) return [];
|
||||
return approvedProjectFlockKandangsData.data;
|
||||
}, [approvedProjectFlockKandangsData]);
|
||||
|
||||
// ===== KANDANG OPTIONS (FILTERED BY SELECTED PROJECT FLOCK) =====
|
||||
const kandangOptions = useMemo(() => {
|
||||
let options: OptionType[] = [];
|
||||
|
||||
if (selectedProjectFlock && projectFlocksDataList) {
|
||||
const selectedProjectFlockData = projectFlocksDataList.find(
|
||||
(pf) => pf.id === selectedProjectFlock.value
|
||||
);
|
||||
|
||||
if (selectedProjectFlockData?.kandangs) {
|
||||
const approvedKandangIds = approvedProjectFlockKandangs
|
||||
.filter((pfk) => pfk.project_flock_id === selectedProjectFlock.value)
|
||||
.map((pfk) => pfk.kandang_id);
|
||||
|
||||
const kandangOpts = selectedProjectFlockData.kandangs
|
||||
.filter((kandang: Kandang) => {
|
||||
if (formType === 'add') {
|
||||
return approvedKandangIds.includes(kandang.id);
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((kandang: Kandang) => ({
|
||||
value: kandang.id,
|
||||
label: kandang.name || '',
|
||||
}));
|
||||
options = options.concat(kandangOpts);
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}, [
|
||||
selectedProjectFlock,
|
||||
projectFlocksDataList,
|
||||
approvedProjectFlockKandangs,
|
||||
formType,
|
||||
]);
|
||||
|
||||
// ===== PROJECT FLOCK KANDANG LOOKUP =====
|
||||
const projectFlockKandangLookupUrl = useMemo(() => {
|
||||
if (!selectedProjectFlock || !selectedKandang) return null;
|
||||
const params = new URLSearchParams({
|
||||
project_flock_id: selectedProjectFlock.value.toString(),
|
||||
kandang_id: selectedKandang.value.toString(),
|
||||
});
|
||||
return `${ProjectFlockApi.basePath}/kandangs/lookup?${params.toString()}`;
|
||||
}, [selectedProjectFlock, selectedKandang]);
|
||||
|
||||
const { data: projectFlockKandangLookupData } = useSWR(
|
||||
projectFlockKandangLookupUrl,
|
||||
projectFlockKandangLookupUrl
|
||||
? () =>
|
||||
ProjectFlockApi.getAllFetcher(
|
||||
projectFlockKandangLookupUrl
|
||||
) as Promise<BaseApiResponse<ProjectFlockKandangLookup>>
|
||||
: null
|
||||
);
|
||||
|
||||
const projectFlockKandangLookup =
|
||||
projectFlockKandangLookupData?.status === 'success'
|
||||
? projectFlockKandangLookupData.data
|
||||
: undefined;
|
||||
|
||||
// ===== FORM CONFIGURATION =====
|
||||
const formikInitialValues = useMemo<UniformityFormValues>(
|
||||
@@ -76,14 +209,22 @@ const UniformityForm = ({
|
||||
validateOnMount: false,
|
||||
enableReinitialize: true,
|
||||
onSubmit: async (values) => {
|
||||
const projectFlockKandangId = projectFlockKandangLookup?.id;
|
||||
|
||||
if (!projectFlockKandangId) {
|
||||
setUniformityFormErrorMessage(
|
||||
'Project Flock Kandang tidak ditemukan. Silakan pilih Project Flock dan Kandang yang valid.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('date', values.date);
|
||||
formData.append('location_id', values.location_id.toString());
|
||||
formData.append(
|
||||
'project_flock_kandang_id',
|
||||
values.project_flock_kandang_id.toString()
|
||||
projectFlockKandangId.toString()
|
||||
);
|
||||
formData.append('kandang_id', values.kandang_id.toString());
|
||||
|
||||
if (values.files) {
|
||||
formData.append('files[]', values.files);
|
||||
@@ -111,6 +252,35 @@ const UniformityForm = ({
|
||||
formik.setFieldValue('location', location);
|
||||
formik.setFieldTouched('location_id', true);
|
||||
formik.setFieldValue('location_id', (location as OptionType)?.value || 0);
|
||||
|
||||
setSelectedLocation(location);
|
||||
setSelectedProjectFlock(null);
|
||||
setSelectedKandang(null);
|
||||
|
||||
formik.setFieldValue('project_flock', null);
|
||||
formik.setFieldValue('project_flock_id', 0);
|
||||
formik.setFieldValue('kandang', null);
|
||||
formik.setFieldValue('kandang_id', 0);
|
||||
},
|
||||
[formik]
|
||||
);
|
||||
|
||||
const handleProjectFlockChange = useCallback(
|
||||
(val: OptionType | OptionType[] | null) => {
|
||||
const projectFlock = val as OptionType | null;
|
||||
formik.setFieldTouched('project_flock', true);
|
||||
formik.setFieldValue('project_flock', projectFlock);
|
||||
formik.setFieldTouched('project_flock_id', true);
|
||||
formik.setFieldValue(
|
||||
'project_flock_id',
|
||||
(projectFlock as OptionType)?.value || 0
|
||||
);
|
||||
|
||||
setSelectedProjectFlock(projectFlock);
|
||||
setSelectedKandang(null);
|
||||
|
||||
formik.setFieldValue('kandang', null);
|
||||
formik.setFieldValue('kandang_id', 0);
|
||||
},
|
||||
[formik]
|
||||
);
|
||||
@@ -122,6 +292,8 @@ const UniformityForm = ({
|
||||
formik.setFieldValue('kandang', kandang);
|
||||
formik.setFieldTouched('kandang_id', true);
|
||||
formik.setFieldValue('kandang_id', (kandang as OptionType)?.value || 0);
|
||||
|
||||
setSelectedKandang(kandang);
|
||||
},
|
||||
[formik]
|
||||
);
|
||||
@@ -225,7 +397,7 @@ const UniformityForm = ({
|
||||
|
||||
<SelectInput
|
||||
required
|
||||
label='Lokasi Farm'
|
||||
label='Lokasi'
|
||||
placeholder='Pilih Lokasi...'
|
||||
value={formik.values.location}
|
||||
onChange={handleLocationChange}
|
||||
@@ -242,33 +414,19 @@ const UniformityForm = ({
|
||||
|
||||
<SelectInput
|
||||
required
|
||||
label='Project Flock Kandang'
|
||||
placeholder='Pilih Project Flock Kandang...'
|
||||
value={
|
||||
formik.values.project_flock_kandang_id
|
||||
? {
|
||||
value: formik.values.project_flock_kandang_id,
|
||||
label: formik.values.project_flock_kandang_id.toString(),
|
||||
}
|
||||
: null
|
||||
}
|
||||
onChange={(val) => {
|
||||
const option = val as OptionType | null;
|
||||
formik.setFieldValue(
|
||||
'project_flock_kandang_id',
|
||||
option?.value || 0
|
||||
);
|
||||
}}
|
||||
options={[
|
||||
{ value: 1, label: '1' },
|
||||
{ value: 2, label: '2' },
|
||||
{ value: 3, label: '3' },
|
||||
]}
|
||||
label='Project Flock'
|
||||
placeholder='Pilih Project Flock...'
|
||||
value={formik.values.project_flock}
|
||||
onChange={handleProjectFlockChange}
|
||||
options={projectFlockOptions}
|
||||
onInputChange={setProjectFlockSearchValue}
|
||||
isLoading={isLoadingProjectFlocks}
|
||||
isDisabled={!formik.values.location_id}
|
||||
isError={
|
||||
formik.touched.project_flock_kandang_id &&
|
||||
Boolean(formik.errors.project_flock_kandang_id)
|
||||
formik.touched.project_flock_id &&
|
||||
Boolean(formik.errors.project_flock_id)
|
||||
}
|
||||
errorMessage={formik.errors.project_flock_kandang_id as string}
|
||||
errorMessage={formik.errors.project_flock_id as string}
|
||||
isClearable
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
@@ -280,8 +438,7 @@ const UniformityForm = ({
|
||||
value={formik.values.kandang}
|
||||
onChange={handleKandangChange}
|
||||
options={kandangOptions}
|
||||
onInputChange={setKandangSelectInputValue}
|
||||
isLoading={isLoadingKandangs}
|
||||
isDisabled={!formik.values.project_flock_id}
|
||||
isError={
|
||||
formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user