From 59205afad9442cfac243459f6f982e4d24326b47 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Sat, 17 May 2025 18:14:16 +0700 Subject: [PATCH 01/43] Adding "B", "M",, and "A" --- src/pages/transfer/transfertype/blocks/AddDialog.tsx | 3 +++ src/pages/transfer/transfertype/blocks/EditDialog.tsx | 3 +++ src/pages/transfer/transfertype/blocks/ListToolBar.tsx | 3 +++ .../transfertype/hooks/ManageTransferTypeContext.tsx | 10 ++++++---- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/pages/transfer/transfertype/blocks/AddDialog.tsx b/src/pages/transfer/transfertype/blocks/AddDialog.tsx index f29bfdc..dd4a50e 100644 --- a/src/pages/transfer/transfertype/blocks/AddDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/AddDialog.tsx @@ -561,6 +561,9 @@ const AddDialog = () => { Top Up Patner Reward Purchase Loja + Top Up P24 + Transfer Agent + Withdraw Agent {errors.status_kind && ( diff --git a/src/pages/transfer/transfertype/blocks/EditDialog.tsx b/src/pages/transfer/transfertype/blocks/EditDialog.tsx index 3f71dd1..85d4f67 100644 --- a/src/pages/transfer/transfertype/blocks/EditDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/EditDialog.tsx @@ -759,6 +759,9 @@ const EditDialog = () => { Top Up Patner Reward Purchase Loja + Top Up P24 + Transfer Agent + Withdraw Agent {errors.status_kind && ( diff --git a/src/pages/transfer/transfertype/blocks/ListToolBar.tsx b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx index e8ab157..b281c29 100644 --- a/src/pages/transfer/transfertype/blocks/ListToolBar.tsx +++ b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx @@ -207,6 +207,9 @@ const ListToolbar = () => { Top Up Patner Reward Purchase Loja + Top Up P24 + Transfer Agent + Withdraw Agent diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx index e2d121a..ad13ccb 100644 --- a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -278,7 +278,10 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React U: { label: 'Top Up', className: 'bg-yellow-100 text-yellow-600' }, N: { label: 'Top Up Patner', className: 'bg-purple-100 text-purple-600' }, E: { label: 'Reward', className: 'bg-rose-100 text-rose-600' }, - L: { label: 'Purchase Loja', className: 'bg-rose-100 text-rose-600' } + L: { label: 'Purchase Loja', className: 'bg-rose-100 text-rose-600' }, + B: { label: 'Top Up P24', className: 'bg-rose-100 text-rose-600' }, + A: { label: 'Transfer Agent', className: 'bg-rose-100 text-rose-600' }, + M: { label: 'Withdraw Agent', className: 'bg-rose-100 text-rose-600' } }; const kindInfo = mapping[kind] || { @@ -371,12 +374,11 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React filterObject['wallet_destination.name'] = filter.value; } else if (filter.id === 'status_kind') { filterObject[filter.id] = filter.value; - } else if(filter.id === 'status_approval'){ + } else if (filter.id === 'status_approval') { filterObject[filter.id] = filter.value; } else if (filter.id === 'type') { filterObject[filter.id] = filter.value; - } - else { + } else { filterObject[filter.id] = filter.value.toLowerCase(); } } From 665922aec59a08164b3022874e520bd609a24f4a Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Sun, 18 May 2025 00:07:09 +0700 Subject: [PATCH 02/43] remove fee_amount on transfer fee --- .../transfer/transferfee/blocks/AddDialog.tsx | 20 +------------------ .../transferfee/blocks/EditDialog.tsx | 20 ------------------- .../hooks/ManageTransferFeeContext.tsx | 8 -------- 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx index 3e2a99e..a071e35 100644 --- a/src/pages/transfer/transferfee/blocks/AddDialog.tsx +++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx @@ -101,7 +101,6 @@ const AddFeeDialog = () => { period_end: '', deduct_amount: 0, deduct_percentage: 0, - fee_amount: 0, priority: '', status: '', status_include: '', @@ -114,7 +113,6 @@ const AddFeeDialog = () => { credit_destination_account: '' }; - const [formField, setFormField] = useState(initialState); const resetForm = () => { @@ -554,23 +552,7 @@ const AddFeeDialog = () => { placeholder="Enter Deduct Percentage" /> -
- - { - setFormField((prev) => ({ - ...prev, - fee_amount: values.floatValue || 0 - })); - }} - placeholder="Enter Fee Amount" - /> -
+
-
- - { - setFormField((prev) => ({ - ...prev, - fee_amount: values.floatValue || 0 - })); - }} - placeholder="Enter Fee Amount" - /> -
-
-
- - -
+
-
- - -
+
+ */} + {transactionDetails?.kind == 'P' && ( + + )} + - + {transactionDetails?.kind !== 'P' && ( + + )} + - - + {transactionDetails?.kind !== 'P' && ( + + )} + + {transactionDetails?.kind !== 'P' && ( + + )} +
{/* Tab Content */} @@ -281,8 +321,16 @@ const DetailTransaction = () => { kind = 'TOP UP'; } else if (transactionDetails?.kind === 'R') { kind = 'RETURN'; - }else if (transactionDetails?.kind === 'E') { + } else if (transactionDetails?.kind === 'E') { kind = 'REWARD'; + } else if (transactionDetails?.kind === 'L') { + kind = 'PURCHASE LOJA'; + } else if (transactionDetails?.kind === 'B') { + kind = 'TOP UP P24'; + } else if (transactionDetails?.kind === 'A') { + kind = 'TRANSFER AGENT'; + } else if (transactionDetails?.kind === 'M') { + kind = 'WITHDRAWAL AGENT'; } return kind; })()} @@ -338,59 +386,60 @@ const DetailTransaction = () => { )} - {activeTab === 'detail' && ( -
-

- Product Information - - Product Info - -

-
-
-

Product Name

-

- {transactionDetails?.purchase?.product?.name ?? "-"} -

-
-
-

Price Cash

-

- {transactionDetails?.purchase?.product?.price_cash != null - ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) - : "-"} -

-
-
-

Price Point

-

- {transactionDetails?.purchase?.product?.price_point ?? "-"} -

-
-
-

Product Type

-

- {transactionDetails?.purchase?.product?.type ?? "-"} -

-
-
-

Provider Name

-

- {transactionDetails?.purchase?.product?.provider?.description ?? "-"} -

-
-
-

Provider Type

-

- {transactionDetails?.purchase?.product?.provider?.type === "h2h" - ? "HOST TO HOST" - : transactionDetails?.purchase?.product?.provider?.type === "agent" - ? "AGENT" + + {activeTab === 'detail' && transactionDetails?.kind == 'P' && ( +

+

+ Product Information + + Product Info + +

+
+
+

Product Name

+

+ {transactionDetails?.purchase?.product?.name ?? "-"} +

+
+
+

Price Cash

+

+ {transactionDetails?.purchase?.product?.price_cash != null + ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) : "-"} -

+

+
+
+

Price Point

+

+ {transactionDetails?.purchase?.product?.price_point ?? "-"} +

+
+
+

Product Type

+

+ {transactionDetails?.purchase?.product?.type ?? "-"} +

+
+
+

Provider Name

+

+ {transactionDetails?.purchase?.product?.provider?.description ?? "-"} +

+
+
+

Provider Type

+

+ {transactionDetails?.purchase?.product?.provider?.type === "h2h" + ? "HOST TO HOST" + : transactionDetails?.purchase?.product?.provider?.type === "agent" + ? "AGENT" + : "-"} +

+
-
)} {activeTab === 'detail' && transactionDetails?.kind != 'P' && transactionDetails?.transfer != null && ( @@ -463,7 +512,7 @@ const DetailTransaction = () => { kind = 'TOP UP'; } else if (transactionDetails?.kind === 'R') { kind = 'RETURN'; - }else if (transactionDetails?.kind === 'E') { + } else if (transactionDetails?.kind === 'E') { kind = 'REWARD'; } return kind; @@ -592,7 +641,7 @@ const DetailTransaction = () => {
)} - {activeTab === 'destinationwallet' && ( + {activeTab === 'destinationwallet' && transactionDetails?.kind?.trim()?.toUpperCase() !== 'P' && (

Destination Wallet

@@ -651,7 +700,7 @@ const DetailTransaction = () => { Type Request Date Response Date - Response Body + {/* Response Body */} Response Code Request Endpoint @@ -683,8 +732,18 @@ const DetailTransaction = () => { hour12: false }) : ''} - {log.request_body} - {log.response_body} + {/* {log.request_body} */} + +
+                                                        
                                                         {log.request_endpoint}
                                                     
                                                 ))
@@ -701,7 +760,7 @@ const DetailTransaction = () => {
                             
)} - {activeTab === 'approve' && ( + {activeTab === 'approve' && transactionDetails?.kind == "P" && (

Approval Logs

{transactionDetails?.log_approve.length === 0 ? ( @@ -777,7 +836,7 @@ const DetailTransaction = () => { Type Request Date Response Date - Response Body + {/* Response Body */} Response Code Request Endpoint @@ -810,8 +869,18 @@ const DetailTransaction = () => { hour12: false }) : ''} - {log.request_body} - {log.response_body} + {/* {log.request_body} */} + +
+                                                            
                                                             {log.request_endpoint ?? '-'}
                                                         
                                                     ))
diff --git a/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx b/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
index 342c24e..413b7ef 100644
--- a/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
+++ b/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
@@ -178,6 +178,10 @@ const ListToolbar = () => {
               RETURN
               TOP UP PARTNER
               REWARD
+              PURCHASE LOJA
+              TOP UP P24
+              TRANSFER AGENT
+              WITHDRAWAL AGENT
             
           
 
diff --git a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
index bfd2355..61c9de6 100644
--- a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
+++ b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
@@ -78,6 +78,10 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
             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'; 
             default: return '_';
           }
         },

From ec5cc4ea37c64c824333ebf8c3ce86c0ac533067 Mon Sep 17 00:00:00 2001
From: bagusajisaputroo 
Date: Mon, 19 May 2025 13:36:10 +0700
Subject: [PATCH 08/43] adding deduct origin on transfer fee

---
 .../transfer/transferfee/blocks/AddDialog.tsx |  98 +++++++++++++++-
 .../transferfee/blocks/EditDialog.tsx         | 109 +++++++++++++++++-
 .../hooks/ManageTransferFeeContext.tsx        |  28 ++++-
 3 files changed, 222 insertions(+), 13 deletions(-)

diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx
index ff0ff5a..f6a736e 100644
--- a/src/pages/transfer/transferfee/blocks/AddDialog.tsx
+++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx
@@ -106,6 +106,7 @@ const AddFeeDialog = () => {
     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',
@@ -296,6 +297,14 @@ const AddFeeDialog = () => {
         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 };
@@ -304,6 +313,9 @@ const AddFeeDialog = () => {
         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);
 
@@ -557,7 +569,13 @@ const AddFeeDialog = () => {
                   
                   
                 
+ {formField.deduct_from === 'I' && ( +
+ +
+
setOpen(!open)} + > + + {customers.find((customer) => customer.id === formField.deduct_origin) + ?.username || 'Search customer...'} + + +
+ + {open && ( +
+
+ 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 + }); + setOpen(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, @@ -580,6 +672,7 @@ const AddFeeDialog = () => { isLoadingWallets )}
+
)} +
+ {formField.deduct_from === 'I' && ( +
+ +
+
setOpen(!open)} + > + + {customers.find((customer) => customer.id === formField.deduct_origin) + ?.username || 'Search customer...'} + + +
+ + {open && ( +
+
+ 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 + }); + setOpen(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, @@ -630,7 +730,6 @@ const EditFeeDialog = () => { isLoadingWallets )}
-
- -
+ */} + {transactionDetails?.kind == 'P' && ( + + )} + - + {transactionDetails?.kind !== 'P' && ( + + )} + - - + {transactionDetails?.kind !== 'P' && ( + + )} + + {transactionDetails?.kind !== 'P' && ( + + )} +
{/* Tab Content */} @@ -281,8 +321,16 @@ const DetailTransaction = () => { kind = 'TOP UP'; } else if (transactionDetails?.kind === 'R') { kind = 'RETURN'; - }else if (transactionDetails?.kind === 'E') { + } else if (transactionDetails?.kind === 'E') { kind = 'REWARD'; + } else if (transactionDetails?.kind === 'L') { + kind = 'PURCHASE LOJA'; + } else if (transactionDetails?.kind === 'B') { + kind = 'TOP UP P24'; + } else if (transactionDetails?.kind === 'A') { + kind = 'TRANSFER AGENT'; + } else if (transactionDetails?.kind === 'M') { + kind = 'WITHDRAWAL AGENT'; } return kind; })()} @@ -338,59 +386,60 @@ const DetailTransaction = () => { )} - {activeTab === 'detail' && ( -
-

- Product Information - - Product Info - -

-
-
-

Product Name

-

- {transactionDetails?.purchase?.product?.name ?? "-"} -

-
-
-

Price Cash

-

- {transactionDetails?.purchase?.product?.price_cash != null - ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) - : "-"} -

-
-
-

Price Point

-

- {transactionDetails?.purchase?.product?.price_point ?? "-"} -

-
-
-

Product Type

-

- {transactionDetails?.purchase?.product?.type ?? "-"} -

-
-
-

Provider Name

-

- {transactionDetails?.purchase?.product?.provider?.description ?? "-"} -

-
-
-

Provider Type

-

- {transactionDetails?.purchase?.product?.provider?.type === "h2h" - ? "HOST TO HOST" - : transactionDetails?.purchase?.product?.provider?.type === "agent" - ? "AGENT" + + {activeTab === 'detail' && transactionDetails?.kind == 'P' && ( +

+

+ Product Information + + Product Info + +

+
+
+

Product Name

+

+ {transactionDetails?.purchase?.product?.name ?? "-"} +

+
+
+

Price Cash

+

+ {transactionDetails?.purchase?.product?.price_cash != null + ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) : "-"} -

+

+
+
+

Price Point

+

+ {transactionDetails?.purchase?.product?.price_point ?? "-"} +

+
+
+

Product Type

+

+ {transactionDetails?.purchase?.product?.type ?? "-"} +

+
+
+

Provider Name

+

+ {transactionDetails?.purchase?.product?.provider?.description ?? "-"} +

+
+
+

Provider Type

+

+ {transactionDetails?.purchase?.product?.provider?.type === "h2h" + ? "HOST TO HOST" + : transactionDetails?.purchase?.product?.provider?.type === "agent" + ? "AGENT" + : "-"} +

+
-
)} {activeTab === 'detail' && transactionDetails?.kind != 'P' && transactionDetails?.transfer != null && ( @@ -463,7 +512,7 @@ const DetailTransaction = () => { kind = 'TOP UP'; } else if (transactionDetails?.kind === 'R') { kind = 'RETURN'; - }else if (transactionDetails?.kind === 'E') { + } else if (transactionDetails?.kind === 'E') { kind = 'REWARD'; } return kind; @@ -592,7 +641,7 @@ const DetailTransaction = () => {
)} - {activeTab === 'destinationwallet' && ( + {activeTab === 'destinationwallet' && transactionDetails?.kind?.trim()?.toUpperCase() !== 'P' && (

Destination Wallet

@@ -651,7 +700,7 @@ const DetailTransaction = () => { Type Request Date Response Date - Response Body + {/* Response Body */} Response Code Request Endpoint @@ -683,8 +732,18 @@ const DetailTransaction = () => { hour12: false }) : ''} - {log.request_body} - {log.response_body} + {/* {log.request_body} */} + +
+                                                        
                                                         {log.request_endpoint}
                                                     
                                                 ))
@@ -701,7 +760,7 @@ const DetailTransaction = () => {
                             
)} - {activeTab === 'approve' && ( + {activeTab === 'approve' && transactionDetails?.kind == "P" && (

Approval Logs

{transactionDetails?.log_approve.length === 0 ? ( @@ -777,7 +836,7 @@ const DetailTransaction = () => { Type Request Date Response Date - Response Body + {/* Response Body */} Response Code Request Endpoint @@ -810,8 +869,18 @@ const DetailTransaction = () => { hour12: false }) : ''} - {log.request_body} - {log.response_body} + {/* {log.request_body} */} + +
+                                                            
                                                             {log.request_endpoint ?? '-'}
                                                         
                                                     ))
diff --git a/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx b/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
index 342c24e..413b7ef 100644
--- a/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
+++ b/src/pages/transaction/history-transaction/blocks/ListToolbar.tsx
@@ -178,6 +178,10 @@ const ListToolbar = () => {
               RETURN
               TOP UP PARTNER
               REWARD
+              PURCHASE LOJA
+              TOP UP P24
+              TRANSFER AGENT
+              WITHDRAWAL AGENT
             
           
 
diff --git a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
index bfd2355..61c9de6 100644
--- a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
+++ b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx
@@ -78,6 +78,10 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
             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'; 
             default: return '_';
           }
         },

From fecb55328e03b648836ae19f69c1bf3bd32e35e2 Mon Sep 17 00:00:00 2001
From: wayanrivan 
Date: Mon, 19 May 2025 14:13:29 +0700
Subject: [PATCH 11/43] update

---
 .../blocks/DetailApprovalTransaction.tsx      | 34 ++++++++++++++++---
 .../hooks/ApprovalTransactionContext.tsx      |  6 +++-
 .../blocks/DetailTransaction.tsx              | 30 ++++++++++++++--
 .../hooks/TransactionContext.tsx              | 16 +++++++--
 4 files changed, 75 insertions(+), 11 deletions(-)

diff --git a/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx b/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx
index dd878f6..82c4c59 100644
--- a/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx
+++ b/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx
@@ -223,6 +223,7 @@ const DetailApprovalTransaction = () => {
                                             {(() => {
                                                 let status;
                                                 let badgeClass;
+
                                                 if (transactionDetails?.status === 'C') {
                                                     status = 'COMPLETE';
                                                     badgeClass = 'bg-green-100 text-green-800';
@@ -232,9 +233,15 @@ const DetailApprovalTransaction = () => {
                                                 } else if (transactionDetails?.status === 'O') {
                                                     status = 'ON PROCESS';
                                                     badgeClass = 'bg-blue-100 text-blue-800';
-                                                } else {
+                                                } else if (transactionDetails?.status === 'P') {
                                                     status = 'PENDING';
                                                     badgeClass = 'bg-gray-100 text-gray-800';
+                                                } else if (transactionDetails?.status === 'R') {
+                                                    status = 'ROLLBACK';
+                                                    badgeClass = 'bg-yellow-100 text-yellow-800';
+                                                } else if (transactionDetails?.status === 'S') {
+                                                    status = 'REVERSAL';
+                                                    badgeClass = 'bg-purple-100 text-purple-800';
                                                 }
 
                                                 return (
@@ -261,7 +268,7 @@ const DetailApprovalTransaction = () => {
                                                     kind = 'TOP UP';
                                                 } else if (transactionDetails?.kind === 'R') {
                                                     kind = 'RETURN';
-                                                }else if (transactionDetails?.kind === 'E') {
+                                                } else if (transactionDetails?.kind === 'E') {
                                                     kind = 'REWARD';
                                                 }
                                                 return kind;
@@ -419,16 +426,33 @@ const DetailApprovalTransaction = () => {
                                         

{(() => { let status; + let badgeClass; + if (transactionDetails?.status === 'C') { status = 'COMPLETE'; + badgeClass = 'bg-green-100 text-green-800'; } else if (transactionDetails?.status === 'F') { status = 'FAILED'; + badgeClass = 'bg-red-100 text-red-800'; } else if (transactionDetails?.status === 'O') { status = 'ON PROCESS'; - } else { + badgeClass = 'bg-blue-100 text-blue-800'; + } else if (transactionDetails?.status === 'P') { status = 'PENDING'; + badgeClass = 'bg-gray-100 text-gray-800'; + } else if (transactionDetails?.status === 'R') { + status = 'ROLLBACK'; + badgeClass = 'bg-yellow-100 text-yellow-800'; + } else if (transactionDetails?.status === 'S') { + status = 'REVERSAL'; + badgeClass = 'bg-purple-100 text-purple-800'; } - return status; + + return ( + + {status} + + ); })()}

@@ -447,7 +471,7 @@ const DetailApprovalTransaction = () => { kind = 'TOP UP'; } else if (transactionDetails?.kind === 'R') { kind = 'RETURN'; - }else if (transactionDetails?.kind === 'E') { + } else if (transactionDetails?.kind === 'E') { kind = 'REWARD'; } return kind; diff --git a/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx b/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx index 9ec95fa..666b219 100644 --- a/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx +++ b/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx @@ -158,11 +158,15 @@ const ApprovalTransactionProvider = ({ children }: { children: React.ReactNode } }, { accessorFn: (row) => { + switch (row.status) { case 'C': return 'COMPLETE'; case 'F': return 'FAILED'; case 'O': return 'ON PROCESS'; - default: return 'PENDING'; + case "P" : return 'PENDING'; + case 'R': return 'ROLLBACK'; + case 'S': return 'REVERSAL'; + default: return 'UNKNOWN'; } }, id: 'status', diff --git a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx index 0c91626..2e12cf1 100644 --- a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx @@ -283,6 +283,7 @@ const DetailTransaction = () => { {(() => { let status; let badgeClass; + if (transactionDetails?.status === 'C') { status = 'COMPLETE'; badgeClass = 'bg-green-100 text-green-800'; @@ -292,9 +293,15 @@ const DetailTransaction = () => { } else if (transactionDetails?.status === 'O') { status = 'ON PROCESS'; badgeClass = 'bg-blue-100 text-blue-800'; - } else { + } else if (transactionDetails?.status === 'P') { status = 'PENDING'; badgeClass = 'bg-gray-100 text-gray-800'; + } else if (transactionDetails?.status === 'R') { + status = 'ROLLBACK'; + badgeClass = 'bg-yellow-100 text-yellow-800'; + } else if (transactionDetails?.status === 'S') { + status = 'REVERSAL'; + badgeClass = 'bg-purple-100 text-purple-800'; } return ( @@ -484,16 +491,33 @@ const DetailTransaction = () => {

{(() => { let status; + let badgeClass; + if (transactionDetails?.status === 'C') { status = 'COMPLETE'; + badgeClass = 'bg-green-100 text-green-800'; } else if (transactionDetails?.status === 'F') { status = 'FAILED'; + badgeClass = 'bg-red-100 text-red-800'; } else if (transactionDetails?.status === 'O') { status = 'ON PROCESS'; - } else { + badgeClass = 'bg-blue-100 text-blue-800'; + } else if (transactionDetails?.status === 'P') { status = 'PENDING'; + badgeClass = 'bg-gray-100 text-gray-800'; + } else if (transactionDetails?.status === 'R') { + status = 'ROLLBACK'; + badgeClass = 'bg-yellow-100 text-yellow-800'; + } else if (transactionDetails?.status === 'S') { + status = 'REVERSAL'; + badgeClass = 'bg-purple-100 text-purple-800'; } - return status; + + return ( + + {status} + + ); })()}

diff --git a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx index 61c9de6..8f2a12c 100644 --- a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx +++ b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx @@ -81,7 +81,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { case 'L': return 'PURCHASE LOJA'; case 'B': return 'TOP UP P24'; case 'A': return 'TRANSFER AGENT'; - case 'M': return 'WITHDRAWAL AGENT'; + case 'M': return 'WITHDRAWAL AGENT'; default: return '_'; } }, @@ -201,10 +201,22 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { label = 'ON PROCESS'; badgeClass = 'bg-blue-100 text-blue-800'; break; - default: + case 'P': label = 'PENDING'; badgeClass = 'bg-gray-100 text-gray-800'; break; + case 'R': + label = 'ROLLBACK'; + badgeClass = 'bg-yellow-100 text-yellow-800'; + break; + case 'S': + label = 'REVERSAL'; + badgeClass = 'bg-purple-100 text-purple-800'; + break; + default: + label = ''; + badgeClass = 'bg-gray-100 text-gray-800'; + break; } return ( From c753fb45f023e44390d85f7b3a4b289d4c083297 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 19 May 2025 13:36:10 +0700 Subject: [PATCH 12/43] adding deduct origin on transfer fee --- .../transfer/transferfee/blocks/AddDialog.tsx | 98 +++++++++++++++- .../transferfee/blocks/EditDialog.tsx | 109 +++++++++++++++++- .../hooks/ManageTransferFeeContext.tsx | 28 ++++- 3 files changed, 222 insertions(+), 13 deletions(-) diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx index ff0ff5a..f6a736e 100644 --- a/src/pages/transfer/transferfee/blocks/AddDialog.tsx +++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx @@ -106,6 +106,7 @@ const AddFeeDialog = () => { 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', @@ -296,6 +297,14 @@ const AddFeeDialog = () => { 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 }; @@ -304,6 +313,9 @@ const AddFeeDialog = () => { 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); @@ -557,7 +569,13 @@ const AddFeeDialog = () => { + {formField.deduct_from === 'I' && ( +
+ +
+
setOpen(!open)} + > + + {customers.find((customer) => customer.id === formField.deduct_origin) + ?.username || 'Search customer...'} + + +
+ + {open && ( +
+
+ 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 + }); + setOpen(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, @@ -580,6 +672,7 @@ const AddFeeDialog = () => { isLoadingWallets )}
+
)} +
+ {formField.deduct_from === 'I' && ( +
+ +
+
setOpen(!open)} + > + + {customers.find((customer) => customer.id === formField.deduct_origin) + ?.username || 'Search customer...'} + + +
+ + {open && ( +
+
+ 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 + }); + setOpen(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, @@ -630,7 +730,6 @@ const EditFeeDialog = () => { isLoadingWallets )}
-
- -
*/} + */} + - )} + {/* {transactionDetails?.kind == 'P' && ( */} + + {/* )} */}
+ )} {activeTab === 'p24' && (
From f6f16d37b213694dea0dfa99cfb60d24bd142109 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Mon, 19 May 2025 16:29:33 +0700 Subject: [PATCH 23/43] add new card in dashboard --- .../dashboards/home/DashboardHomePage.tsx | 37 ++++++++++- .../dashboards/home/blocks/BankSaldo.tsx | 62 +++++++++++++++++++ .../hooks/ApprovalTransactionContext.tsx | 1 + 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/pages/dashboards/home/blocks/BankSaldo.tsx diff --git a/src/pages/dashboards/home/DashboardHomePage.tsx b/src/pages/dashboards/home/DashboardHomePage.tsx index b10125f..7b6f1d7 100644 --- a/src/pages/dashboards/home/DashboardHomePage.tsx +++ b/src/pages/dashboards/home/DashboardHomePage.tsx @@ -23,6 +23,7 @@ import { apiConfig } from '@/config/api.config'; import TransactionValue from './blocks/TransactionValue'; import TransactionPieChart from './blocks/TransactionPieChart'; import MemberActivity from './blocks/MemberActivity'; +import BankSaldo from './blocks/BankSaldo'; // sum -> nominal, count-> total type CountType = 'sum' | 'count'; @@ -57,6 +58,8 @@ const DashboardHomePage = () => { const API_URL = apiConfig.api_dashboard; const { GetData } = useCallApi(); + const API_URL_BANK = apiConfig.service_wallet; + const [responseStatisticCard, setResponseStatisticCard] = useState(null); const fetchData = async () => { @@ -64,10 +67,21 @@ const DashboardHomePage = () => { setResponseStatisticCard(res); }; + const [bankaccount, setbankaccount] = useState(null); + + const fetchDataBankAccount = async () => { + const res = await GetData(`${API_URL_BANK}/dashboard/balance/account/${getAuth()?.user?.customer?.id}`, {}); + setbankaccount(res); + }; + useEffect(() => { fetchData(); }, []); + useEffect(() => { + fetchDataBankAccount(); + }, []); + const [responseGraphic, setresponseGraphic] = useState(null); useEffect(() => { @@ -253,8 +267,29 @@ const DashboardHomePage = () => {
) : null} +
+ + + {/* */} +
+ {/* Cards */} -
+
{ + return ( +
+
+
+
+

{title}

+ +
+
+ {new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }).format(parseFloat(balance))} +
+
+
+ Credit Limit: + {creditLimit} +
+
+ Monthly Limit: + {monthlyLimit} +
+
+
+
+ ); +}; + +interface AccountCardsProps { + accounts: AccountCardProps[]; +} + +export const AccountCards = ({ accounts }: AccountCardsProps) => { + return ( +
+ {accounts.map((account, index) => ( + + ))} +
+ ); +}; + +export default BankSaldo diff --git a/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx b/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx index 666b219..30c2afd 100644 --- a/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx +++ b/src/pages/transaction/approval-transaction/hooks/ApprovalTransactionContext.tsx @@ -13,6 +13,7 @@ import DetailApprovalTransaction from '../blocks/DetailApprovalTransaction'; import ApprovalDialog from '../blocks/ApprovalDialog'; import { Button } from '@/components/ui/button'; +import { getAuth } from '@/auth'; interface ApprovalTransactionProps { id: number; From 1a6bf1bab90a86af9be8cf73a42ac7d41b5fe421 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Mon, 19 May 2025 18:38:11 +0700 Subject: [PATCH 24/43] update homepage --- .../dashboards/home/DashboardHomePage.tsx | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/pages/dashboards/home/DashboardHomePage.tsx b/src/pages/dashboards/home/DashboardHomePage.tsx index 7b6f1d7..0353ee8 100644 --- a/src/pages/dashboards/home/DashboardHomePage.tsx +++ b/src/pages/dashboards/home/DashboardHomePage.tsx @@ -268,24 +268,19 @@ const DashboardHomePage = () => { ) : null}
- - - {/* */} + {bankaccount?.data && bankaccount?.data.length > 0 ? ( + bankaccount?.data.map((bankaccountdatas: { amount: string, creditlimit: string, monthlylimit: string; wallet: string; }, index: number) => ( + + )) + ) : ( + "" + )} +
{/* Cards */} From ff333b8f98678185f5f5457aef19cf7c24ca501e Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Mon, 19 May 2025 19:32:21 +0700 Subject: [PATCH 25/43] disbursement fixing --- .../blocks/DetailTransaction.tsx | 317 ++++++++++++------ .../blocks/DetailTransactionLog.tsx | 262 +++++++++------ .../blocks/UploadBatchDialog.tsx | 100 ++++-- .../hooks/TransactionContext.tsx | 59 ++-- 4 files changed, 489 insertions(+), 249 deletions(-) diff --git a/src/pages/disbursement/history-transaction/blocks/DetailTransaction.tsx b/src/pages/disbursement/history-transaction/blocks/DetailTransaction.tsx index 65c070c..b288d0a 100644 --- a/src/pages/disbursement/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/disbursement/history-transaction/blocks/DetailTransaction.tsx @@ -5,15 +5,15 @@ import { useCallApi } from '@/hooks'; import { apiConfig } from '@/config/api.config'; import { useEffect, useState } from 'react'; import moment from 'moment'; +import { getAuth } from '@/auth'; +import { toast } from 'sonner'; import { Dialog, DialogBody, DialogContent, - DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; -import TransactionLogViewer from './DetailTransactionLog'; const API_URL = apiConfig.service_disbursement; @@ -57,6 +57,7 @@ const DetailTransaction = () => { const [transactionDetails, setTransactionDetails] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [isExporting, setIsExporting] = useState(false); useEffect(() => { const fetchTransactionDetails = async () => { @@ -69,7 +70,6 @@ const DetailTransaction = () => { id: selectedTransactionId } ); - // console.log(response?.data); setTransactionDetails(response?.data); } catch (error) { console.error('Error fetching transaction', error); @@ -84,8 +84,6 @@ const DetailTransaction = () => { } }, [showDetailDialog, selectedTransactionId, GetData]); - const [activeTab, setActiveTab] = useState('detail'); // 'detail', 'log', 'approve' - const resetForm = () => { setTransactionDetails(null); }; @@ -96,109 +94,230 @@ const DetailTransaction = () => { } }, [showDetailDialog]); +const handleExport = async () => { + if (!selectedTransactionId || !transactionDetails) return; + + setIsExporting(true); + try { + const response = await fetch( + `${API_URL}/transaction/export?id_disbursment=${selectedTransactionId}`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${getAuth()?.access_token}` + } + } + ); + + if (!response.ok) { + throw new Error('Failed to fetch file'); + } + + const blob = await response.blob(); + const contentDisposition = response.headers.get('content-disposition'); + + const executionDate = transactionDetails.execution_date; + const formattedDate = executionDate + ? moment(executionDate).format('YYYYMMDD_HHmm') + : moment().format('YYYYMMDD_HHmm'); + + let filename = `transaction_${formattedDate}.xlsx`; + + if (contentDisposition) { + const filenameMatch = contentDisposition.match(/filename\*?=(?:UTF-8'')?"?([^;"\n]*)"?/); + if (filenameMatch && filenameMatch[1]) { + filename = decodeURIComponent(filenameMatch[1]); + } + } + + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + a.click(); + window.URL.revokeObjectURL(url); + + toast.success('Export successful'); + } catch (error) { + console.error('Error exporting transaction:', error); + toast.error('Failed to export transaction'); + } finally { + setIsExporting(false); + } +}; + + return ( - - - Transaction Details + + + Transaction Details - {/* Tab Content */} -
-
-
- {isLoading ? ( -
-
-
-
-
-
-
-
+
+ {/* Summary Info */} + {transactionDetails && ( +
+
+

Filename Upload

+

{transactionDetails.file_name ?? '-'}

+
+
+

Total Amount

+

{transactionDetails.amount ?? '-'}

+
+
+

Total Record

+

+ {transactionDetails.total_record ?? '-'} +

+
+
+

Success Record

+

+ {transactionDetails.total_success ?? '-'} +

+
+
+

Fail Record

+

{transactionDetails.total_fail ?? '-'}

+
+
+

Pending Record

+

+ {transactionDetails.total_pending ?? '-'} +

+
+
+

Status

+

+ {renderStatusBadge(transactionDetails.status)} +

+
+
+

Execution Date

+

+ {transactionDetails.execution_date + ? moment(transactionDetails.execution_date).format('DD/MM/YYYY HH:mm') + : '-'} +

+
+
+

Done Date

+

+ {transactionDetails.done_date + ? moment(transactionDetails.done_date).format('DD/MM/YYYY HH:mm') + : '-'} +

+
+
+ )} + + {/* Log Table */} +
+ {isLoading ? ( +
+
+
+
+
+
+
-

Loading Logs Details...

- ) : ( - - - - - - - - - - - - - - {transactionDetails?.log && transactionDetails.log.length > 0 ? ( - transactionDetails.log.map( - ( - log: { - id: number; - customer: any; - amount: number; - remark: string; - reference: string; - request_date: string; - payment_response: string; - status: string; - }, - index: number - ) => ( - - - - - - - - - - ) - ) - ) : ( - - + + + )} + +
UsernameFullnameAmountStatusProcess Date - Invoice Number - Actions
- {log.customer?.username ?? 'Not Found'} - - {log.customer?.fullname ?? 'Not Found'} - - {log.amount ?? '-'} - - {renderStatusBadge(log.status) ?? '-'} - - {log.request_date && moment(log.request_date).isValid() - ? moment(log.request_date).format('DD/MM/YYYY HH:mm:ss') - : '-'} - - {log.reference ?? '-'} - -
- -
-
- No logs available +

Loading Logs Details...

+ + ) : ( + + + + + + + + + + + + + + + + + {transactionDetails?.log && transactionDetails.log.length > 0 ? ( + transactionDetails.log.map((log: any, index: number) => ( + + + + + + + + + + + - )} - -
UsernameFullnameAmountStatusProcess DateInvoice NumberRemark 1Remark 2Remark 3Actions
+ {log.customer?.username ?? 'Not Found'} + + {log.customer?.fullname ?? 'Not Found'} + {log.amount ?? '-'} + {renderStatusBadge(log.status) ?? '-'} + + {log.request_date && moment(log.request_date).isValid() + ? moment(log.request_date).format('DD/MM/YYYY HH:mm') + : '-'} + + {log.reference ?? '-'} + {log.remark_1 ?? '-'}{log.remark_2 ?? '-'}{log.remark_3 ?? '-'} +
+ )) + ) : ( +
+ No logs available +
+ )} +
+ + {/* Export Button - Moved to bottom right after table */} +
+
+
@@ -207,4 +326,4 @@ const DetailTransaction = () => { ); }; -export default DetailTransaction; +export default DetailTransaction; \ No newline at end of file diff --git a/src/pages/disbursement/history-transaction/blocks/DetailTransactionLog.tsx b/src/pages/disbursement/history-transaction/blocks/DetailTransactionLog.tsx index 3c24c1a..00c58ab 100644 --- a/src/pages/disbursement/history-transaction/blocks/DetailTransactionLog.tsx +++ b/src/pages/disbursement/history-transaction/blocks/DetailTransactionLog.tsx @@ -1,21 +1,13 @@ -import React, { useState } from 'react'; +import React from 'react'; import moment from 'moment'; import { useTransactionContext } from '../hooks/useTransactionContext'; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogBody } from '@/components/ui/dialog'; - -interface LogType { - id: string; - amount: number; - remark: string; - reference: string; - response_date: string; - status: string; - customer?: { - username: string; - fullname: string; - }; - payment_response?: string; -} +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogBody +} from '@/components/ui/dialog'; type StatusCode = 'W' | 'O' | 'F' | 'D'; @@ -29,97 +21,171 @@ const statusMap: Record = { W: { label: 'Waiting Schedule', bg: 'bg-yellow-100', text: 'text-yellow-600' }, O: { label: 'On Process', bg: 'bg-blue-100', text: 'text-blue-600' }, F: { label: 'Fail', bg: 'bg-red-100', text: 'text-red-600' }, - D: { label: 'Done', bg: 'bg-green-100', text: 'text-green-600' }, + D: { label: 'Done', bg: 'bg-green-100', text: 'text-green-600' } }; export const renderStatusBadge = (statusRaw: string | null | undefined) => { - const status = statusRaw as StatusCode; - const { label, bg, text } = statusMap[status] ?? { - label: 'Unknown', - bg: 'bg-gray-100', - text: 'text-gray-600', - }; - - return ( - - {label} - - ); + const status = statusRaw as StatusCode; + const { label, bg, text } = statusMap[status] ?? { + label: 'Unknown', + bg: 'bg-gray-100', + text: 'text-gray-600' }; + return ( + {label} + ); +}; + const TransactionLogViewer = () => { - const { - showDetailLogDialog, - setShowDetailLogDialog, - detailLogData - } = useTransactionContext(); + const { showDetailLogDialog, setShowDetailLogDialog, detailLogData } = useTransactionContext(); return ( - - - Detail Record - - - {/* Tab Content */} - {detailLogData && detailLogData != null ? ( -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ID{detailLogData.customer.id}
Username{detailLogData.customer.username}
Name{detailLogData.customer.fullname}
Amount{detailLogData.amount}
Remark{detailLogData.remark}
Payment Request
{detailLogData.payment_request}
Payment Response
{detailLogData.payment_response}
Status{renderStatusBadge(detailLogData.status)}
Prosess Date{detailLogData.request_date && moment(detailLogData.request_date).isValid() ? moment(detailLogData.request_date).format('DD/MM/YYYY HH:mm:ss') : '-'}
Response Date{detailLogData.response_date && moment(detailLogData.response_date).isValid() ? moment(detailLogData.response_date).format('DD/MM/YYYY HH:mm:ss') : '-'}
Reference Number{detailLogData.reference}
-
-
-
- ) : (
)} -
-
+ + + Detail Record + + + {detailLogData ? ( +
+
+
+ + + + + + + {detailLogData.customer && ( + <> + + + + + + + + + + + + + {detailLogData.customer.email && ( + + + + + )} + {detailLogData.customer.bank_name && ( + + + + + )} + {detailLogData.customer.bank_account && ( + + + + + )} + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Log ID{detailLogData.id}
Customer ID + {detailLogData.customer.id} +
Username + {detailLogData.customer.username} +
Fullname + {detailLogData.customer.fullname} +
Email + {detailLogData.customer.email} +
Bank Name + {detailLogData.customer.bank_name} +
Bank Account + {detailLogData.customer.bank_account} +
Amount{detailLogData.amount}
Remark{detailLogData.remark}
Remark 1 + {detailLogData.remark_1} +
Remark 2 + {detailLogData.remark_2} +
Remark 3 + {detailLogData.remark_3} +
Reference Number + {detailLogData.reference ?? '-'} +
Payment Request +
+                            {detailLogData.payment_request ?? '-'}
+                          
+
Payment Response +
+                            {detailLogData.payment_response ?? '-'}
+                          
+
Status + {renderStatusBadge(detailLogData.status)} +
Request Date + {detailLogData.request_date && + moment(detailLogData.request_date).isValid() + ? moment(detailLogData.request_date).format('DD/MM/YYYY HH:mm:ss') + : '-'} +
Response Date + {detailLogData.response_date && + moment(detailLogData.response_date).isValid() + ? moment(detailLogData.response_date).format('DD/MM/YYYY HH:mm:ss') + : '-'} +
+
+
+
+ ) : ( +
No data available
+ )} +
+
); }; diff --git a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx index e6ccabf..15bc730 100644 --- a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx +++ b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx @@ -27,23 +27,28 @@ import clsx from 'clsx'; import { RefreshCw } from 'lucide-react'; const API_URL = apiConfig.service_disbursement; +const API_URL_TRANSACTION = apiConfig.service_transaction; +interface TransferType { + id: string; + name: string; + type: string; +} const UploadBatchDialog = () => { const parentRef = useRef(null); const { showUploadBatchDialog, handleUploadBatchDialog } = useTransactionContext(); const { reload } = useDataGrid(); - const { PostData, PostDataFile, GetData } = useCallApi(); + const { PostDataFile, GetData } = useCallApi(); + const [isSubmitting, setIsSubmitting] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - const initialState: { - execution_date: string; - file: File | null; - } = { + const [alert, setAlert] = useState({ show: false, message: '' }); + + const [transferTypes, setTransferTypes] = useState([]); + + const initialState = { execution_date: '', - file: null + file: null as File | null, + id_transaction_type: '' }; const [formField, setFormField] = useState(initialState); @@ -52,14 +57,17 @@ const UploadBatchDialog = () => { setAlert({ show: false, message: '' }); }; - /* actions */ const doUploadBatch = useCallback( async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); const formData = new FormData(); - formData.append('execution_date', formField.execution_date); + const localDate = new Date(formField.execution_date); + const newDate = localDate.toISOString(); + + formData.append('execution_date', newDate); + formData.append('id_transaction_type', formField.id_transaction_type); if (formField.file) { formData.append('file', formField.file); @@ -67,9 +75,7 @@ const UploadBatchDialog = () => { try { const response = await PostDataFile(`${API_URL}/upload-excel`, formData, { - headers: { - 'Content-Type': 'multipart/form-data' - } + headers: { 'Content-Type': 'multipart/form-data' } }); if (response?.status) { @@ -102,26 +108,52 @@ const UploadBatchDialog = () => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - console.log('Form data before submit:', formField); - - if (formField.execution_date.trim() === '' || formField.file === null) { + if ( + formField.execution_date.trim() === '' || + formField.file === null || + formField.id_transaction_type.trim() === '' + ) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } doUploadBatch(e); - // console.log(formField); setAlert({ show: false, message: '' }); }; useEffect(() => { if (showUploadBatchDialog === false) { resetForm(); + return; } + + const fetchTransferTypes = async () => { + try { + const response = await GetData(`${API_URL_TRANSACTION}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'id', + order_direction: 'ASC', + filter: JSON.stringify({}) + }); + + const validTypes = ['DM', 'DA', 'DE']; + const records: TransferType[] = response?.data?.list ?? []; + + const filtered = records.filter((item) => validTypes.includes(item.type)); + + setTransferTypes(filtered); + } catch (error) { + console.error('Failed to fetch transfer types', error); + } + }; + + fetchTransferTypes(); }, [showUploadBatchDialog]); return ( - handleUploadBatchDialog(open)}> + @@ -129,7 +161,6 @@ const UploadBatchDialog = () => {

Upload Batch

-
{

{alert.message}

)} -
+
@@ -182,6 +213,31 @@ const UploadBatchDialog = () => { />
+
+
+ + +
+
)} - {transactionDetails?.kind !== 'P' && ( - - )} - - {transactionDetails?.kind !== 'P' && ( - - )} - - {transactionDetails?.kind !== 'P' && ( - - )} {transactionDetails?.kind !== 'P' && (