mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE): Replace active filter count logic with ButtonFilter
component
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
ClosingFilterType,
|
ClosingFilterType,
|
||||||
} from '@/components/pages/closing/filter/ClosingFilter';
|
} from '@/components/pages/closing/filter/ClosingFilter';
|
||||||
import ClosingTableSkeleton from '@/components/pages/closing/skeleton/ClosingTableSkeleton';
|
import ClosingTableSkeleton from '@/components/pages/closing/skeleton/ClosingTableSkeleton';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
props,
|
props,
|
||||||
@@ -287,23 +288,6 @@ const ClosingsTable = () => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.project_status, projectStatusOptions]);
|
}, [formik.values.project_status, projectStatusOptions]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (tableFilterState.location_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.project_status) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [tableFilterState.location_id, tableFilterState.project_status]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== SEARCH CHANGE HANDLER =====
|
// ===== SEARCH CHANGE HANDLER =====
|
||||||
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
updateFilter('search', e.target.value);
|
updateFilter('search', e.target.value);
|
||||||
@@ -352,25 +336,12 @@ const ClosingsTable = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={['page', 'pageSize', 'search']}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import PopoverButton from '@/components/popover/PopoverButton';
|
|||||||
import PopoverContent from '@/components/popover/PopoverContent';
|
import PopoverContent from '@/components/popover/PopoverContent';
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import MarketingFilterModal from '@/components/pages/marketing/MarketingFilter';
|
import MarketingFilterModal from '@/components/pages/marketing/MarketingFilter';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
const RowsOptionsMenu = ({
|
const RowsOptionsMenu = ({
|
||||||
props,
|
props,
|
||||||
@@ -214,32 +215,6 @@ const MarketingTable = () => {
|
|||||||
updateFilter('customer_id', '');
|
updateFilter('customer_id', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
// Product filter
|
|
||||||
if (tableFilterState.product_ids) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status filter
|
|
||||||
if (tableFilterState.status) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Customer filter
|
|
||||||
if (tableFilterState.customer_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [
|
|
||||||
tableFilterState.product_ids,
|
|
||||||
tableFilterState.status,
|
|
||||||
tableFilterState.customer_id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const approveClickHandler = () => {
|
const approveClickHandler = () => {
|
||||||
setApproveAction('APPROVED');
|
setApproveAction('APPROVED');
|
||||||
confirmationModal.openModal();
|
confirmationModal.openModal();
|
||||||
@@ -588,28 +563,14 @@ const MarketingTable = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={['page', 'pageSize', 'search']}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
filterModal.openModal();
|
filterModal.openModal();
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary':
|
|
||||||
activeFiltersCount > 0,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{activeFiltersCount > 0 && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
direction='bottom'
|
direction='bottom'
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import {
|
|||||||
} from './filter/ProjectFlockFilter';
|
} from './filter/ProjectFlockFilter';
|
||||||
import Modal from '@/components/Modal';
|
import Modal from '@/components/Modal';
|
||||||
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
props,
|
props,
|
||||||
@@ -346,25 +347,6 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.period, periodOptions]);
|
}, [formik.values.period, periodOptions]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
if (tableFilterState.area_id) count += 1;
|
|
||||||
if (tableFilterState.location_id) count += 1;
|
|
||||||
if (tableFilterState.kandang_id) count += 1;
|
|
||||||
if (tableFilterState.category) count += 1;
|
|
||||||
if (tableFilterState.period) count += 1;
|
|
||||||
return count;
|
|
||||||
}, [
|
|
||||||
tableFilterState.area_id,
|
|
||||||
tableFilterState.location_id,
|
|
||||||
tableFilterState.kandang_id,
|
|
||||||
tableFilterState.category,
|
|
||||||
tableFilterState.period,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== FILTER DEPENDENCY HANDLERS =====
|
// ===== FILTER DEPENDENCY HANDLERS =====
|
||||||
const handleFilterAreaChange = (area: OptionType | null) => {
|
const handleFilterAreaChange = (area: OptionType | null) => {
|
||||||
const areaId = area?.value ? String(area.value) : undefined;
|
const areaId = area?.value ? String(area.value) : undefined;
|
||||||
@@ -961,25 +943,12 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={['page', 'pageSize', 'search']}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import StatusBadge from '@/components/helper/StatusBadge';
|
|||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import { useUiStore } from '@/stores/ui/ui.store';
|
import { useUiStore } from '@/stores/ui/ui.store';
|
||||||
import { Color } from '@/types/theme';
|
import { Color } from '@/types/theme';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
// ===== STATUS BADGE UTILITIES =====
|
// ===== STATUS BADGE UTILITIES =====
|
||||||
const statusTextMap: Record<string, string> = {
|
const statusTextMap: Record<string, string> = {
|
||||||
@@ -511,36 +512,6 @@ const RecordingTable = () => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.kandang_id, kandangOptions]);
|
}, [formik.values.kandang_id, kandangOptions]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (tableFilterState.areaFilter) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.locationFilter) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.kandangFilter) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.projectFlockKandangFilter) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [
|
|
||||||
tableFilterState.areaFilter,
|
|
||||||
tableFilterState.locationFilter,
|
|
||||||
tableFilterState.kandangFilter,
|
|
||||||
tableFilterState.projectFlockKandangFilter,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== HANDLE FILTER MODAL OPEN =====
|
// ===== HANDLE FILTER MODAL OPEN =====
|
||||||
const handleFilterModalOpen = () => {
|
const handleFilterModalOpen = () => {
|
||||||
filterModal.openModal();
|
filterModal.openModal();
|
||||||
@@ -1264,25 +1235,12 @@ const RecordingTable = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={['page', 'pageSize', 'search']}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
import { Color } from '@/types/theme';
|
import { Color } from '@/types/theme';
|
||||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
props,
|
props,
|
||||||
@@ -159,30 +160,6 @@ const TransferToLayingsTable = () => {
|
|||||||
TransferToLayingApi.getAllFetcher
|
TransferToLayingApi.getAllFetcher
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (tableFilterState.startDate && tableFilterState.endDate) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.flockSource.length > 0) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.flockDestination.length > 0) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableFilterState.status.length > 0) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [tableFilterState]);
|
|
||||||
|
|
||||||
const isFilterActive = filterCount > 0;
|
|
||||||
|
|
||||||
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
|
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
@@ -559,30 +536,19 @@ const TransferToLayingsTable = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={[
|
||||||
|
'page',
|
||||||
|
'pageSize',
|
||||||
|
'search',
|
||||||
|
'filter_by',
|
||||||
|
'sort_by',
|
||||||
|
]}
|
||||||
|
fieldGroups={[['startDate', 'endDate']]}
|
||||||
onClick={filterModal.openModal}
|
onClick={filterModal.openModal}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary': isFilterActive,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{isFilterActive && (
|
|
||||||
<Badge
|
|
||||||
className={{
|
|
||||||
badge:
|
|
||||||
'p-1.5 bg-[#FF3535] text-xs text-base-100 border border-base-300 rounded-lg',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filterCount}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import {
|
|||||||
import { generateUniformityPDF } from '@/components/pages/production/uniformity/export/UniformityExportPDF';
|
import { generateUniformityPDF } from '@/components/pages/production/uniformity/export/UniformityExportPDF';
|
||||||
import { generateUniformityExcel } from '@/components/pages/production/uniformity/export/UniformityExportExcel';
|
import { generateUniformityExcel } from '@/components/pages/production/uniformity/export/UniformityExportExcel';
|
||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import {
|
import {
|
||||||
UniformityTableFilterSchema,
|
UniformityTableFilterSchema,
|
||||||
@@ -192,16 +193,28 @@ const UniformityTable = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
state: tableFilterState,
|
state: tableFilterState,
|
||||||
|
updateFilter,
|
||||||
setPage,
|
setPage,
|
||||||
|
setPageSize,
|
||||||
toQueryString: getTableFilterQueryString,
|
toQueryString: getTableFilterQueryString,
|
||||||
} = useTableFilter({
|
} = useTableFilter({
|
||||||
initial: {
|
initial: {
|
||||||
search: '',
|
search: '',
|
||||||
|
start_date: '',
|
||||||
|
end_date: '',
|
||||||
|
location_id: '',
|
||||||
|
project_flock_id: '',
|
||||||
|
kandang_id: '',
|
||||||
},
|
},
|
||||||
paramMap: {
|
paramMap: {
|
||||||
page: 'page',
|
page: 'page',
|
||||||
pageSize: 'limit',
|
pageSize: 'limit',
|
||||||
search: 'search',
|
search: 'search',
|
||||||
|
start_date: 'start_date',
|
||||||
|
end_date: 'end_date',
|
||||||
|
location_id: 'location_id',
|
||||||
|
project_flock_id: 'project_flock_id',
|
||||||
|
kandang_id: 'kandang_id',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -233,8 +246,6 @@ const UniformityTable = () => {
|
|||||||
const [filterKandang, setFilterKandang] = useState<OptionType | null>(null);
|
const [filterKandang, setFilterKandang] = useState<OptionType | null>(null);
|
||||||
const [filterProjectFlockKandangId, setFilterProjectFlockKandangId] =
|
const [filterProjectFlockKandangId, setFilterProjectFlockKandangId] =
|
||||||
useState<number | undefined>(undefined);
|
useState<number | undefined>(undefined);
|
||||||
const [filterStartDate, setFilterStartDate] = useState('');
|
|
||||||
const [filterEndDate, setFilterEndDate] = useState('');
|
|
||||||
const [filterProjectFlockLocationId, setFilterProjectFlockLocationId] =
|
const [filterProjectFlockLocationId, setFilterProjectFlockLocationId] =
|
||||||
useState<string>('');
|
useState<string>('');
|
||||||
const [, setFilterErrors] = useState<Record<string, string>>({});
|
const [, setFilterErrors] = useState<Record<string, string>>({});
|
||||||
@@ -319,8 +330,8 @@ const UniformityTable = () => {
|
|||||||
// ===== FORMIK FILTER =====
|
// ===== FORMIK FILTER =====
|
||||||
const filterFormik = useFormik<UniformityTableFilterValues>({
|
const filterFormik = useFormik<UniformityTableFilterValues>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
start_date: filterStartDate,
|
start_date: tableFilterState.start_date,
|
||||||
end_date: filterEndDate,
|
end_date: tableFilterState.end_date,
|
||||||
location: filterLocation,
|
location: filterLocation,
|
||||||
project_flock: filterProjectFlock,
|
project_flock: filterProjectFlock,
|
||||||
project_flock_kandang_id: filterProjectFlockKandangId,
|
project_flock_kandang_id: filterProjectFlockKandangId,
|
||||||
@@ -329,8 +340,21 @@ const UniformityTable = () => {
|
|||||||
validationSchema: UniformityTableFilterSchema,
|
validationSchema: UniformityTableFilterSchema,
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
setFilterStartDate(values.start_date);
|
updateFilter('start_date', values.start_date);
|
||||||
setFilterEndDate(values.end_date);
|
updateFilter('end_date', values.end_date);
|
||||||
|
updateFilter(
|
||||||
|
'location_id',
|
||||||
|
values.location?.value ? String(values.location.value) : ''
|
||||||
|
);
|
||||||
|
updateFilter(
|
||||||
|
'project_flock_id',
|
||||||
|
values.project_flock?.value ? String(values.project_flock.value) : ''
|
||||||
|
);
|
||||||
|
updateFilter(
|
||||||
|
'kandang_id',
|
||||||
|
values.kandang?.value ? String(values.kandang.value) : ''
|
||||||
|
);
|
||||||
|
|
||||||
setFilterLocation(values.location ?? null);
|
setFilterLocation(values.location ?? null);
|
||||||
setFilterProjectFlock(values.project_flock ?? null);
|
setFilterProjectFlock(values.project_flock ?? null);
|
||||||
setFilterKandang(values.kandang ?? null);
|
setFilterKandang(values.kandang ?? null);
|
||||||
@@ -356,11 +380,11 @@ const UniformityTable = () => {
|
|||||||
filterProjectFlockKandangId.toString()
|
filterProjectFlockKandangId.toString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (filterStartDate) {
|
if (tableFilterState.start_date) {
|
||||||
queryParams.append('start_date', filterStartDate);
|
queryParams.append('start_date', tableFilterState.start_date);
|
||||||
}
|
}
|
||||||
if (filterEndDate) {
|
if (tableFilterState.end_date) {
|
||||||
queryParams.append('end_date', filterEndDate);
|
queryParams.append('end_date', tableFilterState.end_date);
|
||||||
}
|
}
|
||||||
queryParams.append('with_chart', 'true');
|
queryParams.append('with_chart', 'true');
|
||||||
}
|
}
|
||||||
@@ -379,8 +403,8 @@ const UniformityTable = () => {
|
|||||||
}, [
|
}, [
|
||||||
isSubmitted,
|
isSubmitted,
|
||||||
filterProjectFlockKandangId,
|
filterProjectFlockKandangId,
|
||||||
filterStartDate,
|
tableFilterState.start_date,
|
||||||
filterEndDate,
|
tableFilterState.end_date,
|
||||||
getTableFilterQueryString,
|
getTableFilterQueryString,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -456,30 +480,16 @@ const UniformityTable = () => {
|
|||||||
setFilterProjectFlock(null);
|
setFilterProjectFlock(null);
|
||||||
setFilterKandang(null);
|
setFilterKandang(null);
|
||||||
setFilterProjectFlockKandangId(undefined);
|
setFilterProjectFlockKandangId(undefined);
|
||||||
setFilterStartDate('');
|
|
||||||
setFilterEndDate('');
|
|
||||||
setFilterErrors({});
|
setFilterErrors({});
|
||||||
|
|
||||||
|
updateFilter('start_date', '');
|
||||||
|
updateFilter('end_date', '');
|
||||||
|
updateFilter('location_id', '');
|
||||||
|
updateFilter('project_flock_id', '');
|
||||||
|
updateFilter('kandang_id', '');
|
||||||
|
|
||||||
filterFormik.resetForm();
|
filterFormik.resetForm();
|
||||||
}, [filterFormik]);
|
}, [filterFormik, updateFilter]);
|
||||||
|
|
||||||
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 selectedRowIds = useMemo(() => {
|
const selectedRowIds = useMemo(() => {
|
||||||
return Object.keys(rowSelection)
|
return Object.keys(rowSelection)
|
||||||
@@ -662,11 +672,11 @@ const UniformityTable = () => {
|
|||||||
filterProjectFlockKandangId.toString()
|
filterProjectFlockKandangId.toString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (filterStartDate) {
|
if (tableFilterState.start_date) {
|
||||||
queryParams.append('start_date', filterStartDate);
|
queryParams.append('start_date', tableFilterState.start_date);
|
||||||
}
|
}
|
||||||
if (filterEndDate) {
|
if (tableFilterState.end_date) {
|
||||||
queryParams.append('end_date', filterEndDate);
|
queryParams.append('end_date', tableFilterState.end_date);
|
||||||
}
|
}
|
||||||
queryParams.append('limit', '100');
|
queryParams.append('limit', '100');
|
||||||
queryParams.append('page', '1');
|
queryParams.append('page', '1');
|
||||||
@@ -677,7 +687,7 @@ const UniformityTable = () => {
|
|||||||
const response = await UniformityApi.getAllFetcher(url);
|
const response = await UniformityApi.getAllFetcher(url);
|
||||||
|
|
||||||
return isResponseSuccess(response) ? response.data : null;
|
return isResponseSuccess(response) ? response.data : null;
|
||||||
}, [filterProjectFlockKandangId, filterStartDate, filterEndDate]);
|
}, [filterProjectFlockKandangId, tableFilterState.start_date, tableFilterState.end_date]);
|
||||||
|
|
||||||
const handleExportExcel = useCallback(async () => {
|
const handleExportExcel = useCallback(async () => {
|
||||||
setIsExcelExportLoading(true);
|
setIsExcelExportLoading(true);
|
||||||
@@ -698,8 +708,8 @@ const UniformityTable = () => {
|
|||||||
location_name: locationName,
|
location_name: locationName,
|
||||||
project_flock_name: projectFlockName,
|
project_flock_name: projectFlockName,
|
||||||
kandang_name: kandangName,
|
kandang_name: kandangName,
|
||||||
start_date: filterStartDate,
|
start_date: tableFilterState.start_date,
|
||||||
end_date: filterEndDate,
|
end_date: tableFilterState.end_date,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success('Excel berhasil dibuat dan diunduh.');
|
toast.success('Excel berhasil dibuat dan diunduh.');
|
||||||
@@ -713,8 +723,8 @@ const UniformityTable = () => {
|
|||||||
filterLocation,
|
filterLocation,
|
||||||
filterProjectFlock,
|
filterProjectFlock,
|
||||||
filterKandang,
|
filterKandang,
|
||||||
filterStartDate,
|
tableFilterState.start_date,
|
||||||
filterEndDate,
|
tableFilterState.end_date,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleExportPDF = useCallback(async () => {
|
const handleExportPDF = useCallback(async () => {
|
||||||
@@ -736,8 +746,8 @@ const UniformityTable = () => {
|
|||||||
location_name: locationName,
|
location_name: locationName,
|
||||||
project_flock_name: projectFlockName,
|
project_flock_name: projectFlockName,
|
||||||
kandang_name: kandangName,
|
kandang_name: kandangName,
|
||||||
start_date: filterStartDate,
|
start_date: tableFilterState.start_date,
|
||||||
end_date: filterEndDate,
|
end_date: tableFilterState.end_date,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success('PDF berhasil dibuat dan diunduh.');
|
toast.success('PDF berhasil dibuat dan diunduh.');
|
||||||
@@ -751,8 +761,8 @@ const UniformityTable = () => {
|
|||||||
filterLocation,
|
filterLocation,
|
||||||
filterProjectFlock,
|
filterProjectFlock,
|
||||||
filterKandang,
|
filterKandang,
|
||||||
filterStartDate,
|
tableFilterState.start_date,
|
||||||
filterEndDate,
|
tableFilterState.end_date,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -883,37 +893,6 @@ const UniformityTable = () => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// ===== CALCULATE FILTER COUNT =====
|
|
||||||
const filterCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (filterStartDate && filterEndDate) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterLocation) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterProjectFlock) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterKandang) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [
|
|
||||||
filterStartDate,
|
|
||||||
filterEndDate,
|
|
||||||
filterLocation,
|
|
||||||
filterProjectFlock,
|
|
||||||
filterKandang,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const isFilterActive = filterCount > 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='@container w-full'>
|
<div className='@container w-full'>
|
||||||
@@ -932,30 +911,13 @@ const UniformityTable = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
|
<div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={tableFilterState}
|
||||||
color='none'
|
excludeFields={['page', 'pageSize', 'search']}
|
||||||
|
fieldGroups={[['start_date', 'end_date']]}
|
||||||
onClick={filterModal.openModal}
|
onClick={filterModal.openModal}
|
||||||
className={cn(
|
className='px-3 py-2.5'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
/>
|
||||||
{
|
|
||||||
'border-primary-gradient text-primary': isFilterActive,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{isFilterActive && (
|
|
||||||
<Badge
|
|
||||||
className={{
|
|
||||||
badge:
|
|
||||||
'p-1.5 bg-[#FF3535] text-xs text-base-100 border border-base-300 rounded-lg',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filterCount}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -1279,7 +1241,7 @@ const UniformityTable = () => {
|
|||||||
placeholder='Tanggal Mulai'
|
placeholder='Tanggal Mulai'
|
||||||
value={filterFormik.values.start_date}
|
value={filterFormik.values.start_date}
|
||||||
errorMessage={filterFormik.errors.start_date}
|
errorMessage={filterFormik.errors.start_date}
|
||||||
onChange={handleFilterStartDateChange}
|
onChange={(e) => filterFormik.setFieldValue('start_date', e.target.value)}
|
||||||
isError={
|
isError={
|
||||||
filterFormik.touched.start_date &&
|
filterFormik.touched.start_date &&
|
||||||
Boolean(filterFormik.errors.start_date)
|
Boolean(filterFormik.errors.start_date)
|
||||||
@@ -1291,7 +1253,7 @@ const UniformityTable = () => {
|
|||||||
placeholder='Tanggal Akhir'
|
placeholder='Tanggal Akhir'
|
||||||
value={filterFormik.values.end_date}
|
value={filterFormik.values.end_date}
|
||||||
errorMessage={filterFormik.errors.end_date}
|
errorMessage={filterFormik.errors.end_date}
|
||||||
onChange={handleFilterEndDateChange}
|
onChange={(e) => filterFormik.setFieldValue('end_date', e.target.value)}
|
||||||
isError={
|
isError={
|
||||||
filterFormik.touched.end_date &&
|
filterFormik.touched.end_date &&
|
||||||
Boolean(filterFormik.errors.end_date)
|
Boolean(filterFormik.errors.end_date)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import { Nonstock } from '@/types/api/master-data/nonstock';
|
|||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { httpClient } from '@/services/http/client';
|
import { httpClient } from '@/services/http/client';
|
||||||
import { BaseApiResponse } from '@/types/api/api-general';
|
import { BaseApiResponse } from '@/types/api/api-general';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
interface ReportExpenseTabProps {
|
interface ReportExpenseTabProps {
|
||||||
tabId: string;
|
tabId: string;
|
||||||
@@ -169,20 +170,6 @@ const ReportExpenseTab = ({ tabId }: ReportExpenseTabProps) => {
|
|||||||
[formik.values.category]
|
[formik.values.category]
|
||||||
);
|
);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
if (filterParams.location_id) count += 1;
|
|
||||||
if (filterParams.supplier_id) count += 1;
|
|
||||||
if (filterParams.kandang_id) count += 1;
|
|
||||||
if (filterParams.nonstock_id) count += 1;
|
|
||||||
if (filterParams.realization_date) count += 1;
|
|
||||||
if (filterParams.category) count += 1;
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: reportExpenseResponse, isLoading } = useSWR(
|
const { data: reportExpenseResponse, isLoading } = useSWR(
|
||||||
isSubmitted
|
isSubmitted
|
||||||
@@ -312,25 +299,12 @@ const ReportExpenseTab = ({ tabId }: ReportExpenseTabProps) => {
|
|||||||
setTabActions(
|
setTabActions(
|
||||||
tabId,
|
tabId,
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={formik.values}
|
||||||
color='none'
|
|
||||||
onClick={() => filterModal.openModal()}
|
onClick={() => filterModal.openModal()}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -387,8 +361,7 @@ const ReportExpenseTab = ({ tabId }: ReportExpenseTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
hasFilters,
|
formik.values,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
handleExportExcel,
|
handleExportExcel,
|
||||||
handleExportPDF,
|
handleExportPDF,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store';
|
|||||||
import CustomerSupplierSkeleton from '@/components/pages/report/finance/skeleton/CustomerSupplierSkeleton';
|
import CustomerSupplierSkeleton from '@/components/pages/report/finance/skeleton/CustomerSupplierSkeleton';
|
||||||
import { OptionType } from '@/components/table/TableRowSizeSelector';
|
import { OptionType } from '@/components/table/TableRowSizeSelector';
|
||||||
import { Color } from '@/types/theme';
|
import { Color } from '@/types/theme';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
interface CustomerPaymentTabProps {
|
interface CustomerPaymentTabProps {
|
||||||
tabId: string;
|
tabId: string;
|
||||||
@@ -213,30 +214,6 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.filter_by]);
|
}, [formik.values.filter_by]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
// Date filter (start_date + end_date = 1 filter)
|
|
||||||
if (filterParams.start_date || filterParams.end_date) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Customer filter
|
|
||||||
if (filterParams.customer_ids) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by type filter (hanya dihitung jika ada nilai yang dipilih)
|
|
||||||
if (filterParams.filter_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: customerPayment, isLoading } = useSWR(
|
const { data: customerPayment, isLoading } = useSWR(
|
||||||
isSubmitted
|
isSubmitted
|
||||||
@@ -380,25 +357,13 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
setTabActions(
|
setTabActions(
|
||||||
tabId,
|
tabId,
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={formik.values}
|
||||||
color='none'
|
fieldGroups={[['start_date', 'end_date']]}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -455,8 +420,7 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
hasFilters,
|
formik.values,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
handleExportExcel,
|
handleExportExcel,
|
||||||
handleExportPdf,
|
handleExportPdf,
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
|
|||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<ButtonFilter
|
<ButtonFilter
|
||||||
values={formik.values}
|
values={formik.values}
|
||||||
|
fieldGroups={[['startDate', 'endDate']]}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
variant='outline'
|
variant='outline'
|
||||||
className='px-3 py-2.5'
|
className='px-3 py-2.5'
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
|
|||||||
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
||||||
import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store';
|
import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store';
|
||||||
import PurchasePerSupplierSkeleton from '@/components/pages/report/logistic-stock/skeleton/PurchasePerSupplierSkeleton';
|
import PurchasePerSupplierSkeleton from '@/components/pages/report/logistic-stock/skeleton/PurchasePerSupplierSkeleton';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
interface PurchasesPerSupplierTabProps {
|
interface PurchasesPerSupplierTabProps {
|
||||||
tabId: string;
|
tabId: string;
|
||||||
@@ -253,43 +254,6 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.sort_by, sortByOptions]);
|
}, [formik.values.sort_by, sortByOptions]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (filterParams.start_date || filterParams.end_date) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.area_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.supplier_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.product_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.product_category_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.filter_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.sort_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: purchasePerSupplier, isLoading } = useSWR(
|
const { data: purchasePerSupplier, isLoading } = useSWR(
|
||||||
isSubmitted
|
isSubmitted
|
||||||
@@ -486,25 +450,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
|
|||||||
setTabActions(
|
setTabActions(
|
||||||
tabId,
|
tabId,
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={formik.values}
|
||||||
color='none'
|
fieldGroups={[['start_date', 'end_date']]}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -561,8 +513,7 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
hasFilters,
|
formik.values,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
filterModal.open,
|
filterModal.open,
|
||||||
setTabActions,
|
setTabActions,
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import {
|
|||||||
MARKETING_TYPE_OPTIONS,
|
MARKETING_TYPE_OPTIONS,
|
||||||
} from '@/config/constant';
|
} from '@/config/constant';
|
||||||
import Badge from '@/components/Badge';
|
import Badge from '@/components/Badge';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
|
|
||||||
interface DailyMarketingTabProps {
|
interface DailyMarketingTabProps {
|
||||||
tabId: string;
|
tabId: string;
|
||||||
@@ -202,47 +203,6 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.marketing_type]);
|
}, [formik.values.marketing_type]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (filterParams.area_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.location_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.warehouse_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.customer_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.start_date || filterParams.end_date) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.filter_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.marketing_type) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.sort_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: dailyMarketings, isLoading } = useSWR(
|
const { data: dailyMarketings, isLoading } = useSWR(
|
||||||
isSubmitted
|
isSubmitted
|
||||||
@@ -412,30 +372,13 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={formik.values}
|
||||||
color='none'
|
fieldGroups={[['start_date', 'end_date']]}
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<Badge
|
|
||||||
className={{
|
|
||||||
badge:
|
|
||||||
'p-1.5 bg-[#FF3535] text-xs text-base-100 border border-base-300 rounded-lg',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -493,8 +436,7 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
|
|||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
searchValue,
|
searchValue,
|
||||||
hasFilters,
|
formik.values,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
filterModal.open,
|
filterModal.open,
|
||||||
setTabActions,
|
setTabActions,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from '@/types/api/report/hpp-per-kandang';
|
} from '@/types/api/report/hpp-per-kandang';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
import { generateHppPerKandangPDF } from '@/components/pages/report/marketing/export/HppPerkandangExportPDF';
|
import { generateHppPerKandangPDF } from '@/components/pages/report/marketing/export/HppPerkandangExportPDF';
|
||||||
import { generateHppPerKandangExcel } from '@/components/pages/report/marketing/export/HppPerkandangExportXLSX';
|
import { generateHppPerKandangExcel } from '@/components/pages/report/marketing/export/HppPerkandangExportXLSX';
|
||||||
@@ -233,42 +234,6 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [formik.values.show_unrecorded, showUnrecordedOptions]);
|
}, [formik.values.show_unrecorded, showUnrecordedOptions]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (filterParams.period) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.area_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.location_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.kandang_id) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.weight_min || filterParams.weight_max) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.show_unrecorded !== undefined) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterParams.sort_by) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: hppPerKandang, isLoading } = useSWR(
|
const { data: hppPerKandang, isLoading } = useSWR(
|
||||||
@@ -486,25 +451,12 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
|
|||||||
setTabActions(
|
setTabActions(
|
||||||
tabId,
|
tabId,
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={formik.values}
|
||||||
color='none'
|
|
||||||
onClick={handleFilterModalOpen}
|
onClick={handleFilterModalOpen}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -561,8 +513,7 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
hasFilters,
|
formik.values,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
filterModal.open,
|
filterModal.open,
|
||||||
setTabActions,
|
setTabActions,
|
||||||
|
|||||||
+7
-34
@@ -7,6 +7,7 @@ import toast from 'react-hot-toast';
|
|||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
import Dropdown from '@/components/dropdown/Dropdown';
|
import Dropdown from '@/components/dropdown/Dropdown';
|
||||||
import SelectInput, { useSelect } from '@/components/input/SelectInput';
|
import SelectInput, { useSelect } from '@/components/input/SelectInput';
|
||||||
import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/tab/ProductionResultProjectFlockKandangTable';
|
import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/tab/ProductionResultProjectFlockKandangTable';
|
||||||
@@ -324,20 +325,6 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => {
|
|||||||
[formik.values.kandang_id]
|
[formik.values.kandang_id]
|
||||||
);
|
);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
|
||||||
const activeFiltersCount = useMemo(() => {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (filterParams.area_id) count += 1;
|
|
||||||
if (filterParams.location_id) count += 1;
|
|
||||||
if (filterParams.project_flock_id) count += 1;
|
|
||||||
if (filterParams.project_flock_kandang_id) count += 1;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}, [filterParams]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: projectFlockKandangsData, isLoading } = useSWR<
|
const { data: projectFlockKandangsData, isLoading } = useSWR<
|
||||||
BaseApiResponse<ProjectFlockKandang[]>
|
BaseApiResponse<ProjectFlockKandang[]>
|
||||||
@@ -539,25 +526,12 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => {
|
|||||||
setTabActions(
|
setTabActions(
|
||||||
tabId,
|
tabId,
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<Button
|
<ButtonFilter
|
||||||
variant='outline'
|
values={filterParams}
|
||||||
color='none'
|
|
||||||
onClick={() => filterModal.openModal()}
|
onClick={() => filterModal.openModal()}
|
||||||
className={cn(
|
variant='outline'
|
||||||
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
className='px-3 py-2.5'
|
||||||
{
|
/>
|
||||||
'border-primary-gradient text-primary': hasFilters,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
|
||||||
Filter
|
|
||||||
{hasFilters && (
|
|
||||||
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
|
||||||
{activeFiltersCount}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
@@ -614,8 +588,7 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => {
|
|||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
tabId,
|
tabId,
|
||||||
hasFilters,
|
filterParams,
|
||||||
activeFiltersCount,
|
|
||||||
isAnyExportLoading,
|
isAnyExportLoading,
|
||||||
exportToExcelHandler,
|
exportToExcelHandler,
|
||||||
exportToPdfHandler,
|
exportToPdfHandler,
|
||||||
|
|||||||
Reference in New Issue
Block a user