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;
|
label: string;
|
||||||
} | null;
|
} | null;
|
||||||
location_id: number;
|
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?: {
|
kandang?: {
|
||||||
value: number;
|
value: number;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -46,9 +51,14 @@ export const UniformityFormSchema: Yup.ObjectSchema<UniformityFormSchemaType> =
|
|||||||
location_id: Yup.number()
|
location_id: Yup.number()
|
||||||
.required('Location wajib diisi!')
|
.required('Location wajib diisi!')
|
||||||
.typeError('Location wajib diisi!'),
|
.typeError('Location wajib diisi!'),
|
||||||
project_flock_kandang_id: Yup.number()
|
project_flock: Yup.object({
|
||||||
.required('Project flock kandang wajib diisi!')
|
value: Yup.number().min(1).required(),
|
||||||
.typeError('Project flock kandang wajib diisi!'),
|
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({
|
kandang: Yup.object({
|
||||||
value: Yup.number().min(1).required(),
|
value: Yup.number().min(1).required(),
|
||||||
label: Yup.string().required(),
|
label: Yup.string().required(),
|
||||||
@@ -73,6 +83,13 @@ export const getUniformityFormInitialValues = (
|
|||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
location_id: initialValues?.location?.id ?? 0,
|
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,
|
project_flock_kandang_id: initialValues?.project_flock_kandang_id ?? 0,
|
||||||
kandang: initialValues?.kandang
|
kandang: initialValues?.kandang
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -21,14 +21,22 @@ import {
|
|||||||
UniformityFormValues,
|
UniformityFormValues,
|
||||||
getUniformityFormInitialValues,
|
getUniformityFormInitialValues,
|
||||||
} from '@/components/pages/uniformity/form/UniformityForm.schema';
|
} 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 { UniformityApi } from '@/services/api/uniformity';
|
||||||
import { isResponseError } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import {
|
import {
|
||||||
Uniformity,
|
Uniformity,
|
||||||
CreateUniformityPayload,
|
CreateUniformityPayload,
|
||||||
} from '@/types/api/uniformity/uniformity';
|
} 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 ExpandedDrawerForm from '@/components/pages/uniformity/form/ExpandedDrawerForm';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
interface UniformityFormProps {
|
interface UniformityFormProps {
|
||||||
formType?: 'add' | 'edit';
|
formType?: 'add' | 'edit';
|
||||||
@@ -50,17 +58,142 @@ const UniformityForm = ({
|
|||||||
useState('');
|
useState('');
|
||||||
|
|
||||||
// ===== SELECT INPUT DATA =====
|
// ===== 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 {
|
const {
|
||||||
setInputValue: setLocationSelectInputValue,
|
setInputValue: setLocationSelectInputValue,
|
||||||
options: locationOptions,
|
options: locationOptions,
|
||||||
isLoadingOptions: isLoadingLocations,
|
isLoadingOptions: isLoadingLocations,
|
||||||
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
||||||
|
|
||||||
const {
|
// ===== FETCH PROJECT FLOCKS DATA =====
|
||||||
setInputValue: setKandangSelectInputValue,
|
const projectFlocksUrl = useMemo(() => {
|
||||||
options: kandangOptions,
|
const params = new URLSearchParams({
|
||||||
isLoadingOptions: isLoadingKandangs,
|
search: projectFlockSearchValue || '',
|
||||||
} = useSelect(KandangApi.basePath, 'id', 'name', 'search');
|
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 =====
|
// ===== FORM CONFIGURATION =====
|
||||||
const formikInitialValues = useMemo<UniformityFormValues>(
|
const formikInitialValues = useMemo<UniformityFormValues>(
|
||||||
@@ -76,14 +209,22 @@ const UniformityForm = ({
|
|||||||
validateOnMount: false,
|
validateOnMount: false,
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
onSubmit: async (values) => {
|
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();
|
const formData = new FormData();
|
||||||
formData.append('date', values.date);
|
formData.append('date', values.date);
|
||||||
formData.append('location_id', values.location_id.toString());
|
formData.append('location_id', values.location_id.toString());
|
||||||
formData.append(
|
formData.append(
|
||||||
'project_flock_kandang_id',
|
'project_flock_kandang_id',
|
||||||
values.project_flock_kandang_id.toString()
|
projectFlockKandangId.toString()
|
||||||
);
|
);
|
||||||
formData.append('kandang_id', values.kandang_id.toString());
|
|
||||||
|
|
||||||
if (values.files) {
|
if (values.files) {
|
||||||
formData.append('files[]', values.files);
|
formData.append('files[]', values.files);
|
||||||
@@ -111,6 +252,35 @@ const UniformityForm = ({
|
|||||||
formik.setFieldValue('location', location);
|
formik.setFieldValue('location', location);
|
||||||
formik.setFieldTouched('location_id', true);
|
formik.setFieldTouched('location_id', true);
|
||||||
formik.setFieldValue('location_id', (location as OptionType)?.value || 0);
|
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]
|
[formik]
|
||||||
);
|
);
|
||||||
@@ -122,6 +292,8 @@ const UniformityForm = ({
|
|||||||
formik.setFieldValue('kandang', kandang);
|
formik.setFieldValue('kandang', kandang);
|
||||||
formik.setFieldTouched('kandang_id', true);
|
formik.setFieldTouched('kandang_id', true);
|
||||||
formik.setFieldValue('kandang_id', (kandang as OptionType)?.value || 0);
|
formik.setFieldValue('kandang_id', (kandang as OptionType)?.value || 0);
|
||||||
|
|
||||||
|
setSelectedKandang(kandang);
|
||||||
},
|
},
|
||||||
[formik]
|
[formik]
|
||||||
);
|
);
|
||||||
@@ -225,7 +397,7 @@ const UniformityForm = ({
|
|||||||
|
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
label='Lokasi Farm'
|
label='Lokasi'
|
||||||
placeholder='Pilih Lokasi...'
|
placeholder='Pilih Lokasi...'
|
||||||
value={formik.values.location}
|
value={formik.values.location}
|
||||||
onChange={handleLocationChange}
|
onChange={handleLocationChange}
|
||||||
@@ -242,33 +414,19 @@ const UniformityForm = ({
|
|||||||
|
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
label='Project Flock Kandang'
|
label='Project Flock'
|
||||||
placeholder='Pilih Project Flock Kandang...'
|
placeholder='Pilih Project Flock...'
|
||||||
value={
|
value={formik.values.project_flock}
|
||||||
formik.values.project_flock_kandang_id
|
onChange={handleProjectFlockChange}
|
||||||
? {
|
options={projectFlockOptions}
|
||||||
value: formik.values.project_flock_kandang_id,
|
onInputChange={setProjectFlockSearchValue}
|
||||||
label: formik.values.project_flock_kandang_id.toString(),
|
isLoading={isLoadingProjectFlocks}
|
||||||
}
|
isDisabled={!formik.values.location_id}
|
||||||
: 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' },
|
|
||||||
]}
|
|
||||||
isError={
|
isError={
|
||||||
formik.touched.project_flock_kandang_id &&
|
formik.touched.project_flock_id &&
|
||||||
Boolean(formik.errors.project_flock_kandang_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
|
isClearable
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
@@ -280,8 +438,7 @@ const UniformityForm = ({
|
|||||||
value={formik.values.kandang}
|
value={formik.values.kandang}
|
||||||
onChange={handleKandangChange}
|
onChange={handleKandangChange}
|
||||||
options={kandangOptions}
|
options={kandangOptions}
|
||||||
onInputChange={setKandangSelectInputValue}
|
isDisabled={!formik.values.project_flock_id}
|
||||||
isLoading={isLoadingKandangs}
|
|
||||||
isError={
|
isError={
|
||||||
formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
|
formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user