diff --git a/src/pages/dashboards/home/blocks/ShowDetailWalletDialog.tsx b/src/pages/dashboards/home/blocks/ShowDetailWalletDialog.tsx index fef67f8..b2fa6cc 100644 --- a/src/pages/dashboards/home/blocks/ShowDetailWalletDialog.tsx +++ b/src/pages/dashboards/home/blocks/ShowDetailWalletDialog.tsx @@ -1,406 +1,489 @@ import React, { useCallback, useEffect, useState } from 'react'; import { - Dialog, - DialogBody, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle } from '@/components/ui/dialog'; import { useCallApi } from '@/hooks'; import { apiConfig } from '@/config/api.config'; import { DataGridColumnHeader, DataGridProvider } from '@/components'; import { Button } from '@/components/ui/button'; import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue } from '@/components/ui/select'; import { DefaultTooltip, KeenIcon } from '@/components'; +import { toAbsoluteUrl } from '@/utils'; +import { toast } from 'sonner'; +import * as XLSX from 'xlsx'; +import ExcelJS from 'exceljs'; +import { exportToExcel } from '@/pages/wallet/wallet-statement/details_wallet_statement/ExportData'; interface ShowDetailWalletDialogProps { - open: boolean; - onClose: () => void; - idbalance: string; + open: boolean; + onClose: () => void; + idbalance: string; } interface TransferType { - id: string; - name: string; + id: string; + name: string; } const formatDate = (date: Date) => date.toLocaleDateString('sv-SE'); const getDefaultDateRange = () => { - const today = new Date(); - const sevenDaysAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); - return { - from: formatDate(sevenDaysAgo), - to: formatDate(today), - }; + const today = new Date(); + const sevenDaysAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); + return { + from: formatDate(sevenDaysAgo), + to: formatDate(today) + }; }; const ShowDetailWalletDialog: React.FC = ({ - open, - onClose, - idbalance, + open, + onClose, + idbalance }) => { - const { GetData } = useCallApi(); + const { GetData } = useCallApi(); - const [dateRange, setDateRange] = useState(getDefaultDateRange()); - const [selectedTransferType, setSelectedTransferType] = useState(null); - const [transferType, setTransferType] = useState([]); - const [selectedCategory, setSelectedCategory] = useState(null); - const [searchValue, setSearchValue] = useState(''); - const [category, setCategory] = useState([]); - const [transaction, setTransaction] = useState([]); - const [filters, setFilters] = useState({}); + const [dateRange, setDateRange] = useState(getDefaultDateRange()); + const [selectedTransferType, setSelectedTransferType] = useState(null); + const [transferType, setTransferType] = useState([]); + const [selectedCategory, setSelectedCategory] = useState(null); + const [searchValue, setSearchValue] = useState(''); + const [category, setCategory] = useState([]); + const [transaction, setTransaction] = useState([]); + const [filters, setFilters] = useState({}); - const fetchTransferType = useCallback(async () => { - try { - const response = await GetData(`${apiConfig.service_transaction}/transactiontype/list`, { - limit: 100, - page: 1, - with_deleted: false, - order_field: 'created_at', - order_direction: 'ASC', - }); - setTransferType(response?.data?.list || []); - } catch (error) { - console.error('Error fetching transfer types', error); + const fetchTransferType = useCallback(async () => { + try { + const response = await GetData(`${apiConfig.service_transaction}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'created_at', + order_direction: 'ASC' + }); + setTransferType(response?.data?.list || []); + } catch (error) { + console.error('Error fetching transfer types', error); + } + }, [GetData]); + + useEffect(() => { + fetchTransferType(); + }, [fetchTransferType]); + + useEffect(() => { + const categoryMap: Record = { + T: 'TRANSFER', + P: 'PURCHASE', + W: 'WITHDRAW', + U: 'TOP UP', + R: 'RETURN', + N: 'TOP UP PARTNER', + E: 'REWARD', + L: 'PURCHASE LOJA', + B: 'TOP UP P24', + A: 'TRANSFER AGENT', + M: 'WITHDRAWAL AGENT', + O: 'TOP UP AGENT', + S: 'TRANSFER P24', + I: 'WIJTDRAW MERCHANT', + D: 'DONATION', + F: 'FEE', + V: 'REVERSAL', + C: 'CASHBACK CASH', + H: 'CASHBACK POINT' + }; + + const uniqueCategories = Array.from( + new Set( + transaction + .map((tx) => categoryMap[tx.category] || '_') // map code to label or default to '_' + .filter((cat) => !!cat && cat !== '_') // remove undefined/null or underscore + ) + ); + + setCategory(uniqueCategories); + }, [transaction]); + + const handleTransferTypeChange = (value: string) => { + setSelectedTransferType(value === 'all' ? null : value); + }; + + const handleCategoryChange = (value: string) => { + setSelectedCategory(value === '' ? null : value); + }; + + const handleClearAllFilters = () => { + setDateRange(getDefaultDateRange()); + setSelectedTransferType(null); + setSelectedCategory(null); + setSearchValue(''); + setFilters({}); + }; + + const handleApplyFilters = () => { + const appliedFilters: any = {}; + + if (dateRange.from && dateRange.to) { + const fromDate = new Date(`${dateRange.from}T00:00:00Z`); + const toDate = new Date(`${dateRange.to}T23:59:59Z`); + appliedFilters.date = { + from: fromDate.toISOString(), + to: toDate.toISOString() + }; + } + + if (selectedTransferType) { + appliedFilters.transaction_type_id = selectedTransferType; + } + + if (selectedCategory) { + appliedFilters.category = selectedCategory; + } + + if (searchValue) { + appliedFilters.transaction_code = searchValue; + } + + setFilters(appliedFilters); + }; + + const columns = [ + { + accessorKey: 'transaction_code', + header: ({ column }: any) => ( + + ), + enableSorting: false, + meta: { headerClassName: 'min-w-[120px]' } + }, + { + accessorKey: 'msisdn_reff', + header: ({ column }: any) => , + enableSorting: false, + meta: { headerClassName: 'min-w-[120px]' } + }, + { + accessorKey: 'transaction_type.name', + header: ({ column }: any) => ( + + ), + enableSorting: false, + meta: { headerClassName: 'min-w-[180px]' } + }, + { + accessorKey: 'type', + header: ({ column }: any) => , + enableSorting: false, + meta: { headerClassName: 'min-w-[80px]' } + }, + { + accessorKey: 'pre_amount', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => info.getValue()?.toFixed(2), + meta: { headerClassName: 'min-w-[100px]' } + }, + { + accessorKey: 'amount', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => info.getValue()?.toFixed(2), + meta: { headerClassName: 'min-w-[100px]' } + }, + { + accessorKey: 'post_amount', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => info.getValue()?.toFixed(2), + meta: { headerClassName: 'min-w-[100px]' } + }, + { + accessorFn: (row: any) => { + switch (row.category) { + case 'T': + return 'TRANSFER'; + case 'P': + return 'PURCHASE'; + case 'W': + return 'WITHDRAW'; + case 'U': + return 'TOP UP'; + case 'R': + return 'RETURN'; + case 'N': + return 'TOP UP PARTNER'; + case 'E': + return 'REWARD'; + case 'L': + return 'PURCHASE LOJA'; + case 'B': + return 'TOP UP P24'; + case 'A': + return 'TRANSFER AGENT'; + 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'; + default: + return '_'; } - }, [GetData]); + }, + accessorKey: 'category', + header: ({ column }: any) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorKey: 'date', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => { + const val = info.getValue(); + if (!val) return '-'; + return new Date(val).toLocaleString('id-ID', { + day: '2-digit', + month: 'short', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + }, + meta: { headerClassName: 'min-w-[150px]' } + }, + { + accessorKey: 'purpose', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => info.getValue() || '-', + meta: { headerClassName: 'min-w-[200px]' } + }, + { + accessorKey: 'notes', + header: ({ column }: any) => , + enableSorting: false, + cell: (info: any) => info.getValue() || '-', + meta: { headerClassName: 'min-w-[200px]' } + } + ]; - useEffect(() => { - fetchTransferType(); - }, [fetchTransferType]); - - useEffect(() => { - const categoryMap: Record = { - T: 'TRANSFER', - P: 'PURCHASE', - W: 'WITHDRAW', - U: 'TOP UP', - R: 'RETURN', - N: 'TOP UP PARTNER', - E: 'REWARD', - L: 'PURCHASE LOJA', - B: 'TOP UP P24', - A: 'TRANSFER AGENT', - M: 'WITHDRAWAL AGENT', - O: 'TOP UP AGENT', - S: 'TRANSFER P24', - I: 'WIJTDRAW MERCHANT', - D: 'DONATION', - F: 'FEE', - V: 'REVERSAL', - C: 'CASHBACK CASH', - H: 'CASHBACK POINT', - }; - - const uniqueCategories = Array.from( - new Set( - transaction - .map((tx) => categoryMap[tx.category] || '_') // map code to label or default to '_' - .filter((cat) => !!cat && cat !== '_') // remove undefined/null or underscore - ) + const getTransactionLists = useCallback( + async (page: number, limit: number, sorting: any, _columnFilters: any) => { + // console.log(idbalance); + try { + const response = await GetData( + `${apiConfig.service_wallet}/dashboard/balance/list-balance-detail/${idbalance}`, + { + limit, + page: page + 1, + with_deleted: false, + order_field: 'created_at', + order_direction: 'DESC', + filter: JSON.stringify(filters) + } ); - setCategory(uniqueCategories); - }, [transaction]); + // console.log(response); - - const handleTransferTypeChange = (value: string) => { - setSelectedTransferType(value === 'all' ? null : value); - }; - - const handleCategoryChange = (value: string) => { - setSelectedCategory(value === '' ? null : value); - }; - - const handleClearAllFilters = () => { - setDateRange(getDefaultDateRange()); - setSelectedTransferType(null); - setSelectedCategory(null); - setSearchValue(''); - setFilters({}); - }; - - const handleApplyFilters = () => { - const appliedFilters: any = {}; - - if (dateRange.from && dateRange.to) { - const fromDate = new Date(`${dateRange.from}T00:00:00Z`); - const toDate = new Date(`${dateRange.to}T23:59:59Z`); - appliedFilters.date = { - from: fromDate.toISOString(), - to: toDate.toISOString(), - }; + if (!response || !response.data) { + console.warn('No data received:', response); + return { data: [], totalCount: 0 }; } - if (selectedTransferType) { - appliedFilters.transaction_type_id = selectedTransferType; + setTransaction(response.data.list); + return { data: response.data.list, totalCount: response.data.total_count }; + } catch (error) { + console.error('Error fetching transaction', error); + return { data: [], totalCount: 0 }; + } + }, + [GetData, idbalance, filters] + ); + + const getAllTransactionData = async () => { + try { + const response = await GetData( + `${apiConfig.service_wallet}/dashboard/balance/list-balance-detail/${idbalance}`, + { + limit: 10000, + page: 1, + with_deleted: false, + order_field: 'created_at', + order_direction: 'DESC', + filter: JSON.stringify(filters) } + ); - if (selectedCategory) { - appliedFilters.category = selectedCategory; - } + return response?.data?.list || []; + } catch (error) { + console.error('Error fetching all transaction data', error); + return []; + } + }; - if (searchValue) { - appliedFilters.transaction_code = searchValue; - } + // Tambahkan fungsi handle export excel + const handleExportExcel = async () => { + try { + const allData = await getAllTransactionData(); + + // Buat objek wallet dummy untuk kompatibilitas dengan fungsi exportToExcel + const walletData = { + ID: idbalance, + name: 'Wallet Details', + msisdn: '-' + }; - setFilters(appliedFilters); - }; + await exportToExcel(allData, walletData); + } catch (error) { + console.error('Error exporting to Excel:', error); + toast.error('Failed to export Excel'); + } + }; + return ( + + + + Details Wallet Statement + + - const columns = [ - { - accessorKey: 'transaction_code', - header: ({ column }: any) => , - enableSorting: false, - meta: { headerClassName: 'min-w-[120px]' }, - }, - { - accessorKey: 'msisdn_reff', - header: ({ column }: any) => , - enableSorting: false, - meta: { headerClassName: 'min-w-[120px]' }, - }, - { - accessorKey: 'transaction_type.name', - header: ({ column }: any) => , - enableSorting: false, - meta: { headerClassName: 'min-w-[180px]' }, - }, - { - accessorKey: 'type', - header: ({ column }: any) => , - enableSorting: false, - meta: { headerClassName: 'min-w-[80px]' }, - }, - { - accessorKey: 'pre_amount', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => info.getValue()?.toFixed(2), - meta: { headerClassName: 'min-w-[100px]' }, - }, - { - accessorKey: 'amount', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => info.getValue()?.toFixed(2), - meta: { headerClassName: 'min-w-[100px]' }, - }, - { - accessorKey: 'post_amount', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => info.getValue()?.toFixed(2), - meta: { headerClassName: 'min-w-[100px]' }, - }, - { - accessorFn: (row: any) => { - switch (row.category) { - case 'T': return 'TRANSFER'; - case 'P': return 'PURCHASE'; - case 'W': return 'WITHDRAW'; - case 'U': return 'TOP UP'; - case 'R': return 'RETURN'; - case 'N': return 'TOP UP PARTNER'; - case 'E': return 'REWARD'; - case 'L': return 'PURCHASE LOJA'; - case 'B': return 'TOP UP P24'; - case 'A': return 'TRANSFER AGENT'; - 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'; - default: return '_'; - } - }, - accessorKey: 'category', - header: ({ column }: any) => , - enableSorting: false, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - accessorKey: 'date', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => { - const val = info.getValue(); - if (!val) return '-'; - return new Date(val).toLocaleString('id-ID', { - day: '2-digit', - month: 'short', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - }); - }, - meta: { headerClassName: 'min-w-[150px]' }, - }, - { - accessorKey: 'purpose', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => info.getValue() || '-', - meta: { headerClassName: 'min-w-[200px]' }, - }, - { - accessorKey: 'notes', - header: ({ column }: any) => , - enableSorting: false, - cell: (info: any) => info.getValue() || '-', - meta: { headerClassName: 'min-w-[200px]' }, - }, - ]; + +
+
+ - const getTransactionLists = useCallback( - async (page: number, limit: number, sorting: any, _columnFilters: any) => { - // console.log(idbalance); - try { - const response = await GetData(`${apiConfig.service_wallet}/dashboard/balance/list-balance-detail/${idbalance}`, { - limit, - page: page + 1, - with_deleted: false, - order_field: "created_at", - order_direction: 'DESC', - filter: JSON.stringify(filters) - }); + - // console.log(response); +
+ +
- if (!response || !response.data) { - console.warn('No data received:', response); - return { data: [], totalCount: 0 }; - } +
+ +
- setTransaction(response.data.list); - return { data: response.data.list, totalCount: response.data.total_count }; - } catch (error) { - console.error('Error fetching transaction', error); - return { data: [], totalCount: 0 }; - } - }, - [GetData, idbalance, filters] - ); + - return ( - - - - Details Wallet Statement - - + + + - -
-
- + - + + + +
+
-
- -
- -
- -
- - - - - - - - -
-
- -
- - getTransactionLists(pageIndex, pageSize, sorting, columnFilters) - } - /> -
-
-
-
- ); +
+ + getTransactionLists(pageIndex, pageSize, sorting, columnFilters) + } + /> +
+ + + + ); }; export default ShowDetailWalletDialog;