import { useCallback, useEffect, useRef, useState } from 'react'; import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; import { NumericFormat } from 'react-number-format'; import { Alert, Container, DataGridColumnHeader, DataGridInner, KeenIcon, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; import { Dialog, DialogBody, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Button } from '@/components/ui/button'; import { toast } from 'sonner'; import { doSaveLogActivity } from '@/actions/GlobalActions'; import { getAuth } from '@/auth'; import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { apiConfig } from '@/config/api.config'; interface TransactionTypeProps { id: string; name: string; } interface WalletProps { id: string; name: string; } interface CustomerProps { id: string; username: string; msisdn: string; } const API_URL = apiConfig.service_transaction; const API_URL_MASTER_DATA = apiConfig.service_master_data; const API_URL_CUSTOMER = apiConfig.service_customer; const AddFeeDialog = () => { const parentRef = useRef(null); const { reload } = useDataGrid(); const { PostData, PutData, GetData } = useCallApi(); const { showAddFeeDialog, handleAddFeeDialog, handleEditFeeDialog, selectedTransferFee, transactionTypeId } = useManageTransferFeeContext(); const [customerSearchTerm, setCustomerSearchTerm] = useState(''); const [open, setOpen] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' }); const [transactionTypes, setTransactionTypes] = useState([]); const [wallets, setWallets] = useState([]); 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 })); const [openDeductOrigin, setOpenDeductOrigin] = useState(false); const [openCreditDestination, setOpenCreditDestination] = useState(false); const [errors, setErrors] = useState>({}); const initialState = { name: '', description: '', transaction_type: '', minimum_amount: 0, maximum_amount: 0, period_start: '', period_end: '', deduct_amount: 0, deduct_percentage: 0, status: '', status_include: '', created_by: '', created_at: '', deduct_from: '', deduct_origin: '00000000-0000-0000-0000-000000000000', deduct_from_account: '', credit_to: '', credit_destination: '00000000-0000-0000-0000-000000000000', credit_destination_account: '', deduct_when: 'A' }; const [formField, setFormField] = useState(initialState); const resetForm = () => { setFormField(initialState); setTransactionTypeName(''); }; const handleCloseDialog = () => { setFormField(initialState); setAlert({ show: false, message: '' }); setCustomerSearchTerm(''); setOpenCreditDestination(false); setOpenDeductOrigin(false); setOpen(false); handleEditFeeDialog(false, null); }; const [isSubmitting, setIsSubmitting] = useState(false); const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false); const parsedUser = getAuth()?.user; useEffect(() => { if (showAddFeeDialog && transactionTypeId) { setIsLoadingTransactionType(true); setFormField((prev) => ({ ...prev, transaction_type: transactionTypeId })); const getTransactionTypeDetails = async () => { try { const response = await GetData( `${API_URL}/transactiontype/getdata/${transactionTypeId}`, {} ); if (response?.status && response?.data) { setTransactionTypeName(response.data.name); } } catch (error) { console.error('Error fetching transaction type details', error); } finally { setIsLoadingTransactionType(false); } }; getTransactionTypeDetails(); } }, [showAddFeeDialog, transactionTypeId, GetData]); useEffect(() => { if (!showAddFeeDialog) { setCustomerSearchTerm(''); setOpen(false); } }, [showAddFeeDialog]); useEffect(() => { const created_time = new Date(); const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); if (showAddFeeDialog) { setFormField((prev) => ({ ...prev, created_by: parsedUser?.username, created_at: formattedTime })); } }, [showAddFeeDialog, parsedUser?.username]); useEffect(() => { if (!showAddFeeDialog) return; const getTransactionTypeList = async (sorting: any) => { setIsLoadingTransactionType(true); try { sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; const response = await GetData(`${API_URL}/transactiontype/list`, { limit: 100, page: 1, with_deleted: false, order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); setTransactionTypes(response?.data.list || []); } catch (error) { console.error('Error fetching transaction types', error); } finally { setIsLoadingTransactionType(false); } }; getTransactionTypeList([{ id: 'id', desc: false }]); }, [showAddFeeDialog, GetData]); const fetchWallets = useCallback(async () => { setIsLoadingWallets(true); const params = { limit: 100, page: 1, with_deleted: false, order_field: 'Wallets.name', order_direction: 'ASC' }; try { const response = await GetData(`${API_URL_MASTER_DATA}/wallet/list`, params); if (response?.status && response?.data) { setWallets(response.data.list); } else { setWallets([]); } } catch (error) { console.error('Error fetching wallets', error); setWallets([]); } finally { setIsLoadingWallets(false); } }, [GetData]); useEffect(() => { if (!showAddFeeDialog) return; fetchWallets(); }, [showAddFeeDialog, fetchWallets]); useEffect(() => { if (!showAddFeeDialog) return; const getCustomerList = async (sorting: any) => { setIsLoadingCustomers(true); try { sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { limit: 100, page: 1, with_deleted: false, order_field: sorting[0].id, order_direction: sorting[0].desc ? 'DESC' : 'ASC' }); const customerList = response?.data.list || []; setCustomers(customerList); if (customerList.length > 0) { setDefaultCustomer(customerList[0].id); } } catch (error) { console.error('Error fetching customers', error); setCustomers([]); } finally { setIsLoadingCustomers(false); } }; getCustomerList([{ id: 'id', desc: false }]); }, [showAddFeeDialog, GetData]); const doCreateTransferType = useCallback( async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); const requiredFields = [ 'name', 'description', 'period_start', 'period_end', 'transaction_type', 'status', 'status_include', 'deduct_from', 'deduct_from_account', '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, ' ')}` }); setIsSubmitting(false); return; } } if (formField.credit_to === 'I' && !formField.credit_destination) { setAlert({ show: true, message: 'Credit destination is required when Input Customer is selected' }); setIsSubmitting(false); return; } if (formField.deduct_from === 'I' && !formField.deduct_origin) { setAlert({ show: true, message: 'Deduct Origin is required when Input 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'; } if (formField.deduct_from !== 'I') { payload.deduct_origin = '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}`, action: 'C' }; doSaveLogActivity(createActivity); } else { setAlert({ show: true, message: response?.message || 'Failed to create transfer fee' }); } } catch (error) { console.error('Error creating transfer fee', error); setAlert({ show: true, message: 'An error occurred while creating the transfer fee' }); } finally { setIsSubmitting(false); } }, [formField, PostData, reload, handleAddFeeDialog] ); const renderSelectWithLoading = ( value: string, onChangeHandler: (value: string) => void, options: { id: string; name: string }[] | null, placeholder: string, isLoading: boolean ) => { return ( ); }; useEffect(() => { if (formField.status_include === 'N') { setFormField((prev) => ({ ...prev, deduct_when: 'A' })); } }, [formField.status_include]); return ( { if (!open) { handleAddFeeDialog(open); handleCloseDialog(); } }} >

Add Transfer Fee

{ handleAddFeeDialog(false); resetForm(); }} >
{alert.show && (

{alert.message}

)}
{transactionTypeId ? (
{isLoadingTransactionType && (
Loading transaction type...
)}
) : ( renderSelectWithLoading( formField.transaction_type, (transaction_type) => setFormField((prev) => ({ ...prev, transaction_type })), transactionTypes, 'Select Transaction Type', isLoadingTransactionType ) )}
setFormField((prev) => ({ ...prev, name: target.value })) } />
setFormField((prev) => ({ ...prev, description: target.value })) } />
{ setFormField((prev) => ({ ...prev, minimum_amount: values.floatValue || 0 })); }} placeholder="Enter Minimum Amount" />
{ setFormField((prev) => ({ ...prev, maximum_amount: values.floatValue || 0 })); }} placeholder="Enter Maximum Amount" />
setFormField((prev) => ({ ...prev, period_start: target.value })) } />
setFormField((prev) => ({ ...prev, period_end: target.value })) } />
{ setFormField((prev) => ({ ...prev, deduct_amount: values.floatValue || 0 })); }} placeholder="Enter Deduct Amount" />
{ setFormField((prev) => ({ ...prev, deduct_percentage: values.floatValue || 0 })); }} placeholder="Enter Deduct Percentage" />
{formField.deduct_from === 'I' && (
setOpenDeductOrigin(!openDeductOrigin)} > {customers.find((customer) => customer.id === formField.deduct_origin) ?.username || 'Search customer...'}
{openDeductOrigin && (
setCustomerSearchTerm(e.target.value)} autoComplete="off" onClick={(e) => e.stopPropagation()} autoFocus />
{customers .filter( (customer) => customer.username .toLowerCase() .includes(customerSearchTerm.toLowerCase()) || customer.msisdn.includes(customerSearchTerm) ) .map((customer) => (
{ setFormField({ ...formField, deduct_origin: customer.id }); setOpenDeductOrigin(false); }} > {customer.username}
))} {customers.filter( (customer) => customer.username .toLowerCase() .includes(customerSearchTerm.toLowerCase()) || customer.msisdn.includes(customerSearchTerm) ).length === 0 && (
No customer found
)}
)}
)}
{renderSelectWithLoading( formField.deduct_from_account, (value) => setFormField({ ...formField, deduct_from_account: value }), wallets, 'Select Wallet', isLoadingWallets )}
{formField.credit_to === 'I' && (
setOpenCreditDestination(!openCreditDestination)} > {customers.find( (customer) => customer.id === formField.credit_destination )?.username || 'Search customer...'}
{openCreditDestination && (
setCustomerSearchTerm(e.target.value)} autoComplete="off" onClick={(e) => e.stopPropagation()} autoFocus />
{customers .filter( (customer) => customer.username .toLowerCase() .includes(customerSearchTerm.toLowerCase()) || customer.msisdn.includes(customerSearchTerm) ) .map((customer) => (
{ setFormField({ ...formField, credit_destination: customer.id }); setOpenCreditDestination(false); }} > {customer.username}
))} {customers.filter( (customer) => customer.username .toLowerCase() .includes(customerSearchTerm.toLowerCase()) || customer.msisdn.includes(customerSearchTerm) ).length === 0 && (
No customer found
)}
)}
)}
{renderSelectWithLoading( formField.credit_destination_account, (value) => setFormField({ ...formField, credit_destination_account: value }), wallets, 'Select Wallet', isLoadingWallets )}
{formField.status_include === 'Y' && (
)}
); }; export default AddFeeDialog;