fixing tranfer fee

This commit is contained in:
bagusajisaputroo
2025-05-19 13:58:47 +07:00
parent ec5cc4ea37
commit 6bbaa3e94d
2 changed files with 169 additions and 161 deletions

View File

@ -90,6 +90,10 @@ const AddFeeDialog = () => {
id: customer.id, id: customer.id,
name: customer.username name: customer.username
})); }));
const [openDeductOrigin, setOpenDeductOrigin] = useState(false);
const [openCreditDestination, setOpenCreditDestination] = useState(false);
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({});
const initialState = { const initialState = {
name: '', name: '',
@ -120,6 +124,16 @@ const AddFeeDialog = () => {
setTransactionTypeName(''); 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 [isSubmitting, setIsSubmitting] = useState(false);
const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false); const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false);
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
@ -376,7 +390,15 @@ const AddFeeDialog = () => {
}; };
return ( return (
<Dialog open={showAddFeeDialog} onOpenChange={(open) => handleAddFeeDialog(open)}> <Dialog
open={showAddFeeDialog}
onOpenChange={(open) => {
if (!open) {
handleAddFeeDialog(open);
handleCloseDialog();
}
}}
>
<DialogContent className="container-fixed max-w-[1080px] flex flex-col p-5 overflow-hidden [&>button]:hidden"> <DialogContent className="container-fixed max-w-[1080px] flex flex-col p-5 overflow-hidden [&>button]:hidden">
<DialogTitle></DialogTitle> <DialogTitle></DialogTitle>
<DialogDescription></DialogDescription> <DialogDescription></DialogDescription>
@ -595,16 +617,15 @@ const AddFeeDialog = () => {
<div className="relative"> <div className="relative">
<div <div
className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer" className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer"
onClick={() => setOpen(!open)} onClick={() => setOpenDeductOrigin(!openDeductOrigin)}
> >
<span className="truncate"> <span className="truncate">
{customers.find((customer) => customer.id === formField.deduct_origin) {customers.find((customer) => customer.id === formField.deduct_origin)
?.username || 'Search customer...'} ?.username || 'Search customer...'}
</span> </span>
<path d="m6 9 6 6 6-6"></path>
</div> </div>
{open && ( {openDeductOrigin && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg"> <div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b"> <div className="sticky top-0 bg-white p-2 border-b">
<Input <Input
@ -632,11 +653,8 @@ const AddFeeDialog = () => {
key={customer.id} key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100" className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => { onClick={() => {
setFormField({ setFormField({ ...formField, deduct_origin: customer.id });
...formField, setOpenDeductOrigin(false);
deduct_origin: customer.id
});
setOpen(false);
}} }}
> >
{customer.username} {customer.username}
@ -706,17 +724,16 @@ const AddFeeDialog = () => {
<div className="relative"> <div className="relative">
<div <div
className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer" className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer"
onClick={() => setOpen(!open)} onClick={() => setOpenCreditDestination(!openCreditDestination)}
> >
<span className="truncate"> <span className="truncate">
{customers.find( {customers.find(
(customer) => customer.id === formField.credit_destination (customer) => customer.id === formField.credit_destination
)?.username || 'Search customer...'} )?.username || 'Search customer...'}
</span> </span>
<path d="m6 9 6 6 6-6"></path>
</div> </div>
{open && ( {openCreditDestination && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg"> <div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b"> <div className="sticky top-0 bg-white p-2 border-b">
<Input <Input
@ -748,7 +765,7 @@ const AddFeeDialog = () => {
...formField, ...formField,
credit_destination: customer.id credit_destination: customer.id
}); });
setOpen(false); setOpenCreditDestination(false);
}} }}
> >
{customer.username} {customer.username}

View File

@ -1,4 +1,3 @@
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { NumericFormat } from 'react-number-format'; import { NumericFormat } from 'react-number-format';
import { import {
@ -62,6 +61,8 @@ const EditFeeDialog = () => {
const { reload } = useDataGrid(); const { reload } = useDataGrid();
const { GetData, PutData } = useCallApi(); const { GetData, PutData } = useCallApi();
const parsedUser = getAuth()?.user; const parsedUser = getAuth()?.user;
const [openDeductOrigin, setOpenDeductOrigin] = useState(false);
const [openCreditDestination, setOpenCreditDestination] = useState(false);
const [wallets, setWallets] = useState<WalletProps[]>([]); const [wallets, setWallets] = useState<WalletProps[]>([]);
const [customers, setCustomers] = useState<CustomerProps[]>([]); const [customers, setCustomers] = useState<CustomerProps[]>([]);
@ -326,7 +327,8 @@ const EditFeeDialog = () => {
status_include: response.data.status_include || '', status_include: response.data.status_include || '',
deduct_from: response.data.deduct_from || '', deduct_from: response.data.deduct_from || '',
deduct_from_account: response.data.deduct_from_account?.id || '', deduct_from_account: response.data.deduct_from_account?.id || '',
deduct_origin: response.data.deduct_origin?.id || '00000000-0000-0000-0000-000000000000', deduct_origin:
response.data.deduct_origin?.id || '00000000-0000-0000-0000-000000000000',
credit_to: response.data.credit_to || '', credit_to: response.data.credit_to || '',
credit_destination: credit_destination:
response.data.credit_destination?.id || '00000000-0000-0000-0000-000000000000', response.data.credit_destination?.id || '00000000-0000-0000-0000-000000000000',
@ -361,22 +363,24 @@ const EditFeeDialog = () => {
hasFetchedRef.current = false; hasFetchedRef.current = false;
} }
}, [selectedTransferFee, showEditFeeDialog, fetchTransactionFee]); }, [selectedTransferFee, showEditFeeDialog, fetchTransactionFee]);
const handleCloseDialog = () => { const handleCloseDialog = () => {
setFormField(initialState); setFormField(initialState);
setAlert({ show: false, message: '' }); setAlert({ show: false, message: '' });
setCustomerSearchTerm(''); setCustomerSearchTerm('');
setOpenCreditDestination(false);
setOpenDeductOrigin(false);
setOpen(false); setOpen(false);
handleEditFeeDialog(false, null); handleEditFeeDialog(false, null);
}; };
useEffect(() => { useEffect(() => {
if (!showEditFeeDialog) { if (!showEditFeeDialog) {
setCustomerSearchTerm(''); setCustomerSearchTerm('');
setOpen(false); setOpen(false);
} }
}, [showEditFeeDialog]); }, [showEditFeeDialog]);
const renderSelectWithLoading = ( const renderSelectWithLoading = (
value: string, value: string,
onChangeHandler: (value: string) => void, onChangeHandler: (value: string) => void,
@ -645,78 +649,68 @@ const EditFeeDialog = () => {
</Select> </Select>
</div> </div>
{formField.deduct_from === 'I' && ( {formField.deduct_from === 'I' && (
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">
Deduct Origin <span className="text-red-500">*</span> Deduct Origin <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
<div <div
className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer" className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer"
onClick={() => setOpen(!open)} onClick={() => setOpenDeductOrigin(!openDeductOrigin)}
> >
<span className="truncate"> <span className="truncate">
{customers.find((customer) => customer.id === formField.deduct_origin) {customers.find((customer) => customer.id === formField.deduct_origin)?.username || 'Search customer...'}
?.username || 'Search customer...'} </span>
</span> </div>
<path d="m6 9 6 6 6-6"></path>
</div> {openDeductOrigin && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(
(customer) =>
customer.username.toLowerCase().includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map((customer) => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({ ...formField, deduct_origin: customer.id });
setOpenDeductOrigin(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(
(customer) =>
customer.username.toLowerCase().includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">No customer found</div>
)}
</div>
</div>
)}
</div>
</div>
)}
{open && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map((customer) => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({
...formField,
deduct_origin: customer.id
});
setOpen(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">
No customer found
</div>
)}
</div>
</div>
)}
</div>
</div>
)}
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">
@ -756,79 +750,76 @@ const EditFeeDialog = () => {
</Select> </Select>
</div> </div>
{formField.credit_to === 'I' && ( {formField.credit_to === 'I' && (
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">
Credit Destination <span className="text-red-500">*</span> Credit Destination <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
<div <div
className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer" className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer"
onClick={() => setOpen(!open)} onClick={() => setOpenCreditDestination(!openCreditDestination)}
> >
<span className="truncate"> <span className="truncate">
{customers.find( {customers.find((customer) => customer.id === formField.credit_destination)
(customer) => customer.id === formField.credit_destination ?.username || 'Search customer...'}
)?.username || 'Search customer...'} </span>
</span> </div>
<path d="m6 9 6 6 6-6"></path>
</div> {openCreditDestination && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map((customer) => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({
...formField,
credit_destination: customer.id
});
setOpenCreditDestination(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">No customer found</div>
)}
</div>
</div>
)}
</div>
</div>
)}
{open && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map((customer) => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({
...formField,
credit_destination: customer.id
});
setOpen(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">
No customer found
</div>
)}
</div>
</div>
)}
</div>
</div>
)}
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">