From d0ac8c55b43a0be31d40f82d6bacc358fc3eb005 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 14 Apr 2025 20:09:58 +0700 Subject: [PATCH] fixing transactiontype and transactionfee --- .../transfer/transferfee/blocks/AddDialog.tsx | 186 +++-- .../transferfee/blocks/DeleteDialog.tsx | 26 +- .../transferfee/blocks/EditDialog.tsx | 254 +++--- .../hooks/ManageTransferFeeContext.tsx | 761 +++++++++--------- .../transfertype/blocks/AddDialog.tsx | 30 +- .../transfertype/blocks/DeleteDialog.tsx | 26 +- .../transfertype/blocks/EditDialog.tsx | 2 +- .../hooks/ManageTransferTypeContext.tsx | 23 +- 8 files changed, 711 insertions(+), 597 deletions(-) diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx index 45df2a9..0860010 100644 --- a/src/pages/transfer/transferfee/blocks/AddDialog.tsx +++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx @@ -63,14 +63,14 @@ const AddFeeDialog = () => { const parentRef = useRef(null); const { reload } = useDataGrid(); const { PostData, PutData, GetData } = useCallApi(); - const { - showAddFeeDialog, - handleAddFeeDialog, - handleEditFeeDialog, + const { + showAddFeeDialog, + handleAddFeeDialog, + handleEditFeeDialog, selectedTransferFee, transactionTypeId } = useManageTransferFeeContext(); - + const [alert, setAlert] = useState({ show: false, message: '' @@ -80,13 +80,13 @@ const AddFeeDialog = () => { const [customers, setCustomers] = useState([]); const [defaultCustomer, setDefaultCustomer] = useState(''); const [transactionTypeName, setTransactionTypeName] = useState(''); - + const [isLoadingTransactionType, setIsLoadingTransactionType] = useState(false); const [isLoadingWallets, setIsLoadingWallets] = useState(false); const [isLoadingCustomers, setIsLoadingCustomers] = useState(false); const customersWithNames = customers.map((customer) => ({ id: customer.id, - name: customer.username, + name: customer.username })); const initialState = { name: '', @@ -125,15 +125,18 @@ const AddFeeDialog = () => { useEffect(() => { if (showAddFeeDialog && transactionTypeId) { setIsLoadingTransactionType(true); - - setFormField(prev => ({ + + setFormField((prev) => ({ ...prev, transaction_type: transactionTypeId })); - + const getTransactionTypeDetails = async () => { try { - const response = await GetData(`${API_URL}/transactiontype/getdata/${transactionTypeId}`, {}); + const response = await GetData( + `${API_URL}/transactiontype/getdata/${transactionTypeId}`, + {} + ); if (response?.status && response?.data) { setTransactionTypeName(response.data.name); } @@ -143,17 +146,17 @@ const AddFeeDialog = () => { setIsLoadingTransactionType(false); } }; - + getTransactionTypeDetails(); } }, [showAddFeeDialog, transactionTypeId, GetData]); - + useEffect(() => { const created_time = new Date(); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); if (showAddFeeDialog) { - setFormField(prev => ({ + setFormField((prev) => ({ ...prev, created_by: parsedUser?.username, created_at: formattedTime @@ -193,7 +196,7 @@ const AddFeeDialog = () => { page: 1, with_deleted: false, order_field: 'Wallets.name', - order_direction: 'ASC', + order_direction: 'ASC' }; try { const response = await GetData(`${API_URL_MASTER_DATA}/wallet/list`, params); @@ -209,7 +212,7 @@ const AddFeeDialog = () => { setIsLoadingWallets(false); } }, [GetData]); - + useEffect(() => { if (!showAddFeeDialog) return; fetchWallets(); @@ -231,7 +234,7 @@ const AddFeeDialog = () => { }); const customerList = response?.data.list || []; setCustomers(customerList); - + if (customerList.length > 0) { setDefaultCustomer(customerList[0].id); } @@ -250,9 +253,9 @@ const AddFeeDialog = () => { async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); - + const requiredFields = [ - 'name', + 'name', 'description', 'period_start', 'period_end', @@ -265,44 +268,44 @@ const AddFeeDialog = () => { 'credit_to', 'credit_destination_account' ]; - + for (const field of requiredFields) { if (formField[field as keyof typeof formField] === '') { - setAlert({ - show: true, - message: `All required fields must be filled out. Missing: ${field.replace(/_/g, ' ')}` + setAlert({ + show: true, + message: `All required fields must be filled out. Missing: ${field.replace(/_/g, ' ')}` }); setIsSubmitting(false); return; } } - + if (formField.credit_to === 'I' && !formField.credit_destination) { - setAlert({ - show: true, - message: 'Credit destination is required when Input Customer is selected' + setAlert({ + show: true, + message: 'Credit destination is required when Input Customer is selected' }); setIsSubmitting(false); return; } setAlert({ show: false, message: '' }); - + const payload = { ...formField }; - + if (formField.credit_to !== 'I') { payload.credit_destination = '00000000-0000-0000-0000-000000000000'; } - + try { const response = await PostData(`${API_URL}/transactionfees/create`, payload); - + if (response?.status) { toast.success('Successfully created transfer fee'); reload(); resetForm(); handleAddFeeDialog(false); - + const createActivity = { module: 'Manage Transfer Fee', description: `Create Transfer Fee => ${formField.name}`, @@ -323,18 +326,14 @@ const AddFeeDialog = () => { ); const renderSelectWithLoading = ( - value: string, + value: string, onChangeHandler: (value: string) => void, - options: {id: string, name: string}[] | null, + options: { id: string; name: string }[] | null, placeholder: string, isLoading: boolean ) => { return ( - {isLoading ? (
@@ -346,11 +345,12 @@ const AddFeeDialog = () => { )} - {options && options.map((option) => ( - - {option.name} - - ))} + {options && + options.map((option) => ( + + {option.name} + + ))} ); @@ -389,7 +389,9 @@ const AddFeeDialog = () => {
- + {transactionTypeId ? (
{ formField.transaction_type, (transaction_type) => setFormField((prev) => ({ ...prev, transaction_type })), transactionTypes, - "Select Transaction Type", + 'Select Transaction Type', isLoadingTransactionType ) )}
- + { />
- + { />
- + { />
- + { />
- +
- + {renderSelectWithLoading( formField.deduct_from_account, (value) => setFormField({ ...formField, deduct_from_account: value }), wallets, - "Select Wallet", + 'Select Wallet', isLoadingWallets )}
- + setFormField({ ...formField, status: value })} @@ -633,7 +658,9 @@ const AddFeeDialog = () => {
- +
- + { } />
- +
- + { } />
- +
{ placeholder="Enter Minimum Amount" />
- +
{ placeholder="Enter Maximum Amount" />
- +
- + { } />
- +
- + { } />
- +
{ placeholder="Enter Deduct Amount" />
- +
{ placeholder="Enter Deduct Percentage" />
- +
{ placeholder="Enter Fee Amount" />
- +
- +
- +
- +
- +
- +
- + {formField.credit_to === 'I' && (
- +
)} - +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- - - ); - }, - meta: { - headerClassName: 'w-[100px]', - cellClassName: 'text-center' - } - } - ], - [handleEditFeeDialog, handleDeleteFeeDialog] - ); + try { + const response = await GetData( + `${API_URL}/transactionfees/getdatabytransactiontype/${selectedTransferType}`, + {} + ); - return ( -
-
-

Manage Transaction Fee

-
- - - } - sorting={[{ id: 'id', desc: true }]} - serverSide={true} - onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => - doGetTransferFeeListData(pageIndex, pageSize, sorting, columnFilters) - } - > - {children} + // console.log('API Response:', response?.data); - - -
- ); + return { + data: response?.data, + totalCount: 1 + }; + } catch (error) { + console.error('Error fetching transaction fees by transaction type:', error); + return { data: [], totalCount: 0 }; + } }; - export { ManageTransferFeeContext, ManageTransferFeeContextProvider }; + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => row.name, + id: 'name', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.description, + id: 'description', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.minimum_amount, + id: 'minimum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.maximum_amount, + id: 'maximum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.fee_amount, + id: 'fee_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.deduct_amount, + id: 'deduct_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.deduct_percentage, + id: 'deduct_percentage', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + + { + accessorFn: (row) => row.period_start?.split('T')[0], + id: 'period_start', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.period_end?.split('T')[0], + id: 'period_end', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.transaction_type?.name, + id: 'transactionTypeId', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row: { credit_to: string }) => { + const mapping: Record = { + D: 'Destination Member', + S: 'Source Member', + I: 'Input Customer' + }; + + return mapping[row.credit_to] || 'Unknown'; + }, + id: 'credit_to', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => { + if (row.credit_to === 'S' || row.credit_to === 'D' || !row.credit_destination) { + return 'N/A'; + } + return row.credit_destination?.fullname; + }, + id: 'credit_destination', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.credit_destination_account?.description, + id: 'credit_destination_account', + header: ({ column }) => ( + + ), + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row: { deduct_from: string }) => { + const mapping: Record = { + D: 'Destination Member', + S: 'Source Member' + }; + + return mapping[row.deduct_from]; + }, + id: 'deduct_from', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.deduct_from_account?.description, + id: 'deduct_from_account', + header: ({ column }) => ( + + ), + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.priority, + id: 'priority', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + cell: ({ row }) => { + const isActive = row.original.priority === 'Y'; + + return ( + + {isActive ? 'Yes' : 'No'} + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + }, + { + accessorFn: (row) => row.status, + id: 'status', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + cell: ({ row }) => { + const isActive = row.original.status === 'Y'; + + return ( + + {isActive ? 'Active' : 'Inactive'} + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + }, + { + accessorFn: (row) => row.status_include, + id: 'status_include', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + cell: ({ row }) => { + const isActive = row.original.status_include === 'Y'; + + return ( + + {isActive ? 'Yes' : 'No'} + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + }, + { + id: 'actions', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + cell: (data) => { + const row = data.row.original; + return ( + <> + + + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + } + ], + [handleEditFeeDialog, handleDeleteFeeDialog] + ); + + return ( +
+
+

Manage Transaction Fee

+
+ + + } + sorting={[{ id: 'id', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + doGetTransferFeeListData(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + +
+ ); +}; + +export { ManageTransferFeeContext, ManageTransferFeeContextProvider }; diff --git a/src/pages/transfer/transfertype/blocks/AddDialog.tsx b/src/pages/transfer/transfertype/blocks/AddDialog.tsx index 6d35adc..6e5f51f 100644 --- a/src/pages/transfer/transfertype/blocks/AddDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/AddDialog.tsx @@ -76,7 +76,6 @@ const AddDialog = () => { wallet_origin: '', wallet_destination: '', - minimum_amount: 0, maximum_amount: 0, max_transaction_per_day: 0, @@ -141,13 +140,13 @@ const AddDialog = () => { toast.success('Success Create Transfer Type'); reload(); resetForm(); - const createActivity = { - module: 'Manage Transfer Type', - description: `Create Transfer Type => ${formField.name}`, - action: 'C' - }; + const createActivity = { + module: 'Manage Transfer Type', + description: `Create Transfer Type => ${formField.name}`, + action: 'C' + }; - doSaveLogActivity(createActivity); + doSaveLogActivity(createActivity); } }) .finally(() => { @@ -222,7 +221,7 @@ const AddDialog = () => { page: 1, with_deleted: false, order_field: 'wallets.name', - order_direction: 'ASC', + order_direction: 'ASC' }; const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); // console.log(response) @@ -265,11 +264,11 @@ const AddDialog = () => {
{alert.show && ( -
- -

{alert.message}

-
-
+
+ +

{alert.message}

+
+
)}
@@ -439,11 +438,10 @@ const AddDialog = () => {
-
@@ -458,7 +456,7 @@ const AddDialog = () => { - Disbursement + Disbursement Other Change Group Emoney Customer to Agent Change Group Emoney Agent to Customer diff --git a/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx index e4c51ad..ec35bf1 100644 --- a/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx @@ -1,4 +1,10 @@ -import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Alert, useDataGrid } from '@/components'; import { useCallback, useState } from 'react'; @@ -12,7 +18,8 @@ import { doSaveLogActivity } from '@/actions/GlobalActions'; const API_URL = apiConfig.service_transaction; const DeleteDialog = () => { - const { showDeleteDialog, handleDeleteDialog, selectedTransferType } = useManageTransferTypeContext(); + const { showDeleteDialog, handleDeleteDialog, selectedTransferType } = + useManageTransferTypeContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); const [alert, setAlert] = useState({ @@ -26,9 +33,12 @@ const DeleteDialog = () => { return; } - const response = await DeleteData(`${API_URL}/transactiontype/delete/${selectedTransferType}/false`, { - id: selectedTransferType - }); + const response = await DeleteData( + `${API_URL}/transactiontype/delete/${selectedTransferType}/false`, + { + id: selectedTransferType + } + ); if (response?.status) { setAlert({ show: false, message: '' }); @@ -37,7 +47,7 @@ const DeleteDialog = () => { const createActivity = { module: 'Manage Transfer Type', description: `Delete Transfer Type => ${selectedTransferType}`, - action: 'D' + action: 'D' }; doSaveLogActivity(createActivity); // setTimeout(() => toast.success('Success Delete Transaction Type'), 0); @@ -51,7 +61,9 @@ const DeleteDialog = () => { Delete Transfer Type - Are you sure you want to delete this data? + + Are you sure you want to delete this data? +

Are you sure?

You will delete this data! diff --git a/src/pages/transfer/transfertype/blocks/EditDialog.tsx b/src/pages/transfer/transfertype/blocks/EditDialog.tsx index c4b9e8f..1e3ca41 100644 --- a/src/pages/transfer/transfertype/blocks/EditDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/EditDialog.tsx @@ -589,7 +589,7 @@ const EditDialog = () => { - Disbursement + Disbursement Other Change Group Emoney Customer to Agent Change Group Emoney Agent to Customer diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx index efa6279..942ee8f 100644 --- a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -147,21 +147,21 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React meta: { headerClassName: 'w-[250px]' } }, { - accessorFn: (row: {type: string }) => { + accessorFn: (row: { type: string }) => { const mapping: Record = { D: 'Disbursement', O: 'Other', CA: 'Change Group Emoney Customer to Agent', - AC:'Change Group Emoney Agent to Customer', + AC: 'Change Group Emoney Agent to Customer', PC: 'Change Group Point Agent to Customer', PA: 'Change Group Point Customer to Agent', - CE:'Return Customer Emoney', - AD:'Return Agent Deposit', + CE: 'Return Customer Emoney', + AD: 'Return Agent Deposit', AM: 'Return Agent Merchant', AE: 'Return Agent Emoney', - R: 'Reward Point', + R: 'Reward Point' }; - + return mapping[row.type] || 'Unknown'; }, id: 'type', @@ -171,7 +171,7 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React enableSorting: true, enableHiding: false, meta: { headerClassName: 'w-[250px]' } - }, + }, { accessorFn: (row) => (row.status === 'Y' ? 'Active' : 'Inactive'), id: 'status', @@ -217,20 +217,19 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React ], [handleEditDialog, handleDeleteDialog] ); - + const doGetTransferTypeListData = async ( page: number, limit: number, sorting: any, filter: any ) => { - const orderField = 'created_at'; const orderDirection = sorting.length > 0 ? (sorting[0].desc ? 'DESC' : 'ASC') : 'DESC'; - + filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; - + const response = await GetData(`${API_URL}/transactiontype/list`, { limit: limit, page: page + 1, @@ -281,4 +280,4 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React }; export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; -export type { TransferType }; \ No newline at end of file +export type { TransferType };