mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-23 23:05:46 +00:00
feat(FE-114): integrate location and project flock selection in RecordingForm
This commit is contained in:
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
import { useMemo, useState, useEffect } from 'react';
|
import { useMemo, useState, useEffect } from 'react';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
|
import useSWR from 'swr';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
|
||||||
import TextInput from '@/components/input/TextInput';
|
import TextInput from '@/components/input/TextInput';
|
||||||
|
import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
@@ -21,6 +23,9 @@ import {
|
|||||||
UpdateRecordingFormSchema,
|
UpdateRecordingFormSchema,
|
||||||
} from './RecordingForm.schema';
|
} from './RecordingForm.schema';
|
||||||
import { useRecordingFormHandlers } from './useRecordingFormHandlers';
|
import { useRecordingFormHandlers } from './useRecordingFormHandlers';
|
||||||
|
import { ProjectFlockApi } from '@/services/api/production';
|
||||||
|
import { LocationApi } from '@/services/api/master-data';
|
||||||
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
|
|
||||||
@@ -34,6 +39,62 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const [selectedStocks, setSelectedStocks] = useState<number[]>([]);
|
const [selectedStocks, setSelectedStocks] = useState<number[]>([]);
|
||||||
const [selectedDepletions, setSelectedDepletions] = useState<number[]>([]);
|
const [selectedDepletions, setSelectedDepletions] = useState<number[]>([]);
|
||||||
|
|
||||||
|
// State for Location search and selection
|
||||||
|
const [locationSearchValue, setLocationSearchValue] = useState('');
|
||||||
|
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(null);
|
||||||
|
|
||||||
|
// State for Project Flock search
|
||||||
|
const [projectFlockSearchValue, setProjectFlockSearchValue] = useState('');
|
||||||
|
|
||||||
|
// Fetch Locations data
|
||||||
|
const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({
|
||||||
|
search: locationSearchValue || '',
|
||||||
|
}).toString()}`;
|
||||||
|
|
||||||
|
const { data: locations, isLoading: isLoadingLocations } = useSWR(
|
||||||
|
locationsUrl,
|
||||||
|
LocationApi.getAllFetcher
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fetch Project Flocks data with location filter
|
||||||
|
const projectFlocksUrl = `${ProjectFlockApi.basePath}?${new URLSearchParams({
|
||||||
|
search: projectFlockSearchValue || '',
|
||||||
|
...(selectedLocation ? { location_id: selectedLocation.value.toString() } : {}),
|
||||||
|
}).toString()}`;
|
||||||
|
|
||||||
|
const { data: projectFlocks, isLoading: isLoadingProjectFlocks } = useSWR(
|
||||||
|
projectFlocksUrl,
|
||||||
|
ProjectFlockApi.getAllFetcher
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract location options from locations data
|
||||||
|
const locationOptions = useMemo(() => {
|
||||||
|
if (!isResponseSuccess(locations)) return [];
|
||||||
|
|
||||||
|
return locations?.data.map((location) => ({
|
||||||
|
value: location.id,
|
||||||
|
label: location.name,
|
||||||
|
})) || [];
|
||||||
|
}, [locations]);
|
||||||
|
|
||||||
|
// Extract kandang options from project_flocks data
|
||||||
|
const projectFlockKandangOptions = useMemo(() => {
|
||||||
|
if (!isResponseSuccess(projectFlocks)) return [];
|
||||||
|
|
||||||
|
const options: OptionType[] = [];
|
||||||
|
|
||||||
|
projectFlocks?.data.forEach((projectFlock) => {
|
||||||
|
projectFlock.kandangs.forEach((kandang) => {
|
||||||
|
options.push({
|
||||||
|
value: kandang.id,
|
||||||
|
label: `${projectFlock.flock.name} - ${projectFlock.area.name} - ${kandang.name}`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}, [projectFlocks]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
deleteModal,
|
deleteModal,
|
||||||
recordingFormErrorMessage,
|
recordingFormErrorMessage,
|
||||||
@@ -114,9 +175,19 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// EVENT HANDLERS - Select Inputs
|
// EVENT HANDLERS - Select Inputs
|
||||||
const projectFlockChangeHandler = (value: string) => {
|
const locationChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||||
const projectFlockId = parseInt(value) || 0;
|
setSelectedLocation(val as OptionType);
|
||||||
formik.setFieldValue('project_flock_kandang_id', projectFlockId, false);
|
|
||||||
|
// Reset project flock selection when location changes
|
||||||
|
formik.setFieldValue('project_flock_kandang', null);
|
||||||
|
formik.setFieldValue('project_flock_kandang_id', 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const projectFlockKandangChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||||
|
formik.setFieldTouched('project_flock_kandang', true);
|
||||||
|
formik.setFieldValue('project_flock_kandang', val);
|
||||||
|
formik.setFieldTouched('project_flock_kandang_id', true);
|
||||||
|
formik.setFieldValue('project_flock_kandang_id', (val as OptionType)?.value || 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// EVENT HANDLERS - Date Time
|
// EVENT HANDLERS - Date Time
|
||||||
@@ -303,28 +374,41 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||||
<TextInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
label='Project Flock Kandang ID'
|
label='Lokasi'
|
||||||
type='number'
|
value={selectedLocation}
|
||||||
name='project_flock_kandang_id'
|
onChange={locationChangeHandler}
|
||||||
value={formik.values.project_flock_kandang_id?.toString() || ''}
|
options={locationOptions}
|
||||||
onChange={(e) => {
|
onInputChange={setLocationSearchValue}
|
||||||
const value = e.target.value;
|
isLoading={isLoadingLocations}
|
||||||
formik.setFieldValue(
|
isDisabled={type === 'detail'}
|
||||||
'project_flock_kandang_id',
|
placeholder='Pilih Lokasi'
|
||||||
parseInt(value) || 0
|
isClearable
|
||||||
);
|
isSearchable
|
||||||
projectFlockChangeHandler(value);
|
/>
|
||||||
}}
|
|
||||||
onBlur={formik.handleBlur}
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='Project Flock'
|
||||||
|
value={formik.values.project_flock_kandang ?? undefined}
|
||||||
|
onChange={projectFlockKandangChangeHandler}
|
||||||
|
options={projectFlockKandangOptions}
|
||||||
|
onInputChange={setProjectFlockSearchValue}
|
||||||
|
isLoading={isLoadingProjectFlocks}
|
||||||
isError={
|
isError={
|
||||||
formik.touched.project_flock_kandang_id &&
|
formik.touched.project_flock_kandang_id &&
|
||||||
Boolean(formik.errors.project_flock_kandang_id)
|
Boolean(formik.errors.project_flock_kandang_id)
|
||||||
}
|
}
|
||||||
errorMessage={formik.errors.project_flock_kandang_id as string}
|
errorMessage={formik.errors.project_flock_kandang_id as string}
|
||||||
readOnly={type === 'detail'}
|
isDisabled={type === 'detail' || !selectedLocation}
|
||||||
placeholder='Masukkan project flock kandang ID'
|
placeholder={
|
||||||
|
selectedLocation
|
||||||
|
? 'Pilih Project Flock - Kandang'
|
||||||
|
: 'Pilih Lokasi terlebih dahulu'
|
||||||
|
}
|
||||||
|
isClearable
|
||||||
|
isSearchable
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -369,21 +453,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
readOnly={type === 'detail'}
|
readOnly={type === 'detail'}
|
||||||
placeholder='Masukkan status (0-3)'
|
placeholder='Masukkan status (0-3)'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CheckboxInput
|
|
||||||
hidden={true}
|
|
||||||
name='ontime'
|
|
||||||
checked={formik.values.ontime || false}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
formik.setFieldValue('ontime', e.target.checked);
|
|
||||||
}}
|
|
||||||
disabled={type !== 'detail'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|
||||||
{/* Body Weights Table */}
|
{/* Body Weights Table */}
|
||||||
<Card
|
<Card
|
||||||
title='Data Bobot Badan'
|
title='Bobot Badan'
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full mb-4 shadow',
|
wrapper: 'w-full mb-4 shadow',
|
||||||
title: 'mb-4',
|
title: 'mb-4',
|
||||||
@@ -583,7 +659,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
{/* Stocks Table */}
|
{/* Stocks Table */}
|
||||||
<Card
|
<Card
|
||||||
title='Data Stok Pakan'
|
title='Stok Persediaan'
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full mb-4 shadow',
|
wrapper: 'w-full mb-4 shadow',
|
||||||
title: 'mb-4',
|
title: 'mb-4',
|
||||||
@@ -620,7 +696,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</th>
|
</th>
|
||||||
)}
|
)}
|
||||||
<th>
|
<th>
|
||||||
Product Warehouse ID
|
Persediaan
|
||||||
<span
|
<span
|
||||||
className='tooltip tooltip-error tooltip-bottom z-[9999]'
|
className='tooltip tooltip-error tooltip-bottom z-[9999]'
|
||||||
data-tip='required'
|
data-tip='required'
|
||||||
@@ -826,7 +902,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
{/* Depletions Table */}
|
{/* Depletions Table */}
|
||||||
<Card
|
<Card
|
||||||
title='Data Depletions (Hilang/Mati)'
|
title='Deplesi'
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full mb-4 shadow',
|
wrapper: 'w-full mb-4 shadow',
|
||||||
title: 'mb-4',
|
title: 'mb-4',
|
||||||
|
|||||||
Reference in New Issue
Block a user