mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'fix/adjustment-param-state-keuangan' into 'development'
[FIX/FE] Adjustment Param State on Fetch Keuangan See merge request mbugroup/lti-web-client!311
This commit is contained in:
@@ -1,13 +1,8 @@
|
||||
import {
|
||||
ChangeEventHandler,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { CellContext } from '@tanstack/react-table';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import useSWR from 'swr';
|
||||
import { useFormik } from 'formik';
|
||||
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
@@ -40,6 +35,10 @@ import { Icon } from '@iconify/react';
|
||||
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
||||
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
||||
import { useUiStore } from '@/stores/ui/ui.store';
|
||||
import {
|
||||
FinanceTableFilterSchema,
|
||||
FinanceTableFilterValues,
|
||||
} from './FinanceTableFilter.schema';
|
||||
|
||||
const RowOptionsMenu = ({
|
||||
type = 'dropdown',
|
||||
@@ -152,10 +151,10 @@ const FinanceTable = () => {
|
||||
} = useTableFilter({
|
||||
initial: {
|
||||
search: searchValue,
|
||||
transactionType: '',
|
||||
bankId: '',
|
||||
customerId: '',
|
||||
supplierId: '',
|
||||
transactionTypes: '',
|
||||
bankIds: '',
|
||||
customerIds: '',
|
||||
supplierIds: '',
|
||||
sortBy: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
@@ -163,10 +162,10 @@ const FinanceTable = () => {
|
||||
paramMap: {
|
||||
page: 'page',
|
||||
pageSize: 'limit',
|
||||
transactionType: 'transaction_type',
|
||||
bankId: 'bank_id',
|
||||
customerId: 'customer_id',
|
||||
supplierId: 'supplier_id',
|
||||
transactionTypes: 'transaction_types',
|
||||
bankIds: 'bank_ids',
|
||||
customerIds: 'customer_ids',
|
||||
supplierIds: 'supplier_ids',
|
||||
sortBy: 'sort_date',
|
||||
startDate: 'start_date',
|
||||
endDate: 'end_date',
|
||||
@@ -174,18 +173,7 @@ const FinanceTable = () => {
|
||||
});
|
||||
|
||||
// ===== State =====
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const deleteModal = useModal();
|
||||
const [pendingFilters, setPendingFilters] = useState({
|
||||
search: searchValue,
|
||||
transactionType: '',
|
||||
bankId: '',
|
||||
customerId: '',
|
||||
supplierId: '',
|
||||
sortBy: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
});
|
||||
const [selectedTransactionType, setSelectedTransactionType] = useState<
|
||||
OptionType | OptionType[] | null
|
||||
>(null);
|
||||
@@ -201,6 +189,34 @@ const FinanceTable = () => {
|
||||
const [selectedSortBy, setSelectedSortBy] = useState<OptionType | null>(null);
|
||||
const [selectedFinance, setSelectedFinance] = useState<Finance | null>(null);
|
||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||
const [dateErrorShown, setDateErrorShown] = useState(false);
|
||||
|
||||
// ===== Formik for Filter =====
|
||||
const filterFormik = useFormik<FinanceTableFilterValues>({
|
||||
initialValues: {
|
||||
search: searchValue,
|
||||
transaction_types: '',
|
||||
bank_ids: '',
|
||||
customer_ids: '',
|
||||
supplier_ids: '',
|
||||
sort_by: '',
|
||||
start_date: '',
|
||||
end_date: '',
|
||||
},
|
||||
validationSchema: FinanceTableFilterSchema,
|
||||
enableReinitialize: true,
|
||||
onSubmit: (values) => {
|
||||
updateFilter('search', values.search);
|
||||
setSearchValue(values.search);
|
||||
updateFilter('transactionTypes', values.transaction_types);
|
||||
updateFilter('bankIds', values.bank_ids);
|
||||
updateFilter('customerIds', values.customer_ids);
|
||||
updateFilter('supplierIds', values.supplier_ids);
|
||||
updateFilter('sortBy', values.sort_by);
|
||||
updateFilter('startDate', values.start_date);
|
||||
updateFilter('endDate', values.end_date);
|
||||
},
|
||||
});
|
||||
|
||||
// ===== Fetch Data =====
|
||||
const {
|
||||
@@ -237,84 +253,141 @@ const FinanceTable = () => {
|
||||
loadMore: bankLoadMore,
|
||||
} = useSelect<Bank>(BankApi.basePath, 'id', 'alias');
|
||||
|
||||
const bankSelectOptions = useMemo(() => {
|
||||
if (!isResponseSuccess(bankRawData)) return [];
|
||||
|
||||
return bankOptions.map((bank) => {
|
||||
const bankData = bankRawData.data.find((data) => data.id === bank?.value);
|
||||
return {
|
||||
label: bankData
|
||||
? `${bankData.alias} - ${bankData.account_number} - ${bankData.owner}`
|
||||
: '',
|
||||
value: bank?.value,
|
||||
};
|
||||
});
|
||||
}, [bankOptions, bankRawData]);
|
||||
|
||||
// ===== Handler =====
|
||||
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
setPendingFilters((prev) => ({ ...prev, search: e.target.value }));
|
||||
const searchChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
filterFormik.setFieldValue('search', e.target.value);
|
||||
};
|
||||
const transactionTypeChangeHandler = (
|
||||
val: OptionType | OptionType[] | null
|
||||
) => {
|
||||
setSelectedTransactionType(val);
|
||||
setPendingFilters((prev) => ({
|
||||
...prev,
|
||||
transactionType: val
|
||||
filterFormik.setFieldValue(
|
||||
'transaction_types',
|
||||
val
|
||||
? Array.isArray(val)
|
||||
? val.map((item) => item.value).join(',')
|
||||
: (val.value as string)
|
||||
: '',
|
||||
}));
|
||||
: ''
|
||||
);
|
||||
};
|
||||
const bankChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
setSelectedBank(val);
|
||||
setPendingFilters((prev) => ({
|
||||
...prev,
|
||||
bankId: val
|
||||
filterFormik.setFieldValue(
|
||||
'bank_ids',
|
||||
val
|
||||
? Array.isArray(val)
|
||||
? val.map((item) => item.value).join(',')
|
||||
: (val.value as string)
|
||||
: '',
|
||||
}));
|
||||
: ''
|
||||
);
|
||||
};
|
||||
const customerIdChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
setSelectedCustomerId(val);
|
||||
setPendingFilters((prev) => ({
|
||||
...prev,
|
||||
customerId: val
|
||||
filterFormik.setFieldValue(
|
||||
'customer_ids',
|
||||
val
|
||||
? Array.isArray(val)
|
||||
? val.map((item) => item.value).join(',')
|
||||
: (val.value as string)
|
||||
: '',
|
||||
}));
|
||||
: ''
|
||||
);
|
||||
};
|
||||
const supplierIdChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
setSelectedSupplierId(val);
|
||||
setPendingFilters((prev) => ({
|
||||
...prev,
|
||||
supplierId: val
|
||||
filterFormik.setFieldValue(
|
||||
'supplier_ids',
|
||||
val
|
||||
? Array.isArray(val)
|
||||
? val.map((item) => item.value).join(',')
|
||||
: (val.value as string)
|
||||
: '',
|
||||
}));
|
||||
: ''
|
||||
);
|
||||
};
|
||||
const sortByChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
setSelectedSortBy(val as OptionType);
|
||||
setPendingFilters((prev) => ({
|
||||
...prev,
|
||||
sortBy: val ? ((val as OptionType).value as string) : '',
|
||||
}));
|
||||
filterFormik.setFieldValue(
|
||||
'sort_by',
|
||||
val ? ((val as OptionType).value as string) : ''
|
||||
);
|
||||
};
|
||||
const startDateChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
setPendingFilters((prev) => ({ ...prev, startDate: e.target.value }));
|
||||
|
||||
const startDateChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
const endDate = filterFormik.values.end_date;
|
||||
|
||||
filterFormik.setFieldValue('start_date', value);
|
||||
|
||||
if (value && endDate) {
|
||||
const startDate = new Date(value);
|
||||
const endDateObj = new Date(endDate);
|
||||
|
||||
if (endDateObj < startDate) {
|
||||
filterFormik.setFieldError(
|
||||
'end_date',
|
||||
'Tanggal akhir tidak boleh masa lampau'
|
||||
);
|
||||
if (!dateErrorShown) {
|
||||
toast.error('Tanggal akhir tidak boleh masa lampau', {
|
||||
duration: Infinity,
|
||||
});
|
||||
setDateErrorShown(true);
|
||||
}
|
||||
} else {
|
||||
filterFormik.setFieldError('end_date', undefined);
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const endDateChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
setPendingFilters((prev) => ({ ...prev, endDate: e.target.value }));
|
||||
};
|
||||
const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
const newVal = val as OptionType;
|
||||
setPageSize(newVal.value as number);
|
||||
};
|
||||
const submitFilterHandler = () => {
|
||||
updateFilter('search', pendingFilters.search);
|
||||
setSearchValue(pendingFilters.search);
|
||||
updateFilter('transactionType', pendingFilters.transactionType);
|
||||
updateFilter('bankId', pendingFilters.bankId);
|
||||
updateFilter('customerId', pendingFilters.customerId);
|
||||
updateFilter('supplierId', pendingFilters.supplierId);
|
||||
updateFilter('sortBy', pendingFilters.sortBy);
|
||||
updateFilter('startDate', pendingFilters.startDate);
|
||||
updateFilter('endDate', pendingFilters.endDate);
|
||||
|
||||
const endDateChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
const startDate = filterFormik.values.start_date;
|
||||
|
||||
filterFormik.setFieldValue('end_date', value);
|
||||
|
||||
if (value && startDate) {
|
||||
const startDateObj = new Date(startDate);
|
||||
const endDate = new Date(value);
|
||||
|
||||
if (endDate < startDateObj) {
|
||||
filterFormik.setFieldError(
|
||||
'end_date',
|
||||
'Tanggal akhir tidak boleh masa lampau'
|
||||
);
|
||||
if (!dateErrorShown) {
|
||||
toast.error('Tanggal akhir tidak boleh masa lampau', {
|
||||
duration: Infinity,
|
||||
});
|
||||
setDateErrorShown(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
filterFormik.setFieldError('end_date', undefined);
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
};
|
||||
|
||||
const resetFilterHandler = () => {
|
||||
setSelectedTransactionType(null);
|
||||
setSelectedBank(null);
|
||||
@@ -322,24 +395,14 @@ const FinanceTable = () => {
|
||||
setSelectedSupplierId(null);
|
||||
setSelectedSortBy(null);
|
||||
|
||||
const emptyFilters = {
|
||||
search: '',
|
||||
transactionType: '',
|
||||
bankId: '',
|
||||
customerId: '',
|
||||
supplierId: '',
|
||||
sortBy: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
};
|
||||
setPendingFilters(emptyFilters);
|
||||
filterFormik.resetForm();
|
||||
|
||||
updateFilter('search', '');
|
||||
resetSearchValue();
|
||||
updateFilter('transactionType', '');
|
||||
updateFilter('bankId', '');
|
||||
updateFilter('customerId', '');
|
||||
updateFilter('supplierId', '');
|
||||
updateFilter('transactionTypes', '');
|
||||
updateFilter('bankIds', '');
|
||||
updateFilter('customerIds', '');
|
||||
updateFilter('supplierIds', '');
|
||||
updateFilter('sortBy', '');
|
||||
updateFilter('startDate', '');
|
||||
updateFilter('endDate', '');
|
||||
@@ -464,26 +527,36 @@ const FinanceTable = () => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Store current path on mount
|
||||
return () => {
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
}
|
||||
};
|
||||
}, [dateErrorShown]);
|
||||
|
||||
useEffect(() => {
|
||||
previousPathRef.current = window.location.pathname;
|
||||
|
||||
return () => {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// if both paths are within /finance module
|
||||
const isCurrentPathFinance = currentPath.includes('/finance');
|
||||
const isPreviousPathFinance =
|
||||
previousPathRef.current?.includes('/finance');
|
||||
|
||||
// reset if we outside finance module entirely
|
||||
if (isPreviousPathFinance && !isCurrentPathFinance) {
|
||||
resetSearchValue();
|
||||
}
|
||||
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
};
|
||||
}, [resetSearchValue]);
|
||||
}, [resetSearchValue, dateErrorShown]);
|
||||
|
||||
return (
|
||||
<section className='size-full p-6 flex flex-col gap-6'>
|
||||
<section className='size-full flex flex-col gap-6'>
|
||||
<div className='flex justify-end gap-2'>
|
||||
<RequirePermission permissions='lti.finance.injections.create'>
|
||||
<Button
|
||||
@@ -526,7 +599,7 @@ const FinanceTable = () => {
|
||||
<Button
|
||||
color='primary'
|
||||
className='min-w-24'
|
||||
onClick={submitFilterHandler}
|
||||
onClick={() => filterFormik.handleSubmit()}
|
||||
>
|
||||
Cari
|
||||
</Button>
|
||||
@@ -539,6 +612,7 @@ const FinanceTable = () => {
|
||||
label='Jenis Transaksi'
|
||||
value={selectedTransactionType}
|
||||
onChange={transactionTypeChangeHandler}
|
||||
closeMenuOnSelect={false}
|
||||
isClearable
|
||||
isMulti
|
||||
/>
|
||||
@@ -550,6 +624,7 @@ const FinanceTable = () => {
|
||||
onInputChange={customerInputValue}
|
||||
onMenuScrollToBottom={customerLoadMore}
|
||||
isLoading={customerIsLoadingOptions}
|
||||
closeMenuOnSelect={false}
|
||||
isClearable
|
||||
isMulti
|
||||
/>
|
||||
@@ -561,31 +636,18 @@ const FinanceTable = () => {
|
||||
onInputChange={supplierInputValue}
|
||||
onMenuScrollToBottom={supplierLoadMore}
|
||||
isLoading={supplierIsLoadingOptions}
|
||||
closeMenuOnSelect={false}
|
||||
isClearable
|
||||
isMulti
|
||||
/>
|
||||
<SelectInput
|
||||
options={
|
||||
isResponseSuccess(bankRawData)
|
||||
? bankOptions.map((bank) => ({
|
||||
label:
|
||||
bankRawData.data.find((data) => data.id === bank?.value)
|
||||
?.alias +
|
||||
' - ' +
|
||||
bankRawData.data.find((data) => data.id === bank?.value)
|
||||
?.account_number +
|
||||
' - ' +
|
||||
bankRawData.data.find((data) => data.id === bank?.value)
|
||||
?.owner,
|
||||
value: bank?.value,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
options={bankSelectOptions}
|
||||
label='Bank'
|
||||
value={selectedBank}
|
||||
onChange={bankChangeHandler}
|
||||
onInputChange={bankInputValue}
|
||||
onMenuScrollToBottom={bankLoadMore}
|
||||
closeMenuOnSelect={false}
|
||||
isClearable
|
||||
isMulti
|
||||
/>
|
||||
@@ -597,22 +659,32 @@ const FinanceTable = () => {
|
||||
isClearable
|
||||
/>
|
||||
<DateInput
|
||||
name='startDate'
|
||||
name='start_date'
|
||||
label='Periode Tanggal (Mulai)'
|
||||
value={pendingFilters.startDate}
|
||||
value={filterFormik.values.start_date}
|
||||
onChange={startDateChangeHandler}
|
||||
errorMessage={
|
||||
filterFormik.errors.end_date
|
||||
? filterFormik.errors.end_date
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<DateInput
|
||||
name='endDate'
|
||||
name='end_date'
|
||||
label='Periode Tanggal (Akhir)'
|
||||
value={pendingFilters.endDate}
|
||||
value={filterFormik.values.end_date}
|
||||
onChange={endDateChangeHandler}
|
||||
errorMessage={
|
||||
filterFormik.errors.end_date
|
||||
? filterFormik.errors.end_date
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<DebouncedTextInput
|
||||
name='search'
|
||||
label='Cari'
|
||||
placeholder='Cari'
|
||||
value={pendingFilters.search}
|
||||
value={filterFormik.values.search}
|
||||
onChange={searchChangeHandler}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as yup from 'yup';
|
||||
|
||||
export type FinanceTableFilterType = {
|
||||
search: string;
|
||||
transaction_types: string;
|
||||
bank_ids: string;
|
||||
customer_ids: string;
|
||||
supplier_ids: string;
|
||||
sort_by: string;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
};
|
||||
|
||||
export const FinanceTableFilterSchema = yup.object({
|
||||
search: yup.string().optional(),
|
||||
transaction_types: yup.string().optional(),
|
||||
bank_ids: yup.string().optional(),
|
||||
customer_ids: yup.string().optional(),
|
||||
supplier_ids: yup.string().optional(),
|
||||
sort_by: yup.string().optional(),
|
||||
start_date: yup.string().optional(),
|
||||
end_date: yup
|
||||
.string()
|
||||
.optional()
|
||||
.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);
|
||||
}
|
||||
),
|
||||
}) as yup.ObjectSchema<FinanceTableFilterType>;
|
||||
|
||||
export type FinanceTableFilterValues = yup.InferType<
|
||||
typeof FinanceTableFilterSchema
|
||||
>;
|
||||
Reference in New Issue
Block a user