mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 05:22:02 +00:00
Merge branch 'development' into 'production'
refactor(FE-add-param): Update MarketingFilter to refine API calls and See merge request mbugroup/lti-web-client!400
This commit is contained in:
@@ -5,11 +5,14 @@ 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, useMemo } from 'react';
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import useSWR from 'swr';
|
||||
import { DashboardApi } from '@/services/api/dashboard';
|
||||
import { useFormik } from 'formik';
|
||||
import { ProjectFlockApi } from '@/services/api/production';
|
||||
import {
|
||||
ProjectFlockApi,
|
||||
ProjectFlockKandangApi,
|
||||
} from '@/services/api/production';
|
||||
import { LocationApi } from '@/services/api/master-data';
|
||||
import { generateDashboardPDF } from '@/components/pages/dashboard/export/DashboardPDF';
|
||||
import {
|
||||
@@ -22,10 +25,7 @@ import DashboardExportCharts, {
|
||||
DashboardExportChartsRef,
|
||||
} from '@/components/pages/dashboard/export/DashboardExportCharts';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/input/RadioInput';
|
||||
import {
|
||||
DashboardFilter,
|
||||
DashboardMeta,
|
||||
} from '@/types/api/dashboard/dashboard';
|
||||
import { DashboardMeta } from '@/types/api/dashboard/dashboard';
|
||||
import DashboardStats from '@/components/pages/dashboard/chart/DashboardStats';
|
||||
import { isResponseSuccess } from '@/lib/api-helper';
|
||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||
@@ -43,6 +43,7 @@ import DashboardExportStats, {
|
||||
DashboardExportStatsRef,
|
||||
} from '@/components/pages/dashboard/export/DashboardExportStats';
|
||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||
|
||||
// Helper function to normalize values to array
|
||||
const normalizeToArray = (
|
||||
@@ -72,7 +73,6 @@ 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);
|
||||
@@ -116,15 +116,13 @@ const DashboardProduction = () => {
|
||||
options: flockOptions,
|
||||
isLoadingOptions: isLoadingFlockOptions,
|
||||
loadMore: loadMoreFlock,
|
||||
rawData: projectFlocksRawData,
|
||||
} = useSelect<ProjectFlock>(
|
||||
ProjectFlockApi.basePath,
|
||||
'id',
|
||||
'flock_name',
|
||||
'',
|
||||
'search',
|
||||
{
|
||||
location_id:
|
||||
selectedLocationIds.length > 0 ? selectedLocationIds.toString() : '',
|
||||
location_id: selectedLocationIds ? selectedLocationIds.toString() : '',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -165,66 +163,34 @@ 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 selectedLocationValues = normalizeToArray(formik.values.location);
|
||||
const selectedFlockValues = normalizeToArray(formik.values.flock);
|
||||
|
||||
const {
|
||||
setInputValue: setInputValueKandang,
|
||||
options: kandangOptions,
|
||||
isLoadingOptions: isLoadingKandangOptions,
|
||||
loadMore: loadMoreKandang,
|
||||
} = kandangSelect;
|
||||
} = useSelect<ProjectFlockKandang>(
|
||||
ProjectFlockKandangApi.basePath,
|
||||
'kandang_id',
|
||||
'kandang.name',
|
||||
'search',
|
||||
{
|
||||
location_id:
|
||||
selectedLocationValues.length > 0
|
||||
? selectedLocationValues.toString()
|
||||
: '',
|
||||
project_flock_id:
|
||||
selectedFlockValues.length > 0 ? selectedFlockValues.toString() : '',
|
||||
}
|
||||
);
|
||||
|
||||
const handleResetFilter = useCallback(() => {
|
||||
resetForm();
|
||||
resetFilterValues(); // Clear stored filter values
|
||||
setAnalysisMode('OVERVIEW');
|
||||
setSelectedLocationIds([]);
|
||||
setRawKandangInputValue('');
|
||||
filterModal.closeModal();
|
||||
}, [filterModal, resetForm, resetFilterValues]);
|
||||
|
||||
@@ -520,7 +486,6 @@ const DashboardProduction = () => {
|
||||
formik.setFieldValue('kandang', []);
|
||||
formik.setFieldValue('comparisonType', '');
|
||||
setSelectedLocationIds([]);
|
||||
setRawKandangInputValue('');
|
||||
}}
|
||||
color='primary'
|
||||
className={{
|
||||
@@ -592,7 +557,6 @@ const DashboardProduction = () => {
|
||||
// Reset dependent fields when location changes
|
||||
formik.setFieldValue('flock', []);
|
||||
formik.setFieldValue('kandang', []);
|
||||
setRawKandangInputValue('');
|
||||
}}
|
||||
errorMessage={formik.errors.location as string}
|
||||
options={locationOptions}
|
||||
@@ -625,7 +589,6 @@ const DashboardProduction = () => {
|
||||
// Reset dependent fields when location changes
|
||||
formik.setFieldValue('flock', []);
|
||||
formik.setFieldValue('kandang', []);
|
||||
setRawKandangInputValue('');
|
||||
}}
|
||||
errorMessage={formik.errors.location as string}
|
||||
options={locationOptions}
|
||||
@@ -662,11 +625,9 @@ const DashboardProduction = () => {
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
onChange={(selected) => {
|
||||
formik.setFieldValue('flock', selected);
|
||||
formik.setFieldValue('kandang', []);
|
||||
setInputValueKandang('');
|
||||
}}
|
||||
onChange={(selected) =>
|
||||
formik.setFieldValue('flock', selected)
|
||||
}
|
||||
errorMessage={formik.errors.flock as string}
|
||||
onInputChange={setInputValueFlock}
|
||||
onMenuScrollToBottom={loadMoreFlock}
|
||||
@@ -691,11 +652,9 @@ const DashboardProduction = () => {
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
onChange={(selected) => {
|
||||
formik.setFieldValue('flock', selected);
|
||||
formik.setFieldValue('kandang', []);
|
||||
setInputValueKandang('');
|
||||
}}
|
||||
onChange={(selected) =>
|
||||
formik.setFieldValue('flock', selected)
|
||||
}
|
||||
errorMessage={formik.errors.flock as string}
|
||||
onInputChange={setInputValueFlock}
|
||||
onMenuScrollToBottom={loadMoreFlock}
|
||||
|
||||
@@ -207,7 +207,7 @@ const ExpenseRealizationForm = ({
|
||||
|
||||
// add new realizations for each kandang
|
||||
kandangs.forEach((kandangItem) => {
|
||||
if (!kandangItem.id) return;
|
||||
if (isNaN(Number(kandangItem.id))) return;
|
||||
|
||||
const existingRealization = formik.values.realizations?.find(
|
||||
(realizationItem) => realizationItem.kandang_id === kandangItem.id
|
||||
|
||||
@@ -35,6 +35,7 @@ const ExpenseRealizationKandangDetailExpense: React.FC<
|
||||
setInputValue: setNonstockInputValue,
|
||||
options: nonstockOptions,
|
||||
isLoadingOptions: isLoadingNonstockOptions,
|
||||
loadMore: loadMoreNonstocks,
|
||||
} = useSelect<Nonstock>(
|
||||
NonstockApi.basePath,
|
||||
'id',
|
||||
@@ -164,6 +165,7 @@ const ExpenseRealizationKandangDetailExpense: React.FC<
|
||||
options={nonstockOptions}
|
||||
isLoading={isLoadingNonstockOptions}
|
||||
onInputChange={setNonstockInputValue}
|
||||
onMenuScrollToBottom={loadMoreNonstocks}
|
||||
className={{ wrapper: 'min-w-48' }}
|
||||
isDisabled
|
||||
/>
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import { MarketingFilter } from '@/types/api/marketing/marketing';
|
||||
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
|
||||
import { MarketingApi } from '@/services/api/marketing/marketing';
|
||||
import { CustomerApi } from '@/services/api/master-data';
|
||||
import { isResponseSuccess } from '@/lib/api-helper';
|
||||
import { BaseMarketing, BaseSalesOrder } from '@/types/api/marketing/marketing';
|
||||
|
||||
@@ -41,9 +42,12 @@ const MarketingFilterModal = ({
|
||||
isLoadingOptions: isLoadingProductsOptions,
|
||||
setInputValue: setProductsInputValue,
|
||||
loadMore: loadMoreProducts,
|
||||
} = useSelect<BaseMarketing>(MarketingApi.basePath, 'id', 'so_number', '', {
|
||||
limit: 'limit',
|
||||
});
|
||||
} = useSelect<BaseMarketing>(
|
||||
MarketingApi.basePath,
|
||||
'id',
|
||||
'so_number',
|
||||
'search'
|
||||
);
|
||||
|
||||
const productsOptions = useMemo(() => {
|
||||
if (!productsRawData || !isResponseSuccess(productsRawData)) return [];
|
||||
@@ -70,19 +74,10 @@ const MarketingFilterModal = ({
|
||||
isLoadingOptions: isLoadingCustomersOptions,
|
||||
setInputValue: setCustomersInputValue,
|
||||
loadMore: loadMoreCustomers,
|
||||
} = useSelect(MarketingApi.basePath, 'customer.id', 'customer.name', '', {
|
||||
limit: 'limit',
|
||||
} = useSelect(CustomerApi.basePath, 'id', 'name', 'search', {
|
||||
has_marketing: 'true',
|
||||
});
|
||||
|
||||
const salesCustomerOptions = useMemo(() => {
|
||||
const seen = new Set<string | number>();
|
||||
return customersOptions.filter((customer) => {
|
||||
if (seen.has(customer.value)) return false;
|
||||
seen.add(customer.value);
|
||||
return true;
|
||||
});
|
||||
}, [customersOptions]);
|
||||
|
||||
const statusOptions = [
|
||||
...MARKETING_APPROVAL_LINE.map((item) => ({
|
||||
value: item.step_name.split(' ').join('_').toUpperCase(),
|
||||
@@ -190,7 +185,7 @@ const MarketingFilterModal = ({
|
||||
label='Customer'
|
||||
isClearable
|
||||
placeholder='Pilih customer'
|
||||
options={salesCustomerOptions}
|
||||
options={customersOptions}
|
||||
isLoading={isLoadingCustomersOptions}
|
||||
value={formik.values.customer}
|
||||
onChange={customerChangeHandler}
|
||||
|
||||
@@ -198,7 +198,7 @@ const ReportExpenseTab = ({ tabId }: ReportExpenseTabProps) => {
|
||||
if (filterParams.supplier_id)
|
||||
params.append('supplier_id', filterParams.supplier_id);
|
||||
if (filterParams.kandang_id)
|
||||
params.append('kandang_id', filterParams.kandang_id);
|
||||
params.append('project_flock_kandang_id', filterParams.kandang_id);
|
||||
if (filterParams.nonstock_id)
|
||||
params.append('nonstock_id', filterParams.nonstock_id);
|
||||
if (filterParams.realization_date)
|
||||
|
||||
Reference in New Issue
Block a user