trying fixing filter history transaction

This commit is contained in:
bagusajisaputroo
2025-07-14 13:45:01 +07:00
parent d9b0dc7d85
commit 9df149ee1a
2 changed files with 116 additions and 97 deletions

View File

@ -8,7 +8,7 @@ import {
SelectContent, SelectContent,
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue
} from '@/components/ui/select'; } from '@/components/ui/select';
import { apiConfig } from '@/config/api.config'; import { apiConfig } from '@/config/api.config';
import { useCallApi } from '@/hooks'; import { useCallApi } from '@/hooks';
@ -20,11 +20,11 @@ const ListToolbar = () => {
const [searchValue, setSearchValue] = useState<string>(''); const [searchValue, setSearchValue] = useState<string>('');
const [typeSearchValue, setSearchTypeValue] = useState<string>(''); const [typeSearchValue, setSearchTypeValue] = useState<string>('');
const [typeValue, setTypeValue] = useState<string>( const [typeValue, setTypeValue] = useState<string>(
(table.getState().columnFilters.find(f => f.id === 'kind')?.value as string) ?? '' (table.getState().columnFilters.find((f) => f.id === 'kind')?.value as string) ?? ''
); );
const [status, setStatus] = useState<string>( const [status, setStatus] = useState<string>(
(table.getState().columnFilters.find(f => f.id === 'status')?.value as string) ?? '' (table.getState().columnFilters.find((f) => f.id === 'status')?.value as string) ?? ''
); );
const { GetData } = useCallApi(); const { GetData } = useCallApi();
@ -54,7 +54,9 @@ const ListToolbar = () => {
table.getColumn('transaction_date')?.setFilterValue(trxDate); table.getColumn('transaction_date')?.setFilterValue(trxDate);
table.setColumnFilters((prev) => { table.setColumnFilters((prev) => {
const others = prev.filter(f => f.id !== 'kind' && f.id !== 'searchtype' && f.id !== 'code' && f.id !== 'status'); const others = prev.filter(
(f) => f.id !== 'kind' && f.id !== 'searchtype' && f.id !== 'code' && f.id !== 'status'
);
const filters: any[] = [...others]; const filters: any[] = [...others];
if (typeValue) filters.push({ id: 'kind', value: typeValue }); if (typeValue) filters.push({ id: 'kind', value: typeValue });
@ -75,38 +77,45 @@ const ListToolbar = () => {
status: string status: string
) => { ) => {
try { try {
const formattedFilter: any = { const formattedFilter: any = {};
"Transactions.transaction_date": {
from: `${trxDate.from} 00:00:00`,
to: `${trxDate.to} 23:59:59`,
},
};
if (typeSearchValue === 'msisdn') { // Tambahkan filter tanggal (selalu ada)
formattedFilter['Transactions.origin_msisdn'] = searchValue; if (trxDate.from && trxDate.to) {
} else if (typeSearchValue === 'fullname') { formattedFilter['Transactions.transaction_date'] = {
formattedFilter['Transactions.origin_name'] = searchValue; from: `${trxDate.from} 00:00:00`,
} else if (typeSearchValue === 'trxid') { to: `${trxDate.to} 23:59:59`
formattedFilter['Transactions.code'] = searchValue; };
} }
// Tambahkan filter berdasarkan searchType (sama seperti di search)
if (typeSearchValue && searchValue) {
if (typeSearchValue === 'msisdn') {
formattedFilter['origin_customer.msisdn'] = { like: `%${searchValue}%` };
} else if (typeSearchValue === 'fullname') {
formattedFilter['origin_customer.fullname'] = { like: `%${searchValue}%` };
} else if (typeSearchValue === 'trxid') {
formattedFilter['Transactions.code'] = { like: `%${searchValue}%` };
}
}
// Tambahkan filter jenis transaksi jika ada
if (typeValue) { if (typeValue) {
formattedFilter['Transactions.kind'] = typeValue; formattedFilter['Transactions.kind'] = typeValue;
} }
// Tambahkan filter status jika ada
if (status) {
formattedFilter['Transactions.status'] = status; formattedFilter['Transactions.status'] = status;
}
const filterParam = encodeURIComponent(JSON.stringify(formattedFilter)); const filterParam = encodeURIComponent(JSON.stringify(formattedFilter));
const response = await fetch( const response = await fetch(`${API_URL}/transaction/export?filter=${filterParam}`, {
`${API_URL}/transaction/export?filter=${filterParam}`,
{
method: 'GET', method: 'GET',
headers: { headers: {
Authorization: `Bearer ${getAuth()?.access_token}`, Authorization: `Bearer ${getAuth()?.access_token}`
},
} }
); });
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch file'); throw new Error('Failed to fetch file');
@ -133,9 +142,7 @@ const ListToolbar = () => {
<input <input
type="date" type="date"
value={trxDate.from} value={trxDate.from}
onChange={(event) => onChange={(event) => settrxDate({ ...trxDate, from: event.target.value })}
settrxDate({ ...trxDate, from: event.target.value })
}
name="from" name="from"
/> />
</label> </label>
@ -145,9 +152,7 @@ const ListToolbar = () => {
<input <input
type="date" type="date"
value={trxDate.to} value={trxDate.to}
onChange={(event) => onChange={(event) => settrxDate({ ...trxDate, to: event.target.value })}
settrxDate({ ...trxDate, to: event.target.value })
}
name="to" name="to"
/> />
</label> </label>

View File

@ -36,11 +36,11 @@ interface ContextProps {
const initialProps: ContextProps = { const initialProps: ContextProps = {
getTransactionLists: async () => ({ data: [], totalCount: 0 }), getTransactionLists: async () => ({ data: [], totalCount: 0 }),
showDetailDialog: false, showDetailDialog: false,
setShowDetailDialog: () => { }, setShowDetailDialog: () => {},
showRollbackDialog: false, showRollbackDialog: false,
setShowRollbackDialog: () => { }, setShowRollbackDialog: () => {},
selectedTransactionId: null, selectedTransactionId: null,
setSelectedTransactionId: () => { } setSelectedTransactionId: () => {}
}; };
const ManageTransactionContext = createContext<ContextProps>(initialProps); const ManageTransactionContext = createContext<ContextProps>(initialProps);
@ -58,7 +58,6 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
const url = navigate(`${API_URL}/transaction/history/${path}`); const url = navigate(`${API_URL}/transaction/history/${path}`);
}; };
const handleShowDetail = (transactionId: any) => { const handleShowDetail = (transactionId: any) => {
setIsLoadingDetail(true); setIsLoadingDetail(true);
setSelectedTransactionId(transactionId); setSelectedTransactionId(transactionId);
@ -70,7 +69,6 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
}, 1000); // 500ms loading }, 1000); // 500ms loading
}; };
const columns = useMemo<ColumnDef<any>[]>( const columns = useMemo<ColumnDef<any>[]>(
() => [ () => [
{ {
@ -85,27 +83,48 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
{ {
accessorFn: (row) => { accessorFn: (row) => {
switch (row.kind) { switch (row.kind) {
case 'T': return 'TRANSFER'; case 'T':
case 'P': return 'PURCHASE'; return 'TRANSFER';
case 'W': return 'WITHDRAW'; case 'P':
case 'U': return 'TOP UP'; return 'PURCHASE';
case 'R': return 'RETURN'; case 'W':
case 'N': return 'TOP UP PARTNER'; return 'WITHDRAW';
case 'E': return 'REWARD'; case 'U':
case 'L': return 'PURCHASE LOJA'; return 'TOP UP';
case 'B': return 'TOP UP P24'; case 'R':
case 'A': return 'TRANSFER AGENT'; return 'RETURN';
case 'M': return 'WITHDRAWAL AGENT'; case 'N':
case 'O': return 'TOP UP AGENT'; return 'TOP UP PARTNER';
case 'S': return 'TRANSFER P24'; case 'E':
case 'I': return 'WIJTDRAW MERCHANT'; return 'REWARD';
case 'D': return 'DONATION'; case 'L':
case 'F': return 'FEE'; return 'PURCHASE LOJA';
case 'V': return 'REVERSAL'; case 'B':
case 'C': return 'CASHBACK CASH'; return 'TOP UP P24';
case 'H': return 'CASHBACK POINT'; case 'A':
case 'J': return 'WITHDRAW ADMIN'; return 'TRANSFER AGENT';
default: return '_'; case 'M':
return 'WITHDRAWAL AGENT';
case 'O':
return 'TOP UP AGENT';
case 'S':
return 'TRANSFER P24';
case 'I':
return 'WIJTDRAW MERCHANT';
case 'D':
return 'DONATION';
case 'F':
return 'FEE';
case 'V':
return 'REVERSAL';
case 'C':
return 'CASHBACK CASH';
case 'H':
return 'CASHBACK POINT';
case 'J':
return 'WITHDRAW ADMIN';
default:
return '_';
} }
}, },
accessorKey: 'kind', accessorKey: 'kind',
@ -153,7 +172,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
}, },
{ {
accessorFn: (row) => { accessorFn: (row) => {
const purchase = "T-PAY"; const purchase = 'T-PAY';
const transfer = row?.transfer?.destination_name; const transfer = row?.transfer?.destination_name;
return transfer ?? purchase; return transfer ?? purchase;
@ -165,38 +184,42 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
meta: { meta: {
headerClassName: 'w-[250px]', headerClassName: 'w-[250px]'
}, }
}, },
{ {
accessorFn: (row) => { accessorFn: (row) => {
const purchaseAmount = row?.purchase?.amount; const purchaseAmount = row?.purchase?.amount;
const transferAmount = row?.transfer?.amount; const transferAmount = row?.transfer?.amount;
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(purchaseAmount ?? transferAmount ?? 0); return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(
purchaseAmount ?? transferAmount ?? 0
);
}, },
id: 'amount', id: 'amount',
header: ({ column }) => <DataGridColumnHeader title="Amount" column={column} />, header: ({ column }) => <DataGridColumnHeader title="Amount" column={column} />,
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
meta: { meta: {
headerClassName: 'w-[250px]', headerClassName: 'w-[250px]'
}, }
}, },
{ {
accessorFn: (row) => { accessorFn: (row) => {
const purchaseAmount = row?.purchase?.fee_amount; const purchaseAmount = row?.purchase?.fee_amount;
const transferAmount = row?.transfer?.fee_amount; const transferAmount = row?.transfer?.fee_amount;
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(purchaseAmount ?? transferAmount ?? 0); return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(
purchaseAmount ?? transferAmount ?? 0
);
}, },
id: 'feeamount', id: 'feeamount',
header: ({ column }) => <DataGridColumnHeader title="Fee Amount" column={column} />, header: ({ column }) => <DataGridColumnHeader title="Fee Amount" column={column} />,
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
meta: { meta: {
headerClassName: 'w-[250px]', headerClassName: 'w-[250px]'
}, }
}, },
{ {
accessorKey: 'status', accessorKey: 'status',
@ -204,7 +227,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
meta: { meta: {
headerClassName: 'w-[250px]', headerClassName: 'w-[250px]'
}, },
cell: ({ row }) => { cell: ({ row }) => {
const statusCode = row.original.status; const statusCode = row.original.status;
@ -247,7 +270,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
{label} {label}
</span> </span>
); );
}, }
}, },
{ {
accessorKey: 'description', accessorKey: 'description',
@ -279,7 +302,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
<div key={`actions-${row.id}`}> <div key={`actions-${row.id}`}>
<div className="relative inline-block"> <div className="relative inline-block">
<button <button
className={`btn btn-sm btn-icon btn-clear btn-light ${isLoadingDetail ? "cursor-not-allowed opacity-60" : ""}`} className={`btn btn-sm btn-icon btn-clear btn-light ${isLoadingDetail ? 'cursor-not-allowed opacity-60' : ''}`}
onClick={() => !isLoadingDetail && handleShowDetail(row.id)} onClick={() => !isLoadingDetail && handleShowDetail(row.id)}
> >
<KeenIcon icon="eye" /> <KeenIcon icon="eye" />
@ -305,7 +328,8 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
} }
} }
], ],
[]); []
);
const getTransactionLists = async (page: number, limit: number, sorting: any, filter: any) => { const getTransactionLists = async (page: number, limit: number, sorting: any, filter: any) => {
try { try {
@ -346,27 +370,21 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
}); });
// Kalau tidak ada searchType, baru pakai tanggal // Kalau tidak ada searchType, baru pakai tanggal
if (!searchType) {
if (!startdate || !enddate) { if (!startdate || !enddate) {
startdate = firstDayOfMonth.toISOString().split('T')[0]; startdate = firstDayOfMonth.toISOString().split('T')[0];
enddate = today.toISOString().split('T')[0]; enddate = today.toISOString().split('T')[0];
} }
} else {
// Kosongkan supaya tidak digunakan di bawah
startdate = undefined;
enddate = undefined;
}
// Build formattedFilter setelah semua nilai diketahui // Build formattedFilter setelah semua nilai diketahui
const formattedFilter: any = {}; const formattedFilter: any = {};
if (status) { if (status) {
formattedFilter["Transactions.status"] = status; formattedFilter['Transactions.status'] = status;
} }
// Tambahkan filter tanggal HANYA jika tidak ada searchType // Tambahkan filter tanggal HANYA jika tidak ada searchType
if (startdate && enddate) { if (startdate && enddate) {
formattedFilter["Transactions.transaction_date"] = { formattedFilter['Transactions.transaction_date'] = {
from: `${startdate} 00:00:00`, from: `${startdate} 00:00:00`,
to: `${enddate} 23:59:59` to: `${enddate} 23:59:59`
}; };
@ -374,25 +392,25 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
// Tambahkan filter berdasarkan searchType // Tambahkan filter berdasarkan searchType
if (searchType && codeValue) { if (searchType && codeValue) {
if (searchType === "msisdn") { if (searchType === 'msisdn') {
formattedFilter["origin_customer.msisdn"] = { like: `%${codeValue}%` }; formattedFilter['origin_customer.msisdn'] = { like: `%${codeValue}%` };
} else if (searchType === "fullname") { } else if (searchType === 'fullname') {
formattedFilter["origin_customer.fullname"] = { like: `%${codeValue}%` }; formattedFilter['origin_customer.fullname'] = { like: `%${codeValue}%` };
} else if (searchType === "trxid") { } else if (searchType === 'trxid') {
formattedFilter["Transactions.code"] = { like: `%${codeValue}%` }; formattedFilter['Transactions.code'] = { like: `%${codeValue}%` };
} }
} }
// Tambahkan filter jenis transaksi jika ada // Tambahkan filter jenis transaksi jika ada
if (type) { if (type) {
formattedFilter["Transactions.kind"] = type; formattedFilter['Transactions.kind'] = type;
} }
const response = await GetData(`${API_URL}/transaction/history`, { const response = await GetData(`${API_URL}/transaction/history`, {
limit, limit,
page: page + 1, page: page + 1,
with_deleted: false, with_deleted: false,
order_field: "Transactions.created_at", order_field: 'Transactions.created_at',
order_direction: 'DESC', order_direction: 'DESC',
filter: JSON.stringify(formattedFilter) filter: JSON.stringify(formattedFilter)
}); });
@ -407,15 +425,12 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
} }
return { data: [], totalCount: 0 }; return { data: [], totalCount: 0 };
} catch (error) { } catch (error) {
console.error('Error fetching transaction', error); console.error('Error fetching transaction', error);
return { data: [], totalCount: 0 }; return { data: [], totalCount: 0 };
} }
}; };
return ( return (
<ManageTransactionContext.Provider <ManageTransactionContext.Provider
value={{ value={{
@ -456,7 +471,6 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
</div> </div>
)} )}
<DataGridProvider <DataGridProvider
columns={columns} columns={columns}
pagination={{ size: 10 }} pagination={{ size: 10 }}