From 2e795ece53d2fd3f23d32be8a0564335b474332d Mon Sep 17 00:00:00 2001 From: ardiola Date: Fri, 11 Apr 2025 22:27:58 +0700 Subject: [PATCH 01/37] Add ResendTransaction component Add resend button in transactioncontext --- .gitignore | 3 + package-lock.json | 5 + package.json | 1 + .../blocks/ResendTransaction.tsx | 183 ++++++++++++ .../hooks/TransactionContext.tsx | 37 ++- yarn.lock | 269 ++++++++++++++++++ 6 files changed, 495 insertions(+), 3 deletions(-) create mode 100644 src/pages/transaction/history-transaction/blocks/ResendTransaction.tsx diff --git a/.gitignore b/.gitignore index cff2732..a93a63a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ yarn.lock .env package-lock.json +package.json +yarn.lock +package-lock.json diff --git a/package-lock.json b/package-lock.json index 87756c1..3e4da0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "https": "^1.0.0", "leaflet": "^1.9.4", "lucide-react": "^0.456.0", + "metronic-tailwind-react": "file:", "mini-svg-data-uri": "^1.4.4", "moment": "^2.30.1", "next-themes": "^0.4.3", @@ -6454,6 +6455,10 @@ "node": ">= 8" } }, + "node_modules/metronic-tailwind-react": { + "resolved": "", + "link": true + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", diff --git a/package.json b/package.json index 2e30fa9..7745b80 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "https": "^1.0.0", "leaflet": "^1.9.4", "lucide-react": "^0.456.0", + "metronic-tailwind-react": "file:", "mini-svg-data-uri": "^1.4.4", "moment": "^2.30.1", "next-themes": "^0.4.3", diff --git a/src/pages/transaction/history-transaction/blocks/ResendTransaction.tsx b/src/pages/transaction/history-transaction/blocks/ResendTransaction.tsx new file mode 100644 index 0000000..3e68622 --- /dev/null +++ b/src/pages/transaction/history-transaction/blocks/ResendTransaction.tsx @@ -0,0 +1,183 @@ +import { useTransactionContext } from '../hooks/useTransactionContext'; +import { useCallApi } from '@/hooks'; +import { apiConfig } from '@/config/api.config'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; +import { Alert, KeenIcon, useDataGrid } from '@/components'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { toast } from 'sonner'; +import { Input } from '@/components/ui/input'; + +const API_URL = apiConfig.transaction; + +const ResendTransaction = () => { + const { GetData, PostData } = useCallApi(); + // const { reload } = useDataGrid(); + const { + showResendDialog, + setShowResendDialog, + selectedTransactionRowForResend + } = useTransactionContext(); + + // const [transactionDetails, setTransactionDetails] = useState(null); + + // const [formField, setFormField] = useState({ + // transaction_code: '', + // status: '' + // }); + + console.log('selectedTransactionRowForResend', selectedTransactionRowForResend); + + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + // const doApproval = useCallback( + // async (e: React.FormEvent) => { + // e.preventDefault(); + + // if (!transactionDetails || !transactionDetails.code) { + // toast.error('Transaction data not loaded yet.'); + // return; + // } + + // if (!formField.status) { + // toast.error('Please select a status.'); + // return; + // } + + // const response = await PostData(`${API_URL}/transaction/set-approval`, { + // transaction_code: transactionDetails.code, + // status: formField.status, + // }); + + // if (response?.status) { + // setAlert((prev) => ({ ...prev, show: false, message: '' })); + // toast.success('Success Update Position'); + // const createActivity = { + // module: 'Approval Transaction', + // description: `Change status approve for transaction => ${transactionDetails.code}`, + // action: 'U' + // }; + // doSaveLogActivity(createActivity); + // setShowApprovalDialog(false); // optionally close dialog + // } else { + // setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + // } + // }, + // [formField, transactionDetails] + // ); + + // useEffect(() => { + // const fetchTransactionDetails = async () => { + // if (selectedTransactionIdForApproval) { + // try { + // const response = await GetData(`${API_URL}/transaction/history/detail/${selectedTransactionIdForApproval}`, { + // id: selectedTransactionIdForApproval + // }); + // // console.log(response?.data.code); + // // console.log(selectedTransactionIdForApproval); + // setTransactionDetails(response?.data); + // } catch (error) { + // console.error('Error fetching transaction', error); + // } + // } + // }; + + // if (showApprovalDialog && selectedTransactionIdForApproval) { + // fetchTransactionDetails(); + // } + // }, [showApprovalDialog, selectedTransactionIdForApproval, GetData]); + + return ( + setShowResendDialog(open)}> + + + + + +

Are you sure?

+ You will resend this failed transaction! +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); + + // return ( + // + // + // + // Resend Transaction + // + // + //

tes dialog

+ // {/*
+ //
+ //
+ //
+ // + + //
+ // + //
+ //
+ //
+ + + //
+ //
+ // + //
+ //
+ //
*/} + //
+ //
+ //
+ // ); +}; + +export default ResendTransaction; diff --git a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx index 5e28d8f..ca7b179 100644 --- a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx +++ b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx @@ -9,6 +9,8 @@ import ListToolbar from '../blocks/ListToolbar'; import { Button } from '@/components/ui/button'; import { useNavigate } from 'react-router'; import DetailTransaction from '../blocks/DetailTransaction'; +import { log } from 'console'; +import ResendTransaction from '../blocks/ResendTransaction'; interface TransactionProps { id: number; @@ -28,6 +30,10 @@ interface ContextProps { setShowDetailDialog: React.Dispatch>; selectedTransactionId: number | null; setSelectedTransactionId: React.Dispatch>; + showResendDialog: boolean; + setShowResendDialog: React.Dispatch>; + selectedTransactionRowForResend: any | null; + setTransactionRowForResend: React.Dispatch>; } const initialProps: ContextProps = { @@ -35,7 +41,11 @@ const initialProps: ContextProps = { showDetailDialog: false, setShowDetailDialog: () => { }, selectedTransactionId: null, - setSelectedTransactionId: () => { } + setSelectedTransactionId: () => { }, + showResendDialog: false, + setShowResendDialog: () => { }, + selectedTransactionRowForResend: null, + setTransactionRowForResend: () => { } }; const ManageTransactionContext = createContext(initialProps); @@ -50,6 +60,8 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { const handleNavigate = (path: string) => { const url = navigate(`${API_URL}/transaction/history/${path}`); }; + const [showResendDialog, setShowResendDialog] = useState(false); + const [selectedTransactionRowForResend, setTransactionRowForResend] = useState(null); const columns = useMemo[]>( () => [ @@ -84,7 +96,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { }); return formattedDateTime; // Format DD-MM-YYYY HH:MM:SS (menggunakan waktu yang sudah ada) } - }, + }, { accessorKey: 'origin_customer.fullname', header: ({ column }) => , @@ -171,6 +183,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { enableHiding: false, cell: (data) => { const row = data.row.original; + const isVisible = row.status === 'F' ? true : false || row.status === 'P' ? true : false; return (
+ {/* add new button for resend transaction failed */} + {isVisible && + + }
); }, @@ -241,11 +267,16 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { showDetailDialog, setShowDetailDialog, selectedTransactionId, - setSelectedTransactionId + setSelectedTransactionId, + showResendDialog, + setShowResendDialog, + selectedTransactionRowForResend, + setTransactionRowForResend }} > + Date: Tue, 15 Apr 2025 17:43:08 +0700 Subject: [PATCH 02/37] Adding 3 values on status transaction type field in transactiontype --- src/pages/transfer/transfertype/blocks/AddDialog.tsx | 4 ++++ src/pages/transfer/transfertype/blocks/EditDialog.tsx | 5 ++++- .../transfertype/hooks/ManageTransferTypeContext.tsx | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pages/transfer/transfertype/blocks/AddDialog.tsx b/src/pages/transfer/transfertype/blocks/AddDialog.tsx index 6e5f51f..fe6eff6 100644 --- a/src/pages/transfer/transfertype/blocks/AddDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/AddDialog.tsx @@ -467,6 +467,10 @@ const AddDialog = () => { Return Agent Merchant Return Agent Emoney Reward Point + Top Up Escrow + Top Up Master Agent + Top Up Agent + diff --git a/src/pages/transfer/transfertype/blocks/EditDialog.tsx b/src/pages/transfer/transfertype/blocks/EditDialog.tsx index 1e3ca41..1d9803b 100644 --- a/src/pages/transfer/transfertype/blocks/EditDialog.tsx +++ b/src/pages/transfer/transfertype/blocks/EditDialog.tsx @@ -589,7 +589,7 @@ const EditDialog = () => { - Disbursement + Disbursement Other Change Group Emoney Customer to Agent Change Group Emoney Agent to Customer @@ -600,6 +600,9 @@ const EditDialog = () => { Return Agent Merchant Return Agent Emoney Reward Point + Top Up Escrow + Top Up Master Agent + Top Up Agent diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx index 942ee8f..7e886a3 100644 --- a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -159,7 +159,10 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React AD: 'Return Agent Deposit', AM: 'Return Agent Merchant', AE: 'Return Agent Emoney', - R: 'Reward Point' + R: 'Reward Point', + TE:'Top Up Escrow', + TM:'Top Up Master Agent', + TA:'Top Up Agent' }; return mapping[row.type] || 'Unknown'; From a247afdea31594a50e14cf5235b646c8c21a2214 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 15 Apr 2025 17:59:15 +0700 Subject: [PATCH 03/37] fix margin --- src/pages/members/kyc/Kyc.tsx | 60 ++++++++++++++++------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/pages/members/kyc/Kyc.tsx b/src/pages/members/kyc/Kyc.tsx index b27ce0f..969db5e 100644 --- a/src/pages/members/kyc/Kyc.tsx +++ b/src/pages/members/kyc/Kyc.tsx @@ -222,41 +222,37 @@ const Kyc = () => { ) : ( '' )} -

- KYC Upgrade Members -

-
- - - Dashboard - +

KYC Upgrade Members

+ + + Dashboard + - - Members - + + Members + - - KYC Upgrade Members - - -
-
-
- } - layout={{ card: true }} - sorting={[{ id: 'created_at', desc: true }]} - serverSide={false} - onRowSelectionChange={(selected, table: any) => { - const selectedRow = table.getSelectedRowModel().rows[0]; - if (selectedRow) handleUpdate(selectedRow.original); - }} - > -
+ + KYC Upgrade Members + + + {/*
*/} +
+ } + layout={{ card: true }} + sorting={[{ id: 'created_at', desc: true }]} + serverSide={false} + onRowSelectionChange={(selected, table: any) => { + const selectedRow = table.getSelectedRowModel().rows[0]; + if (selectedRow) handleUpdate(selectedRow.original); + }} + >
+ {/*
*/} ); From f71b203eb7552f3e2c75178a0b28a96e4a9d4da5 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 15 Apr 2025 19:36:35 +0700 Subject: [PATCH 04/37] update pading and pagination on Manage Members --- .../members/manage-members/ManageMembers.tsx | 110 ++++++++---------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/src/pages/members/manage-members/ManageMembers.tsx b/src/pages/members/manage-members/ManageMembers.tsx index 0203ab4..8d27979 100644 --- a/src/pages/members/manage-members/ManageMembers.tsx +++ b/src/pages/members/manage-members/ManageMembers.tsx @@ -7,7 +7,7 @@ import axios from 'axios'; import DetailMember from './blocks/DetailMember'; import ConfirmDialog from '@/components/confirm'; import { useAuthContext } from '@/auth'; -import { DataGridInner, LoaderTransparant } from '@/components'; +import { Container, DataGridInner, LoaderTransparant } from '@/components'; import { DataGridProvider } from '@/components'; import { toast } from 'sonner'; import { Breadcrumbs, Link } from '@mui/material'; @@ -188,67 +188,59 @@ const ManageMembers = () => { TPAY | Manage Members -
-
- setDialogOpen(false)} - title="Confirm Action" - content={`Are you sure you want to ${dialogType}?`} - onYes={handleYes} - onNo={() => setDialogOpen(false)} + + setDialogOpen(false)} + title="Confirm Action" + content={`Are you sure you want to ${dialogType}?`} + onYes={handleYes} + onNo={() => setDialogOpen(false)} + /> + {member.id !== '' || dialogType === 'create' ? ( + - {member.id !== '' || dialogType === 'create' ? ( - - ) : ( - '' - )} -

- Manage Members -

-
- - - Dashboard - - - Members - + ) : ( + '' + )} +

Manage Members

+ + + Dashboard + + + Members + - - Manage Members - - -
-
-
- - } - onRowSelectionChange={(selected, table: any) => { - const selectedRow = table.getSelectedRowModel().rows[0]; - if (selectedRow) handleUpdate(selectedRow.original); - }} - > - -
-
+ + Manage Members + + + {/*
*/} +
+ } + onRowSelectionChange={(selected, table: any) => { + const selectedRow = table.getSelectedRowModel().rows[0]; + if (selectedRow) handleUpdate(selectedRow.original); + }} + >
-
+ {/*
*/} + ); }; From c51889d4401623edb86b9aa05877eb18b1a0ea29 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 15 Apr 2025 21:11:09 +0700 Subject: [PATCH 05/37] update table on manage group --- src/pages/groups/Column.tsx | 22 +++- src/pages/groups/ListToolbar.tsx | 49 +++++++ src/pages/groups/ManageGroups.tsx | 205 ++++++++++++++++-------------- 3 files changed, 178 insertions(+), 98 deletions(-) create mode 100644 src/pages/groups/ListToolbar.tsx diff --git a/src/pages/groups/Column.tsx b/src/pages/groups/Column.tsx index d796078..2f6fe7f 100644 --- a/src/pages/groups/Column.tsx +++ b/src/pages/groups/Column.tsx @@ -1,3 +1,4 @@ +import { KeenIcon } from '@/components'; import { ColumnDef } from '@tanstack/react-table'; export type Group = { @@ -8,7 +9,7 @@ export type Group = { description: string; }; -export const columns: ColumnDef[] = [ +export const getColumns = (handleUpdate: (data: any) => void): ColumnDef[] => [ { accessorKey: 'no', header: 'ID' @@ -30,8 +31,19 @@ export const columns: ColumnDef[] = [ accessorKey: 'description', header: 'Description' }, - // { - // id: 'actions', - // header: 'Actions' - // } + { + id: 'actions', + cell: ({ row }) => { + const dataMembers = row.original; + + return ( + + ); + } + } ]; diff --git a/src/pages/groups/ListToolbar.tsx b/src/pages/groups/ListToolbar.tsx new file mode 100644 index 0000000..7ab5fa4 --- /dev/null +++ b/src/pages/groups/ListToolbar.tsx @@ -0,0 +1,49 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { Button } from '@/components/ui/button'; + +const ListToolBar = ({ createGroup }: { createGroup: () => void }) => { + const { table, reload } = useDataGrid(); + + return ( +
+
+
+
+ + + + +
+
+ + + + +
+
+
+
+ ); +}; + +export { ListToolBar }; diff --git a/src/pages/groups/ManageGroups.tsx b/src/pages/groups/ManageGroups.tsx index 55ae1eb..3ba347d 100644 --- a/src/pages/groups/ManageGroups.tsx +++ b/src/pages/groups/ManageGroups.tsx @@ -1,5 +1,5 @@ import { DataTable } from '@/components/ui/DataTable'; -import { columns, Group } from './Column'; +import { getColumns, Group } from './Column'; import { apiConfig } from '@/config/api.config'; import axios, { AxiosResponse } from 'axios'; import { Helmet } from 'react-helmet'; @@ -24,6 +24,8 @@ import CloseIcon from '@mui/icons-material/Close'; import Divider from '@mui/material/Divider'; import ConfirmDialog from '@/components/confirm'; import { toast } from 'sonner'; +import { Container, DataGridProvider } from '@/components'; +import { ListToolBar } from './ListToolbar'; // import { DialogHeader } from '@/components/ui/dialog'; // import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; const BASE_URL = apiConfig.service_customer; @@ -89,9 +91,9 @@ const ManageGroups = () => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (!formData.groupName) return toast.warning(`Group name can not be empty!`) - if (!formData.status) return toast.warning(`Status can not be empty!`) - if (!formData.description) return toast.warning(`Description can not be empty!`) + if (!formData.groupName) return toast.warning(`Group name can not be empty!`); + if (!formData.status) return toast.warning(`Status can not be empty!`); + if (!formData.description) return toast.warning(`Description can not be empty!`); setIsDialogOpen(false); setDialogOpen(true); }; @@ -134,7 +136,7 @@ const ManageGroups = () => { description: formData.description, created_at: new Date() }); - toast.success(`Success create group`) + toast.success(`Success create group`); } else if (dialogType === 'update') { await axios.put(`${BASE_URL}/groups/update/${formData.id}`, { name: formData.groupName, @@ -142,14 +144,14 @@ const ManageGroups = () => { description: formData.description, updated_at: new Date() }); - toast.success(`Success update group`) + toast.success(`Success update group`); } else if (dialogType === 'delete') { await axios.delete(`${BASE_URL}/groups/delete/${formData.id}/true`); - toast.success(`Success delete group`) + toast.success(`Success delete group`); } } catch (error: any) { console.log(error); - toast.error(error.message) + toast.error(error.message); } finally { await fetchGroups(); setDialogOpen(false); @@ -162,19 +164,19 @@ const ManageGroups = () => { TPAY | Manage Group - setDialogOpen(false)} - title="Confirm Action" - content={ - `Are you sure you want to ` + - (dialogType === 'create' ? 'create?' : dialogType === 'update' ? 'update?' : 'delete?') - } - onYes={handleYes} - onNo={() => setDialogOpen(false)} - /> -

Groups

-
+ + setDialogOpen(false)} + title="Confirm Action" + content={ + `Are you sure you want to ` + + (dialogType === 'create' ? 'create?' : dialogType === 'update' ? 'update?' : 'delete?') + } + onYes={handleYes} + onNo={() => setDialogOpen(false)} + /> +

Groups

Dashboard @@ -188,84 +190,101 @@ const ManageGroups = () => { Manage Groups -
-
- */} +
+ {/* -
+ /> */} + } + layout={{ card: true }} + sorting={[{ id: 'created_at', desc: true }]} + serverSide={false} + onRowSelectionChange={(selected, table: any) => { + const selectedRow = table.getSelectedRowModel().rows[0]; + if (selectedRow) handleUpdate(selectedRow.original); + }} + /> +
+ {/*
*/} - - -
- {dialogType==='create'?"Create New Group":"Update Group"} - - - -
- -
-
-
- - -
-
- - - - } - label="Yes" - /> - } - label="No" - /> - - -
-
- - -
- -
-
-
-
+ + +
+ + {dialogType === 'create' ? 'Create New Group' : 'Update Group'} + + + + +
+ +
+
+
+ + +
+
+ + + + } + label="Yes" + /> + } + label="No" + /> + + +
+
+ + +
+ +
+
+
+
+ ); }; From de9702b1b4f2ba21a1a909143de4ffab7c7ba869 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Tue, 15 Apr 2025 21:13:38 +0700 Subject: [PATCH 06/37] update table on manage groups - remove button filter --- src/pages/groups/ListToolbar.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/groups/ListToolbar.tsx b/src/pages/groups/ListToolbar.tsx index 7ab5fa4..793f4c9 100644 --- a/src/pages/groups/ListToolbar.tsx +++ b/src/pages/groups/ListToolbar.tsx @@ -18,17 +18,17 @@ const ListToolBar = ({ createGroup }: { createGroup: () => void }) => { onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} /> - + {/* - + */}
- ); - - // return ( - // - // - // - // Resend Transaction - // - // - //

tes dialog

- // {/*
- //
- //
- //
- // - - //
- // - //
- //
- //
- - - //
- //
- // - //
- //
- //
*/} - //
- //
- //
- // ); }; export default ResendTransaction; diff --git a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx index 42bcd1b..00bbdf0 100644 --- a/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx +++ b/src/pages/transaction/history-transaction/hooks/TransactionContext.tsx @@ -11,6 +11,7 @@ import { useNavigate } from 'react-router'; import DetailTransaction from '../blocks/DetailTransaction'; import { log } from 'console'; import ResendTransaction from '../blocks/ResendTransaction'; +import { comment } from 'stylis'; interface TransactionProps { id: number; @@ -31,9 +32,8 @@ interface ContextProps { selectedTransactionId: number | null; setSelectedTransactionId: React.Dispatch>; showResendDialog: boolean; - setShowResendDialog: React.Dispatch>; - selectedTransactionRowForResend: any | null; - setTransactionRowForResend: React.Dispatch>; + handleResendDialog: (show: boolean, selected_transaction: string | null) => void; + selectedTransactionForResend: string | null; } const initialProps: ContextProps = { @@ -43,9 +43,8 @@ const initialProps: ContextProps = { selectedTransactionId: null, setSelectedTransactionId: () => { }, showResendDialog: false, - setShowResendDialog: () => { }, - selectedTransactionRowForResend: null, - setTransactionRowForResend: () => { } + handleResendDialog: (show: boolean, selected_transaction: string | null) => { }, + selectedTransactionForResend: null }; const ManageTransactionContext = createContext(initialProps); @@ -61,7 +60,13 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { const url = navigate(`${API_URL}/transaction/history/${path}`); }; const [showResendDialog, setShowResendDialog] = useState(false); - const [selectedTransactionRowForResend, setTransactionRowForResend] = useState(null); + const [selectedTransactionForResend, setSelectedTransactionForResend] = useState(null); + + const handleResendDialog = useCallback((show: boolean, selected_transaction: string | null) => { + setSelectedTransactionForResend(show ? selected_transaction : null); + setShowResendDialog(show); + }, []); + const columns = useMemo[]>( () => [ @@ -174,7 +179,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { ); }, - }, + }, { accessorKey: 'description', header: ({ column }) => , @@ -216,10 +221,9 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => { {isVisible && + {/* - - + +
) : (
)} diff --git a/src/pages/members/kyc-delete-member/hooks/ManageKycDeletionContext.tsx b/src/pages/members/kyc-delete-member/hooks/ManageKycDeletionContext.tsx index c0742fd..48e4608 100644 --- a/src/pages/members/kyc-delete-member/hooks/ManageKycDeletionContext.tsx +++ b/src/pages/members/kyc-delete-member/hooks/ManageKycDeletionContext.tsx @@ -37,7 +37,7 @@ interface ContextProps { selectedIdCustomer: string | null; detailKyc: any | null; setDetailKyc: React.Dispatch>; - handleApproveReject: (customerDeletionId: string, status_approve: string) => {}; + handleApproveReject: (customerDeletionId: string, status_approve: string) => Promise; } const initialProps: ContextProps = { @@ -50,7 +50,7 @@ const initialProps: ContextProps = { setShowDetailDialog: () => { }, detailKyc: async () => {}, setDetailKyc: () => { }, - handleApproveReject: () => ({customerDeletionId: '0', status_approve: 'Y'}), + handleApproveReject: async () => ({customerDeletionId: '0', status_approve: 'Y'}), }; const ManageKycDeletionContext = createContext(initialProps); @@ -271,7 +271,6 @@ const ManageKycDeletionContextProvider = ({ children }: { children: React.ReactN }} > - {children} + ); diff --git a/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx new file mode 100644 index 0000000..4086d51 --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx @@ -0,0 +1,105 @@ +import { Container, DataGridInner } from '@/components'; +import { TransactionDisbursementProvider } from './hooks/TransactionDisbursementContext'; +import { Breadcrumbs, Link } from '@mui/material'; +import { Helmet } from 'react-helmet'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useState } from 'react'; +import { useCallApi } from '@/hooks'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; + +const TransactionDisbursement = () => { + const [form, setForm] = useState({ + customerId: '', + amount: '', + pin: '' + }); + const { GetData, PostData } = useCallApi(); + const API_URL = apiConfig.transaction; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + console.log('Submitted Data:', form); + try { + // let requestTopup = await PostData(`${API_URL}/transaction/request-topup`, { + // amount: form.topupAmount, + // pin: form.pin + // }) + // console.log(requestTopup) + // if (requestTopup?.status == true) { + // toast.success('Success Request Topup') + // } else { + // toast.warning(`${requestTopup?.message}`) + // } + toast.warning('Failed') + } catch (error) { + toast.warning('Failed') + } + // TODO: Kirim ke backend atau proses lainnya + }; + + return ( + <> + + TPAY | Transaction Disbursement Saldo + + + +

MANAGE TRANSACTION DISBURSEMENT SALDO

+ + + Dashboard + + + Transaction + + + Disbursement Saldo + + + +
+
+ {/* form */} +
+
+ + setForm({ ...form, customerId: e.target.value })} + /> +
+
+ + setForm({ ...form, amount: e.target.value })} + /> +
+
+ + setForm({ ...form, pin: e.target.value })} + /> +
+
+ +
+
+
+
+
+
+
+ + ); +}; + +export default TransactionDisbursement; diff --git a/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx b/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx new file mode 100644 index 0000000..8b1ca90 --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx @@ -0,0 +1,105 @@ +import { + Dialog, + DialogBody, + DialogContent, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useManageKycDeletionContext } from '../hooks'; +import { apiConfig } from '@/config/api.config'; +import { useDataGrid } from '@/components'; + +const API_URL = apiConfig.service_customer; +const DetailDialog = () => { + const { showDetailDialog, setShowDetailDialog, detailKyc, handleApproveReject } = useManageKycDeletionContext(); + const { reload } = useDataGrid(); + + return ( + + + + Customer Deletion Details + + + {/* Tab Content */} + {detailKyc && detailKyc != null ? ( +
+ {generateInput(detailKyc, null, 'Group', 'group_name', 'text', false, true)} + {generateInput(detailKyc, null, 'Username', 'username', 'text', false, true)} + {generateInput(detailKyc, null, 'Full Name', 'fullname', 'text', false, true)} + {generateInput(detailKyc, null, 'Gender', 'customers_gender', 'text', false, true)} + {generateInput(detailKyc, null, 'Date of Birth', 'birthdate', 'date', false, true)} + {generateInput(detailKyc, null, 'Mother Name', 'registered_mother_fullname', 'text', false, true)} + {generateInput(detailKyc, null, 'MSISDN', 'registered_msisdn', 'text', false, true)} + {generateInput(detailKyc, null, 'Reason Deletion', 'reason_deletion', 'text', false, true)} + {generateInput(detailKyc, null, 'Reason Note', 'reason_note', 'text', false, true)} + {generateInput(detailKyc, null, 'Status Approval', 'status_approve', 'text', false, true)} + +
+ + + +
+
+ ) : (
)} +
+
+
+ ); +}; + +export default DetailDialog; + +function generateInput(formData: any, handleChange: any, label: string, name: string, type: string, required: boolean, disabled: boolean) { + function generateDate(isoString: string) { + return isoString.slice(0, 10); // "2000-01-18" + } + + type Code = 'W' | 'Y' | 'N' | 'T' | 'P' | 'D' | 'L'; + interface Reason { + label: string; + } + + const statusMap: Record = { + W: { label: 'Waiting Approval' }, + Y: { label: 'Approve' }, + N: { label: 'Reject' }, + T: { label: 'Tidak lagi menggunakan layanan' }, + P: { label: 'Privasi dan keamanan' }, + D: { label: 'Akun ganda' }, + L: { label: 'Lainnya' } + }; + if (name == 'reason_deletion' || name == 'status_approve') { + const status = formData[name] as Code + const fixStatus = statusMap[status] ?? { label: formData[name] } + formData[name] = fixStatus.label + } + return ( + <> +
+
+ + +
+
+ + ) +} \ No newline at end of file diff --git a/src/pages/transaction/disbursement-saldo/blocks/ListToolbar.tsx b/src/pages/transaction/disbursement-saldo/blocks/ListToolbar.tsx new file mode 100644 index 0000000..013a15c --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/blocks/ListToolbar.tsx @@ -0,0 +1,61 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { Button } from '@/components/ui/button'; +import { useCallback, useState, useEffect } from 'react'; +import { toast } from 'sonner'; + +const ListToolbar = () => { + const { table, reload } = useDataGrid(); + + // Set the initial state for trxDate + const [trxDate, settrxDate] = useState({ from: '', to: '' }); + + // Function to format date to YYYY-MM-DD + const formatDate = (date: Date): string => { + return date.toISOString().split('T')[0]; + }; + + // useEffect to set the default date values + useEffect(() => { + const today = new Date(); + const nextWeek = new Date(today); + nextWeek.setDate(today.getDate() + 7); + + settrxDate({ + from: formatDate(today), // Set 'from' to today + to: formatDate(nextWeek), // Set 'to' to 7 days later + }); + }, []); + + const handleFilterData = useCallback(() => { + try { + table.getColumn('transaction_date')?.setFilterValue(trxDate); + } catch (error) { + toast.error('Error applying filter'); + console.error('Error applying filter:', error); + } + }, [trxDate, table]); + + useEffect(() => { + if (trxDate.from && trxDate.to) { + handleFilterData(); + } + }, [trxDate]); + + return ( +
+
+
+
+ + + +
+
+
+
+ ); +}; + +export default ListToolbar; diff --git a/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx b/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx new file mode 100644 index 0000000..a3366be --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx @@ -0,0 +1,81 @@ +import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; +import { Toaster } from '@/components/ui/sonner'; +import { toast } from 'sonner'; +import { apiConfig } from '@/config/api.config'; +import { ColumnDef } from '@tanstack/react-table'; +import { createContext, useCallback, useMemo, useState } from 'react'; +import ListToolbar from '../blocks/ListToolbar'; +import { useCallApi } from '@/hooks'; +import moment from 'moment'; +import DetailDialog from '../blocks/DetailDialog'; + +interface TransactionDisbursementProps { + id: string; + customers_id: string; + group_id: string; + username: string; + fullname: string; + email: string; + status: string; + created_at: Date; +} + +interface ContextProps { + +} + +const initialProps: ContextProps = { + +}; + +const TransactionDisbursementContext = createContext(initialProps); +const API_URL = apiConfig.service_customer; + +type StatusCode = 'W' | 'Y' | 'N' | 'T'; + +interface StatusInfo { + label: string; + bg: string; + text: string; +} + +const statusMap: Record = { + W: { label: 'Waiting Approval', bg: 'bg-yellow-100', text: 'text-yellow-600' }, + T: { label: 'No Need', bg: 'bg-blue-100', text: 'text-blue-600' }, + N: { label: 'Reject', bg: 'bg-red-100', text: 'text-red-600' }, + Y: { label: 'Approve', 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 { reload } = useDataGrid(); + +const TransactionDisbursementProvider = ({ children }: { children: React.ReactNode }) => { + + return ( + + +
+ {children} +
+
+ ); +}; + +export { TransactionDisbursementProvider, TransactionDisbursementContext }; +export type { TransactionDisbursementProps }; diff --git a/src/pages/transaction/disbursement-saldo/hooks/index.tsx b/src/pages/transaction/disbursement-saldo/hooks/index.tsx new file mode 100644 index 0000000..2def845 --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/hooks/index.tsx @@ -0,0 +1,2 @@ +export * from './TransactionDisbursementContext'; +export * from './useTransactionTopupContext'; diff --git a/src/pages/transaction/disbursement-saldo/hooks/useTransactionDisbursementContext.tsx b/src/pages/transaction/disbursement-saldo/hooks/useTransactionDisbursementContext.tsx new file mode 100644 index 0000000..5137bc2 --- /dev/null +++ b/src/pages/transaction/disbursement-saldo/hooks/useTransactionDisbursementContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { TransactionDisbursementContext } from './TransactionDisbursementContext'; + +const useTransactionDisbursementContext = () => { + const context = useContext(TransactionDisbursementContext); + + if (!context) throw new Error('useTransactionDisbursementContext must be used within AuthProvider'); + + return context; +}; + +export { useTransactionDisbursementContext }; diff --git a/src/pages/transaction/topup/TransactionTopup.tsx b/src/pages/transaction/topup/TransactionTopup.tsx new file mode 100644 index 0000000..d6e343c --- /dev/null +++ b/src/pages/transaction/topup/TransactionTopup.tsx @@ -0,0 +1,95 @@ +import { Container, DataGridInner } from '@/components'; +import { TransactionTopupProvider } from './hooks/TransactionTopupContext'; +import { Breadcrumbs, Link } from '@mui/material'; +import { Helmet } from 'react-helmet'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useState } from 'react'; +import { useCallApi } from '@/hooks'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; + +const TransactionTopup = () => { + const [form, setForm] = useState({ + topupAmount: '', + pin: '' + }); + const { GetData, PostData } = useCallApi(); + const API_URL = apiConfig.transaction; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + console.log('Submitted Data:', form); + try { + let requestTopup = await PostData(`${API_URL}/transaction/request-topup`, { + amount: form.topupAmount, + pin: form.pin + }) + console.log(requestTopup) + if (requestTopup?.status == true) { + toast.success('Success Request Topup') + } else { + toast.warning(`${requestTopup?.message}`) + } + } catch (error) { + toast.warning('Failed') + } + // TODO: Kirim ke backend atau proses lainnya + }; + + return ( + <> + + TPAY | Transaction Topup Request + + + +

MANAGE TRANSACTION TOPUP REQUEST

+ + + Dashboard + + + Transaction + + + Topup + + + +
+
+ {/* form */} +
+
+ + setForm({ ...form, topupAmount: e.target.value })} + /> +
+
+ + setForm({ ...form, pin: e.target.value })} + /> +
+
+ +
+
+
+
+
+
+
+ + ); +}; + +export default TransactionTopup; diff --git a/src/pages/transaction/topup/blocks/DetailDialog.tsx b/src/pages/transaction/topup/blocks/DetailDialog.tsx new file mode 100644 index 0000000..8b1ca90 --- /dev/null +++ b/src/pages/transaction/topup/blocks/DetailDialog.tsx @@ -0,0 +1,105 @@ +import { + Dialog, + DialogBody, + DialogContent, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useManageKycDeletionContext } from '../hooks'; +import { apiConfig } from '@/config/api.config'; +import { useDataGrid } from '@/components'; + +const API_URL = apiConfig.service_customer; +const DetailDialog = () => { + const { showDetailDialog, setShowDetailDialog, detailKyc, handleApproveReject } = useManageKycDeletionContext(); + const { reload } = useDataGrid(); + + return ( + + + + Customer Deletion Details + + + {/* Tab Content */} + {detailKyc && detailKyc != null ? ( +
+ {generateInput(detailKyc, null, 'Group', 'group_name', 'text', false, true)} + {generateInput(detailKyc, null, 'Username', 'username', 'text', false, true)} + {generateInput(detailKyc, null, 'Full Name', 'fullname', 'text', false, true)} + {generateInput(detailKyc, null, 'Gender', 'customers_gender', 'text', false, true)} + {generateInput(detailKyc, null, 'Date of Birth', 'birthdate', 'date', false, true)} + {generateInput(detailKyc, null, 'Mother Name', 'registered_mother_fullname', 'text', false, true)} + {generateInput(detailKyc, null, 'MSISDN', 'registered_msisdn', 'text', false, true)} + {generateInput(detailKyc, null, 'Reason Deletion', 'reason_deletion', 'text', false, true)} + {generateInput(detailKyc, null, 'Reason Note', 'reason_note', 'text', false, true)} + {generateInput(detailKyc, null, 'Status Approval', 'status_approve', 'text', false, true)} + +
+ + + +
+
+ ) : (
)} +
+
+
+ ); +}; + +export default DetailDialog; + +function generateInput(formData: any, handleChange: any, label: string, name: string, type: string, required: boolean, disabled: boolean) { + function generateDate(isoString: string) { + return isoString.slice(0, 10); // "2000-01-18" + } + + type Code = 'W' | 'Y' | 'N' | 'T' | 'P' | 'D' | 'L'; + interface Reason { + label: string; + } + + const statusMap: Record = { + W: { label: 'Waiting Approval' }, + Y: { label: 'Approve' }, + N: { label: 'Reject' }, + T: { label: 'Tidak lagi menggunakan layanan' }, + P: { label: 'Privasi dan keamanan' }, + D: { label: 'Akun ganda' }, + L: { label: 'Lainnya' } + }; + if (name == 'reason_deletion' || name == 'status_approve') { + const status = formData[name] as Code + const fixStatus = statusMap[status] ?? { label: formData[name] } + formData[name] = fixStatus.label + } + return ( + <> +
+
+ + +
+
+ + ) +} \ No newline at end of file diff --git a/src/pages/transaction/topup/blocks/ListToolbar.tsx b/src/pages/transaction/topup/blocks/ListToolbar.tsx new file mode 100644 index 0000000..013a15c --- /dev/null +++ b/src/pages/transaction/topup/blocks/ListToolbar.tsx @@ -0,0 +1,61 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { Button } from '@/components/ui/button'; +import { useCallback, useState, useEffect } from 'react'; +import { toast } from 'sonner'; + +const ListToolbar = () => { + const { table, reload } = useDataGrid(); + + // Set the initial state for trxDate + const [trxDate, settrxDate] = useState({ from: '', to: '' }); + + // Function to format date to YYYY-MM-DD + const formatDate = (date: Date): string => { + return date.toISOString().split('T')[0]; + }; + + // useEffect to set the default date values + useEffect(() => { + const today = new Date(); + const nextWeek = new Date(today); + nextWeek.setDate(today.getDate() + 7); + + settrxDate({ + from: formatDate(today), // Set 'from' to today + to: formatDate(nextWeek), // Set 'to' to 7 days later + }); + }, []); + + const handleFilterData = useCallback(() => { + try { + table.getColumn('transaction_date')?.setFilterValue(trxDate); + } catch (error) { + toast.error('Error applying filter'); + console.error('Error applying filter:', error); + } + }, [trxDate, table]); + + useEffect(() => { + if (trxDate.from && trxDate.to) { + handleFilterData(); + } + }, [trxDate]); + + return ( +
+
+
+
+ + + +
+
+
+
+ ); +}; + +export default ListToolbar; diff --git a/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx b/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx new file mode 100644 index 0000000..ffe6337 --- /dev/null +++ b/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx @@ -0,0 +1,81 @@ +import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; +import { Toaster } from '@/components/ui/sonner'; +import { toast } from 'sonner'; +import { apiConfig } from '@/config/api.config'; +import { ColumnDef } from '@tanstack/react-table'; +import { createContext, useCallback, useMemo, useState } from 'react'; +import ListToolbar from '../blocks/ListToolbar'; +import { useCallApi } from '@/hooks'; +import moment from 'moment'; +import DetailDialog from '../blocks/DetailDialog'; + +interface TransactionTopupProps { + id: string; + customers_id: string; + group_id: string; + username: string; + fullname: string; + email: string; + status: string; + created_at: Date; +} + +interface ContextProps { + +} + +const initialProps: ContextProps = { + +}; + +const TransactionTopupContext = createContext(initialProps); +const API_URL = apiConfig.service_customer; + +type StatusCode = 'W' | 'Y' | 'N' | 'T'; + +interface StatusInfo { + label: string; + bg: string; + text: string; +} + +const statusMap: Record = { + W: { label: 'Waiting Approval', bg: 'bg-yellow-100', text: 'text-yellow-600' }, + T: { label: 'No Need', bg: 'bg-blue-100', text: 'text-blue-600' }, + N: { label: 'Reject', bg: 'bg-red-100', text: 'text-red-600' }, + Y: { label: 'Approve', 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 { reload } = useDataGrid(); + +const TransactionTopupProvider = ({ children }: { children: React.ReactNode }) => { + + return ( + + +
+ {children} +
+
+ ); +}; + +export { TransactionTopupProvider, TransactionTopupContext }; +export type { TransactionTopupProps }; diff --git a/src/pages/transaction/topup/hooks/index.tsx b/src/pages/transaction/topup/hooks/index.tsx new file mode 100644 index 0000000..2b919d5 --- /dev/null +++ b/src/pages/transaction/topup/hooks/index.tsx @@ -0,0 +1,2 @@ +export * from './TransactionTopupContext'; +export * from './useTransactionTopupContext'; diff --git a/src/pages/transaction/topup/hooks/useTransactionTopupContext.tsx b/src/pages/transaction/topup/hooks/useTransactionTopupContext.tsx new file mode 100644 index 0000000..cd253c2 --- /dev/null +++ b/src/pages/transaction/topup/hooks/useTransactionTopupContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { TransactionTopupContext } from './TransactionTopupContext'; + +const useTransactionTopupContext = () => { + const context = useContext(TransactionTopupContext); + + if (!context) throw new Error('useTransactionTopupContext must be used within AuthProvider'); + + return context; +}; + +export { useTransactionTopupContext }; diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index 865effb..786cd1e 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -10,6 +10,8 @@ import DashboardHomePage from '@/pages/dashboards/home/DashboardHomePage'; import ManageUserPage from '@/pages/settings/user/manage-user/ManageUserPage'; import Transaction from '@/pages/transaction/history-transaction/Transaction'; import ApprovalTransaction from '@/pages/transaction/approval-transaction/ApprovalTransaction'; +import TransactionTopup from '@/pages/transaction/topup/TransactionTopup'; +import TransactionDisbursement from '@/pages/transaction/disbursement-saldo/TransactionDisbursement'; import LogActivityPage from '@/pages/settings/user/log-activity/LogActivityPage'; import ManagePositionPage from '@/pages/settings/user/manage-position/ManagePositionPage'; import ManageAccount from '@/pages/account/manage-account/ManageAccount'; @@ -96,6 +98,8 @@ const AppRoutingSetup = (): ReactElement => { } /> } /> + } /> + } /> } /> } /> } /> From d422c05894c77ae2a757926bda2ad8e3f25c8acd Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Wed, 16 Apr 2025 01:50:45 +0700 Subject: [PATCH 14/37] fixing --- .../kyc-delete-member/ManageKycDeletion.tsx | 2 +- .../blocks/DetailDialog.tsx | 105 ------------------ .../hooks/TransactionDisbursementContext.tsx | 1 - .../disbursement-saldo/hooks/index.tsx | 2 +- .../transaction/topup/blocks/DetailDialog.tsx | 105 ------------------ .../topup/hooks/TransactionTopupContext.tsx | 1 - 6 files changed, 2 insertions(+), 214 deletions(-) delete mode 100644 src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx delete mode 100644 src/pages/transaction/topup/blocks/DetailDialog.tsx diff --git a/src/pages/members/kyc-delete-member/ManageKycDeletion.tsx b/src/pages/members/kyc-delete-member/ManageKycDeletion.tsx index 0d5962e..8a175b7 100644 --- a/src/pages/members/kyc-delete-member/ManageKycDeletion.tsx +++ b/src/pages/members/kyc-delete-member/ManageKycDeletion.tsx @@ -1,5 +1,5 @@ import { Container, DataGridInner } from '@/components'; -import { ManageKycDeletionContextProvider } from './hooks/ManageKycDeletionContext'; +import { ManageKycDeletionContextProvider } from './hooks'; import { Breadcrumbs, Link } from '@mui/material'; import { Helmet } from 'react-helmet'; diff --git a/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx b/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx deleted file mode 100644 index 8b1ca90..0000000 --- a/src/pages/transaction/disbursement-saldo/blocks/DetailDialog.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { - Dialog, - DialogBody, - DialogContent, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import { useManageKycDeletionContext } from '../hooks'; -import { apiConfig } from '@/config/api.config'; -import { useDataGrid } from '@/components'; - -const API_URL = apiConfig.service_customer; -const DetailDialog = () => { - const { showDetailDialog, setShowDetailDialog, detailKyc, handleApproveReject } = useManageKycDeletionContext(); - const { reload } = useDataGrid(); - - return ( - - - - Customer Deletion Details - - - {/* Tab Content */} - {detailKyc && detailKyc != null ? ( -
- {generateInput(detailKyc, null, 'Group', 'group_name', 'text', false, true)} - {generateInput(detailKyc, null, 'Username', 'username', 'text', false, true)} - {generateInput(detailKyc, null, 'Full Name', 'fullname', 'text', false, true)} - {generateInput(detailKyc, null, 'Gender', 'customers_gender', 'text', false, true)} - {generateInput(detailKyc, null, 'Date of Birth', 'birthdate', 'date', false, true)} - {generateInput(detailKyc, null, 'Mother Name', 'registered_mother_fullname', 'text', false, true)} - {generateInput(detailKyc, null, 'MSISDN', 'registered_msisdn', 'text', false, true)} - {generateInput(detailKyc, null, 'Reason Deletion', 'reason_deletion', 'text', false, true)} - {generateInput(detailKyc, null, 'Reason Note', 'reason_note', 'text', false, true)} - {generateInput(detailKyc, null, 'Status Approval', 'status_approve', 'text', false, true)} - -
- - - -
-
- ) : (
)} -
-
-
- ); -}; - -export default DetailDialog; - -function generateInput(formData: any, handleChange: any, label: string, name: string, type: string, required: boolean, disabled: boolean) { - function generateDate(isoString: string) { - return isoString.slice(0, 10); // "2000-01-18" - } - - type Code = 'W' | 'Y' | 'N' | 'T' | 'P' | 'D' | 'L'; - interface Reason { - label: string; - } - - const statusMap: Record = { - W: { label: 'Waiting Approval' }, - Y: { label: 'Approve' }, - N: { label: 'Reject' }, - T: { label: 'Tidak lagi menggunakan layanan' }, - P: { label: 'Privasi dan keamanan' }, - D: { label: 'Akun ganda' }, - L: { label: 'Lainnya' } - }; - if (name == 'reason_deletion' || name == 'status_approve') { - const status = formData[name] as Code - const fixStatus = statusMap[status] ?? { label: formData[name] } - formData[name] = fixStatus.label - } - return ( - <> -
-
- - -
-
- - ) -} \ No newline at end of file diff --git a/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx b/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx index a3366be..7fc3604 100644 --- a/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx +++ b/src/pages/transaction/disbursement-saldo/hooks/TransactionDisbursementContext.tsx @@ -7,7 +7,6 @@ import { createContext, useCallback, useMemo, useState } from 'react'; import ListToolbar from '../blocks/ListToolbar'; import { useCallApi } from '@/hooks'; import moment from 'moment'; -import DetailDialog from '../blocks/DetailDialog'; interface TransactionDisbursementProps { id: string; diff --git a/src/pages/transaction/disbursement-saldo/hooks/index.tsx b/src/pages/transaction/disbursement-saldo/hooks/index.tsx index 2def845..b3acae0 100644 --- a/src/pages/transaction/disbursement-saldo/hooks/index.tsx +++ b/src/pages/transaction/disbursement-saldo/hooks/index.tsx @@ -1,2 +1,2 @@ export * from './TransactionDisbursementContext'; -export * from './useTransactionTopupContext'; +export * from './useTransactionDisbursementContext'; diff --git a/src/pages/transaction/topup/blocks/DetailDialog.tsx b/src/pages/transaction/topup/blocks/DetailDialog.tsx deleted file mode 100644 index 8b1ca90..0000000 --- a/src/pages/transaction/topup/blocks/DetailDialog.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { - Dialog, - DialogBody, - DialogContent, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import { useManageKycDeletionContext } from '../hooks'; -import { apiConfig } from '@/config/api.config'; -import { useDataGrid } from '@/components'; - -const API_URL = apiConfig.service_customer; -const DetailDialog = () => { - const { showDetailDialog, setShowDetailDialog, detailKyc, handleApproveReject } = useManageKycDeletionContext(); - const { reload } = useDataGrid(); - - return ( - - - - Customer Deletion Details - - - {/* Tab Content */} - {detailKyc && detailKyc != null ? ( -
- {generateInput(detailKyc, null, 'Group', 'group_name', 'text', false, true)} - {generateInput(detailKyc, null, 'Username', 'username', 'text', false, true)} - {generateInput(detailKyc, null, 'Full Name', 'fullname', 'text', false, true)} - {generateInput(detailKyc, null, 'Gender', 'customers_gender', 'text', false, true)} - {generateInput(detailKyc, null, 'Date of Birth', 'birthdate', 'date', false, true)} - {generateInput(detailKyc, null, 'Mother Name', 'registered_mother_fullname', 'text', false, true)} - {generateInput(detailKyc, null, 'MSISDN', 'registered_msisdn', 'text', false, true)} - {generateInput(detailKyc, null, 'Reason Deletion', 'reason_deletion', 'text', false, true)} - {generateInput(detailKyc, null, 'Reason Note', 'reason_note', 'text', false, true)} - {generateInput(detailKyc, null, 'Status Approval', 'status_approve', 'text', false, true)} - -
- - - -
-
- ) : (
)} -
-
-
- ); -}; - -export default DetailDialog; - -function generateInput(formData: any, handleChange: any, label: string, name: string, type: string, required: boolean, disabled: boolean) { - function generateDate(isoString: string) { - return isoString.slice(0, 10); // "2000-01-18" - } - - type Code = 'W' | 'Y' | 'N' | 'T' | 'P' | 'D' | 'L'; - interface Reason { - label: string; - } - - const statusMap: Record = { - W: { label: 'Waiting Approval' }, - Y: { label: 'Approve' }, - N: { label: 'Reject' }, - T: { label: 'Tidak lagi menggunakan layanan' }, - P: { label: 'Privasi dan keamanan' }, - D: { label: 'Akun ganda' }, - L: { label: 'Lainnya' } - }; - if (name == 'reason_deletion' || name == 'status_approve') { - const status = formData[name] as Code - const fixStatus = statusMap[status] ?? { label: formData[name] } - formData[name] = fixStatus.label - } - return ( - <> -
-
- - -
-
- - ) -} \ No newline at end of file diff --git a/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx b/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx index ffe6337..14cccdb 100644 --- a/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx +++ b/src/pages/transaction/topup/hooks/TransactionTopupContext.tsx @@ -7,7 +7,6 @@ import { createContext, useCallback, useMemo, useState } from 'react'; import ListToolbar from '../blocks/ListToolbar'; import { useCallApi } from '@/hooks'; import moment from 'moment'; -import DetailDialog from '../blocks/DetailDialog'; interface TransactionTopupProps { id: string; From 81c84dc1cda6ace248d5a13d3b99b7d55ae159d6 Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Wed, 16 Apr 2025 02:04:12 +0700 Subject: [PATCH 15/37] fixing required --- .../disbursement-saldo/TransactionDisbursement.tsx | 10 +++++++--- src/pages/transaction/topup/TransactionTopup.tsx | 9 +++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx index 4086d51..e2f6cba 100644 --- a/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx +++ b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx @@ -21,6 +21,10 @@ const TransactionDisbursement = () => { const handleSubmit = async (e: any) => { e.preventDefault(); console.log('Submitted Data:', form); + if (form.amount == '' || form.customerId == '' || form.pin == '') { + toast.warning('Please fill in all required fields.') + return + } try { // let requestTopup = await PostData(`${API_URL}/transaction/request-topup`, { // amount: form.topupAmount, @@ -64,7 +68,7 @@ const TransactionDisbursement = () => { {/* form */}
- + * { />
- + * { />
- + * { const handleSubmit = async (e: any) => { e.preventDefault(); console.log('Submitted Data:', form); + + if (form.pin == '' || form.topupAmount) { + toast.warning('Please fill in all required fields.') + return + } try { let requestTopup = await PostData(`${API_URL}/transaction/request-topup`, { amount: form.topupAmount, @@ -62,7 +67,7 @@ const TransactionTopup = () => { {/* form */}
- + * { />
- + * Date: Wed, 16 Apr 2025 10:04:58 +0700 Subject: [PATCH 16/37] fix customer dropdown on edit manage user --- src/pages/settings/user/manage-user/blocks/EditDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/user/manage-user/blocks/EditDialog.tsx b/src/pages/settings/user/manage-user/blocks/EditDialog.tsx index e2c1248..f8b5ef8 100644 --- a/src/pages/settings/user/manage-user/blocks/EditDialog.tsx +++ b/src/pages/settings/user/manage-user/blocks/EditDialog.tsx @@ -153,7 +153,7 @@ const EditDialog = () => { email: response.data.email, id_role: response.data.idRole, status: response.data.status, - customerid: response.data.customerid?.id || '' + customerid: response.data.customer?.id || '' })); // console.log('Customer ID from API:', response?.data.customerid); } else { From ac5969c3b8d08d696a91ee05ef0c0885d542d6d7 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Wed, 16 Apr 2025 10:13:24 +0700 Subject: [PATCH 17/37] update variable on columns table manage user - sync with response - fix sorting --- .../settings/user/manage-user/blocks/ListToolBar.tsx | 2 +- .../user/manage-user/hooks/ManageUserContext.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/settings/user/manage-user/blocks/ListToolBar.tsx b/src/pages/settings/user/manage-user/blocks/ListToolBar.tsx index 2e76deb..998ef61 100644 --- a/src/pages/settings/user/manage-user/blocks/ListToolBar.tsx +++ b/src/pages/settings/user/manage-user/blocks/ListToolBar.tsx @@ -15,7 +15,7 @@ const ListToolBar = () => { table.getColumn('username')?.setFilterValue(event.target.value) diff --git a/src/pages/settings/user/manage-user/hooks/ManageUserContext.tsx b/src/pages/settings/user/manage-user/hooks/ManageUserContext.tsx index 8b33e36..77f68a9 100644 --- a/src/pages/settings/user/manage-user/hooks/ManageUserContext.tsx +++ b/src/pages/settings/user/manage-user/hooks/ManageUserContext.tsx @@ -86,7 +86,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) }, { accessorFn: (row) => row.customer?.username, - id: 'customer', + id: 'Users.customer', header: ({ column }) => , enableSorting: true, enableHiding: false, @@ -98,7 +98,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) accessorFn: (row) => row.email, id: 'email', header: ({ column }) => , - enableSorting: true, + enableSorting: false, enableHiding: false, meta: { headerClassName: 'w-[350px]' @@ -106,9 +106,9 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) }, { accessorFn: (row) => row.name, - id: 'name', + id: 'Users.name', header: ({ column }) => , - enableSorting: true, + enableSorting: false, enableHiding: false, meta: { headerClassName: 'w-[250px]' @@ -116,7 +116,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) }, { accessorFn: (row) => row.role.name, - id: 'role_name', + id: 'Users.role', header: ({ column }) => , enableSorting: true, enableHiding: false, @@ -239,7 +239,7 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) pagination={{ size: 10 }} toolbar={} layout={{ card: true }} - sorting={[{ id: 'Users.username', desc: false }]} + sorting={[{ id: 'Users.created_at', desc: false }]} serverSide={true} onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => doGetListData(pageIndex, pageSize, sorting, columnFilters) From e691041e7c2f86e7678702a2376af3c1b3a0a551 Mon Sep 17 00:00:00 2001 From: Wikzyy Date: Wed, 16 Apr 2025 10:58:11 +0700 Subject: [PATCH 18/37] update responsive search bar on master data --- src/pages/master/aldeias/blocks/ListToolbar.tsx | 2 +- src/pages/master/municipios/blocks/ListToolbar.tsx | 2 +- src/pages/master/postoadms/blocks/ListToolbar.tsx | 2 +- src/pages/master/products/blocks/ListToolbar.tsx | 2 +- src/pages/master/profession/blocks/ListToolbar.tsx | 2 +- src/pages/master/reward/blocks/ListToolbar.tsx | 2 +- src/pages/master/sucos/blocks/ListToolbar.tsx | 2 +- src/pages/master/wallet/blocks/ListToolbar.tsx | 2 +- src/pages/menu/manage-menu/blocks/ListToolbar.tsx | 2 +- src/pages/settings/user/manage-user/blocks/ListToolBar.tsx | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/master/aldeias/blocks/ListToolbar.tsx b/src/pages/master/aldeias/blocks/ListToolbar.tsx index 2454a1c..efbb499 100644 --- a/src/pages/master/aldeias/blocks/ListToolbar.tsx +++ b/src/pages/master/aldeias/blocks/ListToolbar.tsx @@ -11,7 +11,7 @@ const ListToolbar = () => {
-