mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE): Refactor CustomerPaymentTab to use Formik for filter
management
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
|
export type CustomerPaymentFilterType = {
|
||||||
|
start_date: string | null;
|
||||||
|
end_date: string | null;
|
||||||
|
customer_ids: string | null;
|
||||||
|
filter_by: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CustomerPaymentFilterSchema = yup.object({
|
||||||
|
start_date: yup.string().optional().nullable(),
|
||||||
|
end_date: yup
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.nullable()
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
customer_ids: yup.string().nullable(),
|
||||||
|
filter_by: yup.string().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type CustomerPaymentFilterValues = yup.InferType<
|
||||||
|
typeof CustomerPaymentFilterSchema
|
||||||
|
>;
|
||||||
@@ -9,7 +9,6 @@ import SelectInputRadio from '@/components/input/SelectInputRadio';
|
|||||||
import DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
import { CustomerApi } from '@/services/api/master-data';
|
import { CustomerApi } from '@/services/api/master-data';
|
||||||
import { FinanceApi } from '@/services/api/report/finance-report';
|
import { FinanceApi } from '@/services/api/report/finance-report';
|
||||||
// import { UserApi } from '@/services/api/user';
|
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { formatCurrency, formatDate, formatNumber, cn } from '@/lib/helper';
|
import { formatCurrency, formatDate, formatNumber, cn } from '@/lib/helper';
|
||||||
@@ -22,18 +21,30 @@ import Button from '@/components/Button';
|
|||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
import MenuItem from '@/components/menu/MenuItem';
|
import MenuItem from '@/components/menu/MenuItem';
|
||||||
import Menu from '@/components/menu/Menu';
|
import Menu from '@/components/menu/Menu';
|
||||||
import Modal from '@/components/Modal';
|
import Modal, { useModal } from '@/components/Modal';
|
||||||
import { useModal } from '@/components/Modal';
|
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
|
import { useFormik } from 'formik';
|
||||||
|
import {
|
||||||
|
CustomerPaymentFilterSchema,
|
||||||
|
CustomerPaymentFilterType,
|
||||||
|
} from '@/components/pages/report/finance/filter/CustomerPaymentFilter';
|
||||||
import { generateCustomerPaymentExcel } from '@/components/pages/report/finance/export/CustomerPaymentExportXLSX';
|
import { generateCustomerPaymentExcel } from '@/components/pages/report/finance/export/CustomerPaymentExportXLSX';
|
||||||
import { generateCustomerPaymentPDF } from '@/components/pages/report/finance/export/CustomerPaymentExportPDF';
|
import { generateCustomerPaymentPDF } from '@/components/pages/report/finance/export/CustomerPaymentExportPDF';
|
||||||
import { useFinanceTabStore } from '@/stores/finance-tab/finance-tab.store';
|
import { useFinanceTabStore } from '@/stores/finance-tab/finance-tab.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';
|
||||||
|
|
||||||
interface CustomerPaymentTabProps {
|
interface CustomerPaymentTabProps {
|
||||||
tabId: string;
|
tabId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FilterParams {
|
||||||
|
customer_ids?: string;
|
||||||
|
start_date?: string;
|
||||||
|
end_date?: string;
|
||||||
|
filter_by?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
||||||
// ===== STATE MANAGEMENT =====
|
// ===== STATE MANAGEMENT =====
|
||||||
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
|
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
|
||||||
@@ -46,31 +57,10 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
|
|
||||||
// ===== SUBMISSION STATE =====
|
// ===== SUBMISSION STATE =====
|
||||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||||
|
const [filterParams, setFilterParams] = useState<FilterParams>({});
|
||||||
// ===== FILTER STATE =====
|
|
||||||
const [appliedFilterCustomer, setAppliedFilterCustomer] = useState<
|
|
||||||
typeof customerOptions
|
|
||||||
>([]);
|
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// const [appliedFilterSales, setAppliedFilterSales] = useState<
|
|
||||||
// typeof salesOptions
|
|
||||||
// >([]);
|
|
||||||
const [appliedFilterByType, setAppliedFilterByType] = useState<
|
|
||||||
(typeof dataTypeOptions)[0] | null
|
|
||||||
>(null);
|
|
||||||
const [appliedFilterStartDate, setAppliedFilterStartDate] = useState('');
|
|
||||||
const [appliedFilterEndDate, setAppliedFilterEndDate] = useState('');
|
|
||||||
const [dateErrorShown, setDateErrorShown] = useState(false);
|
const [dateErrorShown, setDateErrorShown] = useState(false);
|
||||||
const [hasDateError, setHasDateError] = useState(false);
|
const [hasDateError, setHasDateError] = useState(false);
|
||||||
|
|
||||||
const [filterCustomer, setFilterCustomer] = useState<typeof customerOptions>(
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// const [filterSales, setFilterSales] = useState<typeof salesOptions>([]);
|
|
||||||
const [filterStartDate, setFilterStartDate] = useState('');
|
|
||||||
const [filterEndDate, setFilterEndDate] = useState('');
|
|
||||||
|
|
||||||
const filterModal = useModal();
|
const filterModal = useModal();
|
||||||
|
|
||||||
const dataTypeOptions = useMemo(
|
const dataTypeOptions = useMemo(
|
||||||
@@ -81,10 +71,6 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [filterByType, setFilterByType] = useState<
|
|
||||||
(typeof dataTypeOptions)[0] | null
|
|
||||||
>(null);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
options: customerOptions,
|
options: customerOptions,
|
||||||
setInputValue: setCustomerInputValue,
|
setInputValue: setCustomerInputValue,
|
||||||
@@ -92,14 +78,43 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
loadMore: loadMoreCustomers,
|
loadMore: loadMoreCustomers,
|
||||||
} = useSelect(CustomerApi.basePath, 'id', 'name', 'search');
|
} = useSelect(CustomerApi.basePath, 'id', 'name', 'search');
|
||||||
|
|
||||||
// TODO: Uncomment when BE is ready
|
const handleFilterModalOpen = () => {
|
||||||
// const {
|
filterModal.openModal();
|
||||||
// options: salesOptions,
|
formik.validateForm();
|
||||||
// setInputValue: setSalesInputValue,
|
};
|
||||||
// isLoadingOptions: isLoadingSales,
|
|
||||||
// loadMore: loadMoreSales,
|
// ===== FORMIK SETUP =====
|
||||||
// hasMore: hasMoreSales,
|
const formik = useFormik<CustomerPaymentFilterType>({
|
||||||
// } = useSelect(UserApi.basePath, 'id', 'name', 'search');
|
initialValues: {
|
||||||
|
start_date: null,
|
||||||
|
end_date: null,
|
||||||
|
customer_ids: null,
|
||||||
|
filter_by: null,
|
||||||
|
},
|
||||||
|
validationSchema: CustomerPaymentFilterSchema,
|
||||||
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
|
setFilterParams({
|
||||||
|
start_date: values.start_date || undefined,
|
||||||
|
end_date: values.end_date || undefined,
|
||||||
|
customer_ids: values.customer_ids || undefined,
|
||||||
|
filter_by: values.filter_by || undefined,
|
||||||
|
});
|
||||||
|
filterModal.closeModal();
|
||||||
|
setIsSubmitted(true);
|
||||||
|
setCurrentPage(1);
|
||||||
|
setSubmitting(false);
|
||||||
|
},
|
||||||
|
onReset: () => {
|
||||||
|
setFilterParams({});
|
||||||
|
setIsSubmitted(false);
|
||||||
|
setCurrentPage(1);
|
||||||
|
setHasDateError(false);
|
||||||
|
if (dateErrorShown) {
|
||||||
|
toast.dismiss();
|
||||||
|
setDateErrorShown(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const getPaymentStatusColor = (notes: string) => {
|
const getPaymentStatusColor = (notes: string) => {
|
||||||
const normalizedValue = notes.toLowerCase();
|
const normalizedValue = notes.toLowerCase();
|
||||||
@@ -137,63 +152,15 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
.join(' ');
|
.join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== FILTER HANDLERS =====
|
// ===== DATE CHANGE HANDLERS =====
|
||||||
const handleFilterModalOpen = useCallback(() => {
|
|
||||||
setFilterCustomer(appliedFilterCustomer);
|
|
||||||
// setFilterSales(appliedFilterSales);
|
|
||||||
setFilterByType(appliedFilterByType);
|
|
||||||
setFilterStartDate(appliedFilterStartDate);
|
|
||||||
setFilterEndDate(appliedFilterEndDate);
|
|
||||||
filterModal.openModal();
|
|
||||||
}, [
|
|
||||||
filterModal,
|
|
||||||
appliedFilterCustomer,
|
|
||||||
appliedFilterByType,
|
|
||||||
appliedFilterStartDate,
|
|
||||||
appliedFilterEndDate,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const handleResetFilters = useCallback(() => {
|
|
||||||
setIsSubmitted(false);
|
|
||||||
setFilterCustomer([]);
|
|
||||||
setFilterByType(null);
|
|
||||||
setFilterStartDate('');
|
|
||||||
setFilterEndDate('');
|
|
||||||
setAppliedFilterCustomer([]);
|
|
||||||
setAppliedFilterByType(null);
|
|
||||||
setAppliedFilterStartDate('');
|
|
||||||
setAppliedFilterEndDate('');
|
|
||||||
setHasDateError(false);
|
|
||||||
if (dateErrorShown) {
|
|
||||||
toast.dismiss();
|
|
||||||
setDateErrorShown(false);
|
|
||||||
}
|
|
||||||
}, [dateErrorShown]);
|
|
||||||
|
|
||||||
const handleApplyFilters = useCallback(() => {
|
|
||||||
setAppliedFilterCustomer(filterCustomer);
|
|
||||||
setAppliedFilterByType(filterByType);
|
|
||||||
setAppliedFilterStartDate(filterStartDate);
|
|
||||||
setAppliedFilterEndDate(filterEndDate);
|
|
||||||
setIsSubmitted(true);
|
|
||||||
setCurrentPage(1);
|
|
||||||
filterModal.closeModal();
|
|
||||||
}, [
|
|
||||||
filterModal,
|
|
||||||
filterCustomer,
|
|
||||||
filterByType,
|
|
||||||
filterStartDate,
|
|
||||||
filterEndDate,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const handleStartDateChange = useCallback(
|
const handleStartDateChange = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setFilterStartDate(value);
|
formik.setFieldValue('start_date', value || null);
|
||||||
|
|
||||||
if (value && filterEndDate) {
|
if (value && formik.values.end_date) {
|
||||||
const startDate = new Date(value);
|
const startDate = new Date(value);
|
||||||
const endDateObj = new Date(filterEndDate);
|
const endDateObj = new Date(formik.values.end_date);
|
||||||
|
|
||||||
if (endDateObj < startDate) {
|
if (endDateObj < startDate) {
|
||||||
setHasDateError(true);
|
setHasDateError(true);
|
||||||
@@ -214,16 +181,16 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
setHasDateError(false);
|
setHasDateError(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[filterEndDate, dateErrorShown]
|
[formik, dateErrorShown]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleEndDateChange = useCallback(
|
const handleEndDateChange = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setFilterEndDate(value);
|
formik.setFieldValue('end_date', value || null);
|
||||||
|
|
||||||
if (value && filterStartDate) {
|
if (value && formik.values.start_date) {
|
||||||
const startDateObj = new Date(filterStartDate);
|
const startDateObj = new Date(formik.values.start_date);
|
||||||
const endDate = new Date(value);
|
const endDate = new Date(value);
|
||||||
|
|
||||||
if (endDate < startDateObj) {
|
if (endDate < startDateObj) {
|
||||||
@@ -244,41 +211,46 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
setDateErrorShown(false);
|
setDateErrorShown(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[filterStartDate, dateErrorShown]
|
[formik, dateErrorShown]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== FILTER HELPERS =====
|
||||||
|
const customerIdsValue = useMemo(() => {
|
||||||
|
if (!formik.values.customer_ids) return [];
|
||||||
|
return customerOptions.filter((opt) =>
|
||||||
|
formik.values.customer_ids?.split(',').includes(String(opt.value))
|
||||||
|
);
|
||||||
|
}, [formik.values.customer_ids, customerOptions]);
|
||||||
|
|
||||||
|
const filterByValue = useMemo(() => {
|
||||||
|
if (!formik.values.filter_by) return null;
|
||||||
|
return (
|
||||||
|
dataTypeOptions.find((opt) => opt.value === formik.values.filter_by) ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}, [formik.values.filter_by]);
|
||||||
|
|
||||||
// ===== ACTIVE FILTERS COUNT =====
|
// ===== ACTIVE FILTERS COUNT =====
|
||||||
const activeFiltersCount = useMemo(() => {
|
const activeFiltersCount = useMemo(() => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
// Date filter (start_date + end_date = 1 filter)
|
// Date filter (start_date + end_date = 1 filter)
|
||||||
if (appliedFilterStartDate || appliedFilterEndDate) {
|
if (filterParams.start_date || filterParams.end_date) {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Customer filter
|
// Customer filter
|
||||||
if (appliedFilterCustomer.length > 0) {
|
if (filterParams.customer_ids) {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by type filter (hanya dihitung jika ada nilai yang dipilih)
|
// Filter by type filter (hanya dihitung jika ada nilai yang dipilih)
|
||||||
if (appliedFilterByType) {
|
if (filterParams.filter_by) {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// // Sales filter
|
|
||||||
// if (appliedFilterSales.length > 0) {
|
|
||||||
// count += 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}, [
|
}, [filterParams]);
|
||||||
appliedFilterStartDate,
|
|
||||||
appliedFilterEndDate,
|
|
||||||
appliedFilterCustomer,
|
|
||||||
appliedFilterByType,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const hasFilters = activeFiltersCount > 0;
|
const hasFilters = activeFiltersCount > 0;
|
||||||
|
|
||||||
@@ -287,21 +259,13 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
isSubmitted
|
isSubmitted
|
||||||
? () => {
|
? () => {
|
||||||
const params = {
|
const params = {
|
||||||
customer_ids:
|
customer_ids: filterParams.customer_ids,
|
||||||
appliedFilterCustomer.length > 0
|
filter_by: filterParams.filter_by as
|
||||||
? appliedFilterCustomer.map((v) => String(v.value)).join(',')
|
|
||||||
: undefined,
|
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// sales_id:
|
|
||||||
// appliedFilterSales.length > 0
|
|
||||||
// ? appliedFilterSales.map((v) => String(v.value)).join(',')
|
|
||||||
// : undefined,
|
|
||||||
filter_by: appliedFilterByType?.value as
|
|
||||||
| 'trans_date'
|
| 'trans_date'
|
||||||
| 'realization_date'
|
| 'realization_date'
|
||||||
| undefined,
|
| undefined,
|
||||||
start_date: appliedFilterStartDate || undefined,
|
start_date: filterParams.start_date,
|
||||||
end_date: appliedFilterEndDate || undefined,
|
end_date: filterParams.end_date,
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
};
|
};
|
||||||
@@ -333,21 +297,13 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
CustomerPaymentReport[] | null
|
CustomerPaymentReport[] | null
|
||||||
> => {
|
> => {
|
||||||
const params = {
|
const params = {
|
||||||
customer_ids:
|
customer_ids: filterParams.customer_ids,
|
||||||
appliedFilterCustomer.length > 0
|
filter_by: filterParams.filter_by as
|
||||||
? appliedFilterCustomer.map((v) => String(v.value)).join(',')
|
|
||||||
: undefined,
|
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// sales_id:
|
|
||||||
// appliedFilterSales.length > 0
|
|
||||||
// ? appliedFilterSales.map((v) => String(v.value)).join(',')
|
|
||||||
// : undefined,
|
|
||||||
filter_by: appliedFilterByType?.value as
|
|
||||||
| 'trans_date'
|
| 'trans_date'
|
||||||
| 'realization_date'
|
| 'realization_date'
|
||||||
| undefined,
|
| undefined,
|
||||||
start_date: appliedFilterStartDate || undefined,
|
start_date: filterParams.start_date,
|
||||||
end_date: appliedFilterEndDate || undefined,
|
end_date: filterParams.end_date,
|
||||||
limit: 100,
|
limit: 100,
|
||||||
page: 1,
|
page: 1,
|
||||||
};
|
};
|
||||||
@@ -364,13 +320,7 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
return isResponseSuccess(response)
|
return isResponseSuccess(response)
|
||||||
? (response.data as unknown as CustomerPaymentReport[])
|
? (response.data as unknown as CustomerPaymentReport[])
|
||||||
: null;
|
: null;
|
||||||
}, [
|
}, [filterParams]);
|
||||||
appliedFilterCustomer,
|
|
||||||
// appliedFilterSales,
|
|
||||||
appliedFilterStartDate,
|
|
||||||
appliedFilterEndDate,
|
|
||||||
appliedFilterByType,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// ===== EXPORT HANDLERS =====
|
// ===== EXPORT HANDLERS =====
|
||||||
const handleExportExcel = useCallback(async () => {
|
const handleExportExcel = useCallback(async () => {
|
||||||
@@ -410,21 +360,22 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customerName = filterParams.customer_ids
|
||||||
|
? customerOptions
|
||||||
|
.filter((opt) =>
|
||||||
|
filterParams.customer_ids?.split(',').includes(String(opt.value))
|
||||||
|
)
|
||||||
|
.map((opt) => opt.label)
|
||||||
|
.join(', ') || 'Semua Customer'
|
||||||
|
: 'Semua Customer';
|
||||||
|
|
||||||
await generateCustomerPaymentPDF({
|
await generateCustomerPaymentPDF({
|
||||||
data: allDataForExport,
|
data: allDataForExport,
|
||||||
params: {
|
params: {
|
||||||
customer_name:
|
customer_name: customerName,
|
||||||
appliedFilterCustomer.length > 0
|
start_date: filterParams.start_date,
|
||||||
? appliedFilterCustomer.map((c) => c.label).join(', ')
|
end_date: filterParams.end_date,
|
||||||
: undefined,
|
filter_by: filterParams.filter_by as
|
||||||
// TODO: Uncomment when BE is ready
|
|
||||||
// sales:
|
|
||||||
// appliedFilterSales.length > 0
|
|
||||||
// ? appliedFilterSales.map((s) => s.label).join(', ')
|
|
||||||
// : undefined,
|
|
||||||
start_date: appliedFilterStartDate || undefined,
|
|
||||||
end_date: appliedFilterEndDate || undefined,
|
|
||||||
filter_by: appliedFilterByType?.value as
|
|
||||||
| 'trans_date'
|
| 'trans_date'
|
||||||
| 'realization_date'
|
| 'realization_date'
|
||||||
| undefined,
|
| undefined,
|
||||||
@@ -436,7 +387,7 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsPdfExportLoading(false);
|
setIsPdfExportLoading(false);
|
||||||
}
|
}
|
||||||
}, [customerPaymentExport]);
|
}, [customerPaymentExport, filterParams, customerOptions]);
|
||||||
|
|
||||||
// ===== REGISTER TAB ACTIONS TO STORE =====
|
// ===== REGISTER TAB ACTIONS TO STORE =====
|
||||||
const setTabActions = useFinanceTabStore((state) => state.setTabActions);
|
const setTabActions = useFinanceTabStore((state) => state.setTabActions);
|
||||||
@@ -517,7 +468,6 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
setTabActions,
|
setTabActions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Cleanup on unmount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
clearTabActions(tabId);
|
clearTabActions(tabId);
|
||||||
@@ -931,95 +881,86 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
|
|||||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='p-4 flex flex-col gap-1.5'>
|
<form onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
|
||||||
<div>
|
<div className='p-4 flex flex-col gap-1.5'>
|
||||||
<label className='block text-xs font-semibold text-base-content py-2'>
|
<div>
|
||||||
Tanggal
|
<label className='block text-xs font-semibold text-base-content py-2'>
|
||||||
</label>
|
Tanggal
|
||||||
<div className='flex flex-row gap-1.5 items-center justify-between'>
|
</label>
|
||||||
<DateInput
|
<div className='flex flex-row gap-1.5 items-center justify-between'>
|
||||||
name='start_date'
|
<DateInput
|
||||||
value={filterStartDate}
|
name='start_date'
|
||||||
onChange={handleStartDateChange}
|
value={formik.values.start_date || ''}
|
||||||
className={{ wrapper: 'w-full' }}
|
onChange={handleStartDateChange}
|
||||||
isNestedModal
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
isNestedModal
|
||||||
<hr className='w-full max-w-3 h-px border-base-content/10' />
|
/>
|
||||||
|
<hr className='w-full max-w-3 h-px border-base-content/10' />
|
||||||
|
|
||||||
<DateInput
|
<DateInput
|
||||||
name='end_date'
|
name='end_date'
|
||||||
value={filterEndDate}
|
value={formik.values.end_date || ''}
|
||||||
onChange={handleEndDateChange}
|
onChange={handleEndDateChange}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
isNestedModal
|
isNestedModal
|
||||||
/>
|
isError={hasDateError}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<SelectInputCheckbox
|
||||||
|
label='Customer'
|
||||||
|
placeholder='Pilih Customer'
|
||||||
|
options={customerOptions}
|
||||||
|
value={customerIdsValue}
|
||||||
|
onChange={(val) => {
|
||||||
|
formik.setFieldValue(
|
||||||
|
'customer_ids',
|
||||||
|
Array.isArray(val) && val.length > 0
|
||||||
|
? val.map((v: OptionType) => String(v.value)).join(',')
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onInputChange={setCustomerInputValue}
|
||||||
|
isLoading={isLoadingCustomers}
|
||||||
|
isClearable
|
||||||
|
onMenuScrollToBottom={loadMoreCustomers}
|
||||||
|
className={{ wrapper: 'w-full' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectInputRadio
|
||||||
|
label='Filter Berdasarkan'
|
||||||
|
placeholder='Pilih Filter Berdasarkan'
|
||||||
|
options={dataTypeOptions}
|
||||||
|
value={filterByValue}
|
||||||
|
onChange={(val) => {
|
||||||
|
if (!Array.isArray(val)) {
|
||||||
|
formik.setFieldValue('filter_by', val?.value || null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={{ wrapper: 'w-full' }}
|
||||||
|
isClearable={true}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SelectInputCheckbox
|
{/* Modal Footer */}
|
||||||
label='Customer'
|
<div className='flex justify-between items-center gap-4 p-4 border-t border-base-content/10 bg-gray-50'>
|
||||||
placeholder='Pilih Customer'
|
<Button
|
||||||
options={customerOptions}
|
type='reset'
|
||||||
value={filterCustomer}
|
variant='soft'
|
||||||
onChange={(val) => {
|
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
|
||||||
setFilterCustomer(Array.isArray(val) ? val : val ? [val] : []);
|
>
|
||||||
}}
|
Reset Filter
|
||||||
onInputChange={setCustomerInputValue}
|
</Button>
|
||||||
isLoading={isLoadingCustomers}
|
<Button
|
||||||
isClearable
|
type='submit'
|
||||||
onMenuScrollToBottom={loadMoreCustomers}
|
className='min-w-40 text-sm rounded-lg py-3 text-white font-semibold'
|
||||||
className={{ wrapper: 'w-full' }}
|
disabled={hasDateError || !formik.isValid || formik.isSubmitting}
|
||||||
/>
|
>
|
||||||
|
Apply Filter
|
||||||
{/* TODO: Uncomment when BE is ready */}
|
</Button>
|
||||||
{/* <div>
|
</div>
|
||||||
<SelectInputCheckbox
|
</form>
|
||||||
label='Sales'
|
|
||||||
placeholder='Pilih Sales'
|
|
||||||
options={salesOptions}
|
|
||||||
value={filterSales}
|
|
||||||
onChange={(val) => {
|
|
||||||
setFilterSales(Array.isArray(val) ? val : val ? [val] : []);
|
|
||||||
}}
|
|
||||||
onInputChange={setSalesInputValue}
|
|
||||||
isLoading={isLoadingSales}
|
|
||||||
isClearable
|
|
||||||
onMenuScrollToBottom={loadMoreSales}
|
|
||||||
className={{ wrapper: 'w-full' }}
|
|
||||||
/>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
<SelectInputRadio
|
|
||||||
label='Filter Berdasarkan'
|
|
||||||
placeholder='Pilih Filter Berdasarkan'
|
|
||||||
options={dataTypeOptions}
|
|
||||||
value={filterByType}
|
|
||||||
onChange={(val) => {
|
|
||||||
if (val && !Array.isArray(val)) {
|
|
||||||
setFilterByType(val);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className={{ wrapper: 'w-full' }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Action Buttons */}
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-between items-center gap-4 p-4 border-t border-base-content/10 bg-gray-50'>
|
|
||||||
<Button
|
|
||||||
variant='soft'
|
|
||||||
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
|
|
||||||
onClick={handleResetFilters}
|
|
||||||
>
|
|
||||||
Reset Filter
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className='min-w-40 text-sm rounded-lg py-3 text-white font-semibold'
|
|
||||||
onClick={handleApplyFilters}
|
|
||||||
disabled={hasDateError}
|
|
||||||
>
|
|
||||||
Apply Filter
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user