mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 07:15:44 +00:00
Merge branch 'development' into fix/transfer-to-laying
This commit is contained in:
@@ -71,7 +71,6 @@ import {
|
||||
|
||||
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
|
||||
import { formatDate, formatNumber } from '@/lib/helper';
|
||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
||||
import toast from 'react-hot-toast';
|
||||
import ApprovalSteps, {
|
||||
useApprovalSteps,
|
||||
@@ -423,7 +422,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
options: locationOptions,
|
||||
isLoadingOptions: isLoadingLocations,
|
||||
loadMore: loadMoreLocations,
|
||||
hasMore: hasMoreLocations,
|
||||
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
@@ -432,7 +430,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
rawData: projectFlocksRawData,
|
||||
isLoadingOptions: isLoadingProjectFlocks,
|
||||
loadMore: loadMoreProjectFlocks,
|
||||
hasMore: hasMoreProjectFlocks,
|
||||
} = useSelect(ProjectFlockApi.basePath, 'id', 'flock_name', 'search', {
|
||||
location_id: selectedProjectFlockLocationId,
|
||||
});
|
||||
@@ -531,7 +528,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
rawData: stockProducts,
|
||||
isLoadingOptions: isLoadingStockProducts,
|
||||
loadMore: loadMoreStockProducts,
|
||||
hasMore: hasMoreStockProducts,
|
||||
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', '', {
|
||||
flags: 'PAKAN,OVK',
|
||||
location_id: stockProductsLocationId,
|
||||
@@ -539,11 +535,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
});
|
||||
|
||||
const {
|
||||
options: depletionProductOptions,
|
||||
rawData: depletionProductsData,
|
||||
isLoadingOptions: isLoadingDepletionProducts,
|
||||
loadMore: loadMoreDepletionProducts,
|
||||
hasMore: hasMoreDepletionProducts,
|
||||
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', '', {
|
||||
location_id: depletionProductsLocationId,
|
||||
kandang_id: depletionProductsKandangId,
|
||||
@@ -584,11 +578,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
}, [nextDayRecordingData]);
|
||||
|
||||
const {
|
||||
options: eggProductOptions,
|
||||
rawData: eggProductsData,
|
||||
isLoadingOptions: isLoadingEggProducts,
|
||||
loadMore: loadMoreEggProducts,
|
||||
hasMore: hasMoreEggProducts,
|
||||
} = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', 'search', {
|
||||
search: 'telur',
|
||||
location_id: eggProductsLocationId,
|
||||
|
||||
@@ -51,6 +51,13 @@ import { generateUniformityExcel } from '@/components/pages/production/uniformit
|
||||
import Dropdown from '@/components/Dropdown';
|
||||
import Menu from '@/components/menu/Menu';
|
||||
import MenuItem from '@/components/menu/MenuItem';
|
||||
import { useFormik } from 'formik';
|
||||
import {
|
||||
UniformityTableFilterSchema,
|
||||
type UniformityTableFilterValues,
|
||||
} from '@/components/pages/production/uniformity/UniformityTableFilter.schema';
|
||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||
|
||||
const UniformityConfirmationPreview = ({
|
||||
uniformity,
|
||||
@@ -241,7 +248,6 @@ const UniformityTable = () => {
|
||||
options: filterLocationOptions,
|
||||
isLoadingOptions: isLoadingFilterLocations,
|
||||
loadMore: loadMoreFilterLocations,
|
||||
hasMore: hasMoreFilterLocations,
|
||||
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
// ===== FETCH PROJECT FLOCKS DATA FOR FILTER =====
|
||||
@@ -251,7 +257,6 @@ const UniformityTable = () => {
|
||||
rawData: filterProjectFlocksRawData,
|
||||
isLoadingOptions: isLoadingFilterProjectFlocks,
|
||||
loadMore: loadMoreFilterProjectFlocks,
|
||||
hasMore: hasMoreFilterProjectFlocks,
|
||||
} = useSelect(ProjectFlockApi.basePath, 'id', 'flock_name', 'search', {
|
||||
location_id: filterProjectFlockLocationId,
|
||||
});
|
||||
@@ -316,6 +321,34 @@ const UniformityTable = () => {
|
||||
}
|
||||
}, [projectFlockKandangLookup]);
|
||||
|
||||
// ===== FORMIK FILTER =====
|
||||
const filterFormik = useFormik<UniformityTableFilterValues>({
|
||||
initialValues: {
|
||||
start_date: filterStartDate,
|
||||
end_date: filterEndDate,
|
||||
location: filterLocation,
|
||||
project_flock: filterProjectFlock,
|
||||
project_flock_kandang_id: filterProjectFlockKandangId,
|
||||
kandang: filterKandang,
|
||||
},
|
||||
validationSchema: UniformityTableFilterSchema,
|
||||
enableReinitialize: true,
|
||||
onSubmit: async (values) => {
|
||||
setFilterStartDate(values.start_date);
|
||||
setFilterEndDate(values.end_date);
|
||||
setFilterLocation(values.location ?? null);
|
||||
setFilterProjectFlock(values.project_flock ?? null);
|
||||
setFilterKandang(values.kandang ?? null);
|
||||
|
||||
setIsSubmitted(true);
|
||||
filterModal.closeModal();
|
||||
},
|
||||
});
|
||||
|
||||
// ===== FORMIK ERROR LIST =====
|
||||
const { formErrorList, close, handleFormSubmit } =
|
||||
useFormikErrorList(filterFormik);
|
||||
|
||||
// ===== BUILD SWR KEY WITH FILTERS =====
|
||||
const uniformitySwrKey = useMemo(() => {
|
||||
const basePath = UniformityApi.basePath;
|
||||
@@ -372,29 +405,54 @@ const UniformityTable = () => {
|
||||
const handleFilterLocationChange = useCallback(
|
||||
(val: OptionType | OptionType[] | null) => {
|
||||
const location = val as OptionType | null;
|
||||
const locationId = Number(location?.value) || 0;
|
||||
|
||||
filterFormik.setFieldValue('location', location);
|
||||
filterFormik.setFieldValue('location_id', locationId);
|
||||
|
||||
setFilterLocation(location);
|
||||
setFilterProjectFlock(null);
|
||||
setFilterKandang(null);
|
||||
setFilterProjectFlockLocationId(
|
||||
location ? location.value.toString() : ''
|
||||
);
|
||||
|
||||
filterFormik.setFieldValue('project_flock', null);
|
||||
filterFormik.setFieldValue('project_flock_id', 0);
|
||||
filterFormik.setFieldValue('kandang', null);
|
||||
filterFormik.setFieldValue('kandang_id', 0);
|
||||
},
|
||||
[]
|
||||
[filterFormik]
|
||||
);
|
||||
|
||||
const handleFilterProjectFlockChange = useCallback(
|
||||
(val: OptionType | OptionType[] | null) => {
|
||||
setFilterProjectFlock(val as OptionType | null);
|
||||
const projectFlock = val as OptionType | null;
|
||||
const projectFlockId = Number(projectFlock?.value) || 0;
|
||||
|
||||
filterFormik.setFieldValue('project_flock', projectFlock);
|
||||
filterFormik.setFieldValue('project_flock_id', projectFlockId);
|
||||
|
||||
setFilterProjectFlock(projectFlock);
|
||||
setFilterKandang(null);
|
||||
|
||||
filterFormik.setFieldValue('kandang', null);
|
||||
filterFormik.setFieldValue('kandang_id', 0);
|
||||
},
|
||||
[]
|
||||
[filterFormik]
|
||||
);
|
||||
|
||||
const handleFilterKandangChange = useCallback(
|
||||
(val: OptionType | OptionType[] | null) => {
|
||||
setFilterKandang(val as OptionType | null);
|
||||
const kandang = val as OptionType | null;
|
||||
const kandangId = Number(kandang?.value) || 0;
|
||||
|
||||
filterFormik.setFieldValue('kandang', kandang);
|
||||
filterFormik.setFieldValue('kandang_id', kandangId);
|
||||
|
||||
setFilterKandang(kandang);
|
||||
},
|
||||
[]
|
||||
[filterFormik]
|
||||
);
|
||||
|
||||
const handleResetFilters = useCallback(() => {
|
||||
@@ -405,41 +463,34 @@ const UniformityTable = () => {
|
||||
setFilterProjectFlockKandangId(undefined);
|
||||
setFilterStartDate('');
|
||||
setFilterEndDate('');
|
||||
}, []);
|
||||
setFilterErrors({});
|
||||
|
||||
filterFormik.resetForm();
|
||||
}, [filterFormik]);
|
||||
|
||||
const handleFilterStartDateChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setFilterStartDate(value);
|
||||
filterFormik.setFieldValue('start_date', value);
|
||||
},
|
||||
[filterFormik]
|
||||
);
|
||||
|
||||
const handleFilterEndDateChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setFilterEndDate(value);
|
||||
filterFormik.setFieldValue('end_date', value);
|
||||
},
|
||||
[filterFormik]
|
||||
);
|
||||
|
||||
const handleApplyFilters = useCallback(() => {
|
||||
const errors: Record<string, string> = {};
|
||||
|
||||
if (!filterStartDate) {
|
||||
errors.start_date = 'Tanggal mulai wajib diisi';
|
||||
}
|
||||
if (!filterEndDate) {
|
||||
errors.end_date = 'Tanggal akhir wajib diisi';
|
||||
}
|
||||
if (!filterLocation) {
|
||||
errors.location = 'Lokasi wajib dipilih';
|
||||
}
|
||||
if (!filterProjectFlock) {
|
||||
errors.project_flock = 'Project Flock wajib dipilih';
|
||||
}
|
||||
if (!filterKandang) {
|
||||
errors.kandang = 'Kandang wajib dipilih';
|
||||
}
|
||||
|
||||
setFilterErrors(errors);
|
||||
|
||||
if (Object.keys(errors).length === 0) {
|
||||
setIsSubmitted(true);
|
||||
filterModal.closeModal();
|
||||
}
|
||||
}, [
|
||||
filterModal,
|
||||
filterStartDate,
|
||||
filterEndDate,
|
||||
filterLocation,
|
||||
filterProjectFlock,
|
||||
filterKandang,
|
||||
]);
|
||||
handleFormSubmit(
|
||||
new Event('submit') as unknown as React.FormEvent<HTMLFormElement>
|
||||
);
|
||||
}, [handleFormSubmit]);
|
||||
|
||||
const selectedRowIds = useMemo(() => {
|
||||
return Object.keys(rowSelection)
|
||||
@@ -1136,108 +1187,117 @@ const UniformityTable = () => {
|
||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Error List Alert */}
|
||||
{formErrorList.length > 0 && (
|
||||
<div className='w-full px-4'>
|
||||
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='space-y-4 px-4'>
|
||||
<div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-4'>
|
||||
<div>
|
||||
<DateInput
|
||||
label='Tanggal'
|
||||
required
|
||||
label='Tanggal mulai'
|
||||
name='start_date'
|
||||
value={filterStartDate}
|
||||
onChange={(e) => {
|
||||
setFilterStartDate(e.target.value);
|
||||
setFilterErrors((prev) => ({ ...prev, start_date: '' }));
|
||||
}}
|
||||
value={filterFormik.values.start_date}
|
||||
onChange={handleFilterStartDateChange}
|
||||
onBlur={filterFormik.handleBlur}
|
||||
isError={
|
||||
filterFormik.touched.start_date &&
|
||||
Boolean(filterFormik.errors.start_date)
|
||||
}
|
||||
errorMessage={filterFormik.errors.start_date}
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
{filterErrors.start_date && (
|
||||
<p className='text-red-500 text-sm mt-1'>
|
||||
{filterErrors.start_date}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<DateInput
|
||||
label=' '
|
||||
required
|
||||
label='Tanggal akhir'
|
||||
name='end_date'
|
||||
value={filterEndDate}
|
||||
onChange={(e) => {
|
||||
setFilterEndDate(e.target.value);
|
||||
setFilterErrors((prev) => ({ ...prev, end_date: '' }));
|
||||
}}
|
||||
value={filterFormik.values.end_date}
|
||||
onChange={handleFilterEndDateChange}
|
||||
onBlur={filterFormik.handleBlur}
|
||||
isError={
|
||||
filterFormik.touched.end_date &&
|
||||
Boolean(filterFormik.errors.end_date)
|
||||
}
|
||||
errorMessage={filterFormik.errors.end_date}
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
{filterErrors.end_date && (
|
||||
<p className='text-red-500 text-sm mt-1'>
|
||||
{filterErrors.end_date}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SelectInput
|
||||
required
|
||||
label='Lokasi'
|
||||
placeholder='Pilih Lokasi...'
|
||||
value={filterLocation}
|
||||
value={filterFormik.values.location}
|
||||
onChange={(value) => {
|
||||
handleFilterLocationChange(value);
|
||||
setFilterErrors((prev) => ({ ...prev, location: '' }));
|
||||
}}
|
||||
options={filterLocationOptions}
|
||||
onInputChange={setFilterLocationInputValue}
|
||||
isLoading={isLoadingFilterLocations}
|
||||
onMenuScrollToBottom={loadMoreFilterLocations}
|
||||
isError={
|
||||
filterFormik.touched.location &&
|
||||
Boolean(filterFormik.errors.location)
|
||||
}
|
||||
errorMessage={filterFormik.errors.location}
|
||||
isClearable
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
{filterErrors.location && (
|
||||
<p className='text-red-500 text-sm mt-1'>
|
||||
{filterErrors.location}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SelectInput
|
||||
required
|
||||
label='Project Flock'
|
||||
placeholder='Pilih Project Flock...'
|
||||
value={filterProjectFlock}
|
||||
value={filterFormik.values.project_flock}
|
||||
onChange={(value) => {
|
||||
handleFilterProjectFlockChange(value);
|
||||
setFilterErrors((prev) => ({ ...prev, project_flock: '' }));
|
||||
}}
|
||||
options={filterProjectFlockOptions}
|
||||
onInputChange={setFilterProjectFlockSearchValue}
|
||||
isLoading={isLoadingFilterProjectFlocks}
|
||||
onMenuScrollToBottom={loadMoreFilterProjectFlocks}
|
||||
isDisabled={!filterLocation}
|
||||
isDisabled={!filterFormik.values.location}
|
||||
isError={
|
||||
filterFormik.touched.project_flock &&
|
||||
Boolean(filterFormik.errors.project_flock)
|
||||
}
|
||||
errorMessage={filterFormik.errors.project_flock}
|
||||
isClearable
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
{filterErrors.project_flock && (
|
||||
<p className='text-red-500 text-sm mt-1'>
|
||||
{filterErrors.project_flock}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SelectInput
|
||||
required
|
||||
label='Kandang'
|
||||
placeholder='Pilih Kandang...'
|
||||
value={filterKandang}
|
||||
value={filterFormik.values.kandang}
|
||||
onChange={(value) => {
|
||||
handleFilterKandangChange(value);
|
||||
setFilterErrors((prev) => ({ ...prev, kandang: '' }));
|
||||
}}
|
||||
options={filterKandangOptions}
|
||||
isDisabled={!filterProjectFlock}
|
||||
isDisabled={!filterFormik.values.project_flock}
|
||||
isError={
|
||||
filterFormik.touched.kandang &&
|
||||
Boolean(filterFormik.errors.kandang)
|
||||
}
|
||||
errorMessage={filterFormik.errors.kandang}
|
||||
isClearable
|
||||
className={{ wrapper: 'w-full' }}
|
||||
/>
|
||||
{filterErrors.kandang && (
|
||||
<p className='text-red-500 text-sm mt-1'>
|
||||
{filterErrors.kandang}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { OptionType } from '@/components/input/SelectInput';
|
||||
import * as yup from 'yup';
|
||||
|
||||
export type UniformityTableFilterType = {
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
location: OptionType | null;
|
||||
project_flock: OptionType | null;
|
||||
project_flock_kandang_id: number | undefined;
|
||||
kandang: OptionType | null;
|
||||
};
|
||||
|
||||
export const UniformityTableFilterSchema = yup.object({
|
||||
start_date: yup.string().required('Tanggal mulai wajib diisi'),
|
||||
end_date: yup
|
||||
.string()
|
||||
.required('Tanggal akhir wajib diisi')
|
||||
.test(
|
||||
'is-greater-than-start',
|
||||
'Tanggal akhir tidak boleh masa lampau',
|
||||
function (value) {
|
||||
const { start_date } = this.parent;
|
||||
if (!start_date || !value) return true;
|
||||
return new Date(value) >= new Date(start_date);
|
||||
}
|
||||
),
|
||||
location: yup
|
||||
.mixed<OptionType>()
|
||||
.required('Lokasi wajib dipilih')
|
||||
.test('is-not-empty', 'Lokasi wajib dipilih', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
project_flock: yup
|
||||
.mixed<OptionType>()
|
||||
.required('Project Flock wajib dipilih')
|
||||
.test('is-not-empty', 'Project Flock wajib dipilih', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
project_flock_kandang_id: yup.number().optional(),
|
||||
kandang: yup
|
||||
.mixed<OptionType>()
|
||||
.required('Kandang wajib dipilih')
|
||||
.test('is-not-empty', 'Kandang wajib dipilih', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
}) as yup.ObjectSchema<UniformityTableFilterType>;
|
||||
|
||||
export type UniformityTableFilterValues = yup.InferType<
|
||||
typeof UniformityTableFilterSchema
|
||||
>;
|
||||
@@ -49,7 +49,7 @@ function CustomTooltip({ payload, label, active }: CustomTooltipProps) {
|
||||
<div className='flex flex-col gap-2 mt-2'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='w-5 h-5 bg-[#0069E0] rounded-md'></div>
|
||||
<div className='w-5 h-5 bg-primary rounded-md'></div>
|
||||
<span className='text-sm'>Ideal</span>
|
||||
</div>
|
||||
<span className='text-sm font-medium'>
|
||||
@@ -84,7 +84,7 @@ function CustomTooltip({ payload, label, active }: CustomTooltipProps) {
|
||||
<p className='m-0 font-bold text-white/50'>Uniformity 2025</p>
|
||||
<div className='flex items-center gap-2 mt-2 justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='w-5 h-5 bg-[#0069E0] rounded-md'></div>
|
||||
<div className='w-5 h-5 bg-primary rounded-md'></div>
|
||||
<span className='text-sm'>Ideal</span>
|
||||
</div>
|
||||
<span className='text-sm font-medium'>{chartData.idealRange}</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Cell, Pie, PieChart, ResponsiveContainer } from 'recharts';
|
||||
import Card from '@/components/Card';
|
||||
import { formatNumber } from '@/lib/helper';
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useFormik } from 'formik';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import moment from 'moment';
|
||||
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
||||
import { useUiStore } from '@/stores/ui/ui.store';
|
||||
import { useUniformityStore } from '@/stores/uniformity/uniformity.store';
|
||||
@@ -28,6 +27,7 @@ import { LocationApi } from '@/services/api/master-data';
|
||||
import {
|
||||
ProjectFlockApi,
|
||||
ProjectFlockKandangApi,
|
||||
RecordingApi,
|
||||
} from '@/services/api/production';
|
||||
import { UniformityApi } from '@/services/api/uniformity';
|
||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||
@@ -40,6 +40,7 @@ import {
|
||||
ProjectFlockKandangLookup,
|
||||
ProjectFlock,
|
||||
} from '@/types/api/production/project-flock';
|
||||
import { Recording } from '@/types/api/production/recording';
|
||||
import { Kandang } from '@/types/api/master-data/kandang';
|
||||
import UniformityPreviewForm from '@/components/pages/production/uniformity/form/UniformityPreviewForm';
|
||||
import UniformityResultForm from '@/components/pages/production/uniformity/form/UniformityResultForm';
|
||||
@@ -87,9 +88,7 @@ const UniformityForm = ({
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// ===== SELECT INPUT DATA =====
|
||||
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(
|
||||
null
|
||||
);
|
||||
const [, setSelectedLocation] = useState<OptionType | null>(null);
|
||||
|
||||
const [selectedProjectFlockLocationId, setSelectedProjectFlockLocationId] =
|
||||
useState<string>('');
|
||||
@@ -106,7 +105,6 @@ const UniformityForm = ({
|
||||
options: locationOptions,
|
||||
isLoadingOptions: isLoadingLocations,
|
||||
loadMore: loadMoreLocations,
|
||||
hasMore: hasMoreLocations,
|
||||
} = useSelect(LocationApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
@@ -115,7 +113,6 @@ const UniformityForm = ({
|
||||
rawData: projectFlocksRawData,
|
||||
isLoadingOptions: isLoadingProjectFlocks,
|
||||
loadMore: loadMoreProjectFlocks,
|
||||
hasMore: hasMoreProjectFlocks,
|
||||
} = useSelect(ProjectFlockApi.basePath, 'id', 'flock_name', 'search', {
|
||||
location_id: selectedProjectFlockLocationId,
|
||||
});
|
||||
@@ -204,6 +201,20 @@ const UniformityForm = ({
|
||||
? projectFlockKandangLookupData.data
|
||||
: undefined;
|
||||
|
||||
// ===== RECORDINGS DATA (FOR WEEK CALCULATION) =====
|
||||
const recordingsUrl = useMemo(() => {
|
||||
const params = new URLSearchParams({
|
||||
page: '1',
|
||||
limit: '100',
|
||||
});
|
||||
return `${RecordingApi.basePath}?${params.toString()}`;
|
||||
}, []);
|
||||
|
||||
const { data: recordingsData } = useSWR(
|
||||
recordingsUrl,
|
||||
RecordingApi.getAllFetcher
|
||||
);
|
||||
|
||||
// ===== FORM CONFIGURATION =====
|
||||
const formikInitialValues = useMemo<UniformityFormValues>(
|
||||
() => getUniformityFormInitialValues(initialValues),
|
||||
@@ -387,14 +398,24 @@ const UniformityForm = ({
|
||||
|
||||
// ===== SIDE EFFECTS =====
|
||||
useEffect(() => {
|
||||
if (formik.values.date) {
|
||||
const date = moment(formik.values.date);
|
||||
const weekNumber = date.week() - moment(date).startOf('month').week() + 1;
|
||||
const adjustedWeekNumber = weekNumber <= 0 ? weekNumber + 52 : weekNumber;
|
||||
if (
|
||||
projectFlockKandangLookup?.project_flock_kandang_id &&
|
||||
isResponseSuccess(recordingsData) &&
|
||||
recordingsData.data
|
||||
) {
|
||||
const matchingRecording = recordingsData.data.find(
|
||||
(recording: Recording) =>
|
||||
recording.project_flock?.project_flock_kandang_id ===
|
||||
projectFlockKandangLookup.project_flock_kandang_id
|
||||
);
|
||||
|
||||
formik.setFieldValue('week', adjustedWeekNumber);
|
||||
if (matchingRecording?.project_flock?.production_standart?.week) {
|
||||
const weekValue =
|
||||
matchingRecording.project_flock.production_standart.week;
|
||||
formik.setFieldValue('week', weekValue);
|
||||
}
|
||||
}
|
||||
}, [formik.values.date]);
|
||||
}, [projectFlockKandangLookup?.project_flock_kandang_id, recordingsData]);
|
||||
|
||||
useEffect(() => {
|
||||
const unsub = subscribeValidate(() => {
|
||||
@@ -598,7 +619,7 @@ const UniformityForm = ({
|
||||
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center'>
|
||||
<Button
|
||||
type='button'
|
||||
className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'
|
||||
className='rounded-2xl border border-sky-500 bg-primary text-white'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
document.getElementById('file-upload-input')?.click();
|
||||
@@ -622,7 +643,7 @@ const UniformityForm = ({
|
||||
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center'>
|
||||
<Button
|
||||
type='button'
|
||||
className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'
|
||||
className='rounded-2xl border border-sky-500 bg-primary text-white'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
document
|
||||
|
||||
@@ -68,7 +68,7 @@ const EmptyState = () => {
|
||||
<>
|
||||
<div className='absolute inset-0 flex flex-col items-center justify-center z-10 gap-2'>
|
||||
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center my-2'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-primary text-white'>
|
||||
<Icon icon={'heroicons:funnel'} className='text-4xl text-whitd' />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ const UniformityGaugeChartSkeleton: React.FC<
|
||||
|
||||
return (
|
||||
<div className='flex flex-col w-full items-center'>
|
||||
<div className='h-64 w-full relative flex justify-center min-h-[256px]'>
|
||||
<div className='h-64 w-full relative flex justify-center min-h-64'>
|
||||
<div className='relative w-full h-full flex flex-col items-center justify-end min-w-0'>
|
||||
<ResponsiveContainer width='100%' height={256}>
|
||||
<PieChart>
|
||||
@@ -57,7 +57,7 @@ const UniformityGaugeChartSkeleton: React.FC<
|
||||
</ResponsiveContainer>
|
||||
<div className='absolute inset-x-0 top-24 flex flex-col items-center justify-center'>
|
||||
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center mt-5'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-primary text-white'>
|
||||
<Icon
|
||||
icon={'heroicons:funnel'}
|
||||
className='text-4xl text-whitd'
|
||||
|
||||
@@ -5,7 +5,7 @@ const UniformityTableSkeleton = () => {
|
||||
return (
|
||||
<div className='flex flex-col items-center justify-center gap-2 my-20'>
|
||||
<div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-[#0069E0] text-white'>
|
||||
<Button className='rounded-2xl border border-sky-500 bg-primary text-white'>
|
||||
<Icon
|
||||
icon={'heroicons-outline:chart-bar'}
|
||||
className='text-4xl text-whitd'
|
||||
|
||||
Reference in New Issue
Block a user