393 lines
13 KiB
TypeScript
393 lines
13 KiB
TypeScript
import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components';
|
|
import { Toaster } from '@/components/ui/sonner';
|
|
import { apiConfig } from '@/config/api.config';
|
|
import { useCallApi } from '@/hooks';
|
|
import { ColumnDef } from '@tanstack/react-table';
|
|
import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
|
|
import ListToolbar from '../blocks/ListToolBar';
|
|
import DeleteDialog from '../blocks/DeleteDialog';
|
|
import { EditFeeDialog } from '../blocks/EditDialog';
|
|
import { useManageTransferTypeContext } from '../../transfertype/hooks/useManageTransferTypeContext';
|
|
|
|
interface ContextProps {
|
|
showEditFeeDialog: boolean;
|
|
handleEditFeeDialog: (show: boolean, selected_TransferFee: string | null) => void;
|
|
showAddFeeDialog: boolean;
|
|
handleAddFeeDialog: (show: boolean) => void;
|
|
handleDeleteFeeDialog: (show: boolean, selected_TransferFee: string | null) => void;
|
|
showDeleteFeeDialog: boolean;
|
|
selectedTransferFee: string | null;
|
|
transactionTypeId: string | null;
|
|
}
|
|
|
|
const initialProps: ContextProps = {
|
|
showEditFeeDialog: false,
|
|
handleEditFeeDialog: () => {},
|
|
showAddFeeDialog: false,
|
|
handleAddFeeDialog: () => {},
|
|
showDeleteFeeDialog: false,
|
|
handleDeleteFeeDialog: () => {},
|
|
selectedTransferFee: null,
|
|
transactionTypeId: null
|
|
};
|
|
|
|
interface TransferFeeProps {
|
|
name: string;
|
|
description: string;
|
|
minimum_amount: number;
|
|
maximum_amount: number;
|
|
period_start: string;
|
|
period_end: string;
|
|
deduct_amount: number;
|
|
deduct_percentage: number;
|
|
transaction_type: string;
|
|
status: string;
|
|
status_include: string;
|
|
fee: number;
|
|
}
|
|
|
|
const ManageTransferFeeContext = createContext<ContextProps>(initialProps);
|
|
const API_URL = apiConfig.service_transaction;
|
|
|
|
const ManageTransferFeeContextProvider = ({
|
|
children,
|
|
transactionTypeId = null
|
|
}: {
|
|
children: React.ReactNode;
|
|
transactionTypeId?: string | null;
|
|
}) => {
|
|
const [showEditFeeDialog, setShowEditFeeDialog] = useState(false);
|
|
const [showAddFeeDialog, setShowAddFeeDialog] = useState(false);
|
|
const [showDeleteFeeDialog, setShowDeleteFeeDialog] = useState(false);
|
|
const { showAddDialog, handleAddDialog, selectedTransferType } = useManageTransferTypeContext();
|
|
const [selectedTransferFee, setSelectedTransferFee] = useState<string | null>(null);
|
|
const { GetData } = useCallApi();
|
|
const handleEditFeeDialog = useCallback((show: boolean, selected_TransferFee: string | null) => {
|
|
setSelectedTransferFee(show ? selected_TransferFee : null);
|
|
setShowEditFeeDialog(show);
|
|
}, []);
|
|
|
|
const handleAddFeeDialog = useCallback((show: boolean) => {
|
|
setShowAddFeeDialog(show);
|
|
}, []);
|
|
|
|
const handleDeleteFeeDialog = useCallback(
|
|
(show: boolean, selected_TransferFee: string | null) => {
|
|
setSelectedTransferFee(show ? selected_TransferFee : null);
|
|
setShowDeleteFeeDialog(show);
|
|
},
|
|
[]
|
|
);
|
|
const doGetTransferFeeListData = async (
|
|
page: number,
|
|
limit: number,
|
|
sorting: any,
|
|
filter: any
|
|
) => {
|
|
if (!selectedTransferType) {
|
|
return { data: [], totalCount: 0 };
|
|
}
|
|
|
|
sorting = sorting.length === 0 ? [{ id: 'id', desc: false }] : sorting;
|
|
filter = filter.length === 0 ? {} : { any: filter[0].value.toLowerCase() };
|
|
|
|
try {
|
|
const response = await GetData(
|
|
`${API_URL}/transactionfees/getdatabytransactiontype/${selectedTransferType}`,
|
|
{}
|
|
);
|
|
|
|
// 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 };
|
|
}
|
|
};
|
|
|
|
const columns = useMemo<ColumnDef<any>[]>(
|
|
() => [
|
|
{
|
|
accessorFn: (row) => row.name,
|
|
id: 'name',
|
|
header: ({ column }) => <DataGridColumnHeader title="Name" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[200px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.description,
|
|
id: 'description',
|
|
header: ({ column }) => <DataGridColumnHeader title="Description" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.minimum_amount,
|
|
id: 'minimum_amount',
|
|
header: ({ column }) => <DataGridColumnHeader title="Min Amount" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[150px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.maximum_amount,
|
|
id: 'maximum_amount',
|
|
header: ({ column }) => <DataGridColumnHeader title="Max Amount" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[150px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.deduct_amount,
|
|
id: 'deduct_amount',
|
|
header: ({ column }) => <DataGridColumnHeader title="Deduct Amount" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[150px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.deduct_percentage,
|
|
id: 'deduct_percentage',
|
|
header: ({ column }) => <DataGridColumnHeader title="Deduct %" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[150px]' }
|
|
},
|
|
|
|
{
|
|
accessorFn: (row) => row.period_start?.split('T')[0],
|
|
id: 'period_start',
|
|
header: ({ column }) => <DataGridColumnHeader title="Period Start" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[200px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.period_end?.split('T')[0],
|
|
id: 'period_end',
|
|
header: ({ column }) => <DataGridColumnHeader title="Period End" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[200px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.transaction_type?.name,
|
|
id: 'transactionTypeId',
|
|
header: ({ column }) => <DataGridColumnHeader title="Transaction Type" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row: { credit_to: string }) => {
|
|
const mapping: Record<string, string> = {
|
|
D: 'Destination Member',
|
|
S: 'Source Member',
|
|
I: 'Input Customer'
|
|
};
|
|
|
|
return mapping[row.credit_to] || 'Unknown';
|
|
},
|
|
id: 'credit_to',
|
|
header: ({ column }) => <DataGridColumnHeader title="Credit To" column={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 }) => <DataGridColumnHeader title="Credit Destination" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.credit_destination_account?.description,
|
|
id: 'credit_destination_account',
|
|
header: ({ column }) => (
|
|
<DataGridColumnHeader title="Credit Destination Account" column={column} />
|
|
),
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row: { deduct_from: string }) => {
|
|
const mapping: Record<string, string> = {
|
|
D: 'Destination Member',
|
|
S: 'Source Member'
|
|
};
|
|
|
|
return mapping[row.deduct_from];
|
|
},
|
|
id: 'deduct_from',
|
|
header: ({ column }) => <DataGridColumnHeader title="Deduct From" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.deduct_from_account?.description,
|
|
id: 'deduct_from_account',
|
|
header: ({ column }) => (
|
|
<DataGridColumnHeader title="Deduct From Account" column={column} />
|
|
),
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
meta: { headerClassName: 'w-[250px]' }
|
|
},
|
|
{
|
|
accessorFn: (row) => row.priority,
|
|
id: 'priority',
|
|
header: ({ column }) => <DataGridColumnHeader title="Priority" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
cell: ({ row }) => {
|
|
const isActive = row.original.priority === 'Y';
|
|
|
|
return (
|
|
<span
|
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
|
}`}
|
|
>
|
|
{isActive ? 'Yes' : 'No'}
|
|
</span>
|
|
);
|
|
},
|
|
meta: {
|
|
headerClassName: 'w-[100px]',
|
|
cellClassName: 'text-center'
|
|
}
|
|
},
|
|
{
|
|
accessorFn: (row) => row.status,
|
|
id: 'status',
|
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
cell: ({ row }) => {
|
|
const isActive = row.original.status === 'Y';
|
|
|
|
return (
|
|
<span
|
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
|
}`}
|
|
>
|
|
{isActive ? 'Active' : 'Inactive'}
|
|
</span>
|
|
);
|
|
},
|
|
meta: {
|
|
headerClassName: 'w-[100px]',
|
|
cellClassName: 'text-center'
|
|
}
|
|
},
|
|
{
|
|
accessorFn: (row) => row.status_include,
|
|
id: 'status_include',
|
|
header: ({ column }) => <DataGridColumnHeader title="Status Include" column={column} />,
|
|
enableSorting: true,
|
|
enableHiding: false,
|
|
cell: ({ row }) => {
|
|
const isActive = row.original.status_include === 'Y';
|
|
|
|
return (
|
|
<span
|
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
|
}`}
|
|
>
|
|
{isActive ? 'Yes' : 'No'}
|
|
</span>
|
|
);
|
|
},
|
|
meta: {
|
|
headerClassName: 'w-[100px]',
|
|
cellClassName: 'text-center'
|
|
}
|
|
},
|
|
{
|
|
id: 'actions',
|
|
header: ({ column }) => <DataGridColumnHeader title="Actions" column={column} />,
|
|
enableSorting: false,
|
|
enableHiding: false,
|
|
cell: (data) => {
|
|
const row = data.row.original;
|
|
return (
|
|
<>
|
|
<button
|
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
|
onClick={() => handleEditFeeDialog(true, row.id)}
|
|
>
|
|
<KeenIcon icon="notepad-edit" />
|
|
</button>
|
|
<button
|
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
|
onClick={() => handleDeleteFeeDialog(true, row.id)}
|
|
>
|
|
<KeenIcon icon="trash" />
|
|
</button>
|
|
</>
|
|
);
|
|
},
|
|
meta: {
|
|
headerClassName: 'w-[100px]',
|
|
cellClassName: 'text-center'
|
|
}
|
|
}
|
|
],
|
|
[handleEditFeeDialog, handleDeleteFeeDialog]
|
|
);
|
|
|
|
return (
|
|
<div className="container mx-auto py-5">
|
|
<div className="flex items-center mb-5 px-5">
|
|
<h2 className="text-xl font-semibold text-gray-900">Manage Transaction Fee</h2>
|
|
</div>
|
|
<ManageTransferFeeContext.Provider
|
|
value={{
|
|
showEditFeeDialog,
|
|
handleEditFeeDialog,
|
|
showAddFeeDialog,
|
|
handleAddFeeDialog,
|
|
selectedTransferFee,
|
|
showDeleteFeeDialog,
|
|
handleDeleteFeeDialog,
|
|
transactionTypeId
|
|
}}
|
|
>
|
|
{/* <Toaster expand visibleToasts={9} duration={3000} /> */}
|
|
<DataGridProvider
|
|
columns={columns}
|
|
pagination={{ size: 10 }}
|
|
layout={{ card: true }}
|
|
toolbar={<ListToolbar />}
|
|
sorting={[{ id: 'id', desc: true }]}
|
|
serverSide={true}
|
|
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
|
|
doGetTransferFeeListData(pageIndex, pageSize, sorting, columnFilters)
|
|
}
|
|
>
|
|
{children}
|
|
</DataGridProvider>
|
|
</ManageTransferFeeContext.Provider>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { ManageTransferFeeContext, ManageTransferFeeContextProvider };
|