refactor(FE-remove-kandang-fetch): Refactor Kandang select logic to use

derived options
This commit is contained in:
rstubryan
2026-04-13 11:48:32 +07:00
parent 3ad04e5bac
commit 907f6664e1
@@ -5,12 +5,12 @@ import { Icon } from '@iconify/react';
import Modal, { useModal } from '@/components/Modal';
import DateInput from '@/components/input/DateInput';
import { OptionType, useSelect } from '@/components/input/SelectInput';
import { useState, useEffect, useRef, useCallback } from 'react';
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import useSWR from 'swr';
import { DashboardApi } from '@/services/api/dashboard';
import { useFormik } from 'formik';
import { ProjectFlockApi } from '@/services/api/production';
import { KandangApi, LocationApi } from '@/services/api/master-data';
import { LocationApi } from '@/services/api/master-data';
import { generateDashboardPDF } from '@/components/pages/dashboard/export/DashboardPDF';
import {
DashboardFilterType,
@@ -42,6 +42,7 @@ import { cn } from '@/lib/helper';
import DashboardExportStats, {
DashboardExportStatsRef,
} from '@/components/pages/dashboard/export/DashboardExportStats';
import { ProjectFlock } from '@/types/api/production/project-flock';
// Helper function to normalize values to array
const normalizeToArray = (
@@ -71,6 +72,7 @@ const DashboardProduction = () => {
const [selectedLocationIds, setSelectedLocationIds] = useState<number[]>(
normalizeToArray(filterValues.location)
);
const [kandangInputValue, setRawKandangInputValue] = useState('');
const [exporting, setExporting] = useState(false);
const allChartsRef = useRef<DashboardExportChartsRef>(null);
const allStatsRef = useRef<DashboardExportStatsRef>(null);
@@ -114,9 +116,17 @@ const DashboardProduction = () => {
options: flockOptions,
isLoadingOptions: isLoadingFlockOptions,
loadMore: loadMoreFlock,
} = useSelect(ProjectFlockApi.basePath, 'id', 'flock_name', '', {
location_id: selectedLocationIds ? selectedLocationIds.toString() : '',
});
rawData: projectFlocksRawData,
} = useSelect<ProjectFlock>(
ProjectFlockApi.basePath,
'id',
'flock_name',
'',
{
location_id:
selectedLocationIds.length > 0 ? selectedLocationIds.toString() : '',
}
);
const {
setInputValue: setInputValueLocation,
@@ -125,13 +135,6 @@ const DashboardProduction = () => {
loadMore: loadMoreLocation,
} = useSelect(LocationApi.basePath, 'id', 'name');
const {
setInputValue: setInputValueKandang,
options: kandangOptions,
isLoadingOptions: isLoadingKandangOptions,
loadMore: loadMoreKandang,
} = useSelect(KandangApi.basePath, 'id', 'name', '');
const comparisonTypeOptions = [
{ value: 'FARM', label: 'Farm' },
{ value: 'FLOCK', label: 'Flock' },
@@ -162,11 +165,66 @@ const DashboardProduction = () => {
const { resetForm } = formik;
const selectedFlockIds = useMemo(
() => normalizeToArray(formik.values.flock),
[formik.values.flock]
);
const derivedKandangOptions = useMemo(() => {
if (!isResponseSuccess(projectFlocksRawData)) return [];
const availableProjectFlocks = projectFlocksRawData.data.filter(
(projectFlock) =>
selectedFlockIds.length === 0 ||
selectedFlockIds.includes(projectFlock.id)
);
const kandangMap = new Map<number, OptionType<number>>();
availableProjectFlocks.forEach((projectFlock) => {
projectFlock.kandangs?.forEach((kandang) => {
if (!kandangMap.has(kandang.id)) {
kandangMap.set(kandang.id, {
value: kandang.id,
label: kandang.name,
});
}
});
});
const normalizedSearch = kandangInputValue.trim().toLowerCase();
const allOptions = Array.from(kandangMap.values());
if (!normalizedSearch) return allOptions;
return allOptions.filter((option) =>
option.label.toLowerCase().includes(normalizedSearch)
);
}, [projectFlocksRawData, selectedFlockIds, kandangInputValue]);
const kandangSelect = useMemo(
() => ({
setInputValue: setRawKandangInputValue,
options: derivedKandangOptions,
isLoadingOptions: isLoadingFlockOptions,
loadMore: loadMoreFlock,
}),
[derivedKandangOptions, isLoadingFlockOptions, loadMoreFlock]
);
const {
setInputValue: setInputValueKandang,
options: kandangOptions,
isLoadingOptions: isLoadingKandangOptions,
loadMore: loadMoreKandang,
} = kandangSelect;
const handleResetFilter = useCallback(() => {
resetForm();
resetFilterValues(); // Clear stored filter values
setAnalysisMode('OVERVIEW');
setSelectedLocationIds([]);
setRawKandangInputValue('');
}, [resetForm, resetFilterValues]);
// ===== Formik Error List =====
@@ -461,6 +519,7 @@ const DashboardProduction = () => {
formik.setFieldValue('kandang', []);
formik.setFieldValue('comparisonType', '');
setSelectedLocationIds([]);
setRawKandangInputValue('');
}}
color='primary'
className={{
@@ -532,6 +591,7 @@ const DashboardProduction = () => {
// Reset dependent fields when location changes
formik.setFieldValue('flock', []);
formik.setFieldValue('kandang', []);
setRawKandangInputValue('');
}}
errorMessage={formik.errors.location as string}
options={locationOptions}
@@ -564,6 +624,7 @@ const DashboardProduction = () => {
// Reset dependent fields when location changes
formik.setFieldValue('flock', []);
formik.setFieldValue('kandang', []);
setRawKandangInputValue('');
}}
errorMessage={formik.errors.location as string}
options={locationOptions}
@@ -600,9 +661,11 @@ const DashboardProduction = () => {
| null
| undefined
}
onChange={(selected) =>
formik.setFieldValue('flock', selected)
}
onChange={(selected) => {
formik.setFieldValue('flock', selected);
formik.setFieldValue('kandang', []);
setInputValueKandang('');
}}
errorMessage={formik.errors.flock as string}
onInputChange={setInputValueFlock}
onMenuScrollToBottom={loadMoreFlock}
@@ -627,9 +690,11 @@ const DashboardProduction = () => {
| null
| undefined
}
onChange={(selected) =>
formik.setFieldValue('flock', selected)
}
onChange={(selected) => {
formik.setFieldValue('flock', selected);
formik.setFieldValue('kandang', []);
setInputValueKandang('');
}}
errorMessage={formik.errors.flock as string}
onInputChange={setInputValueFlock}
onMenuScrollToBottom={loadMoreFlock}