diff --git a/src/config/api.config.ts b/src/config/api.config.ts index 4025a2e..bfff0a4 100644 --- a/src/config/api.config.ts +++ b/src/config/api.config.ts @@ -8,10 +8,12 @@ interface apiConfigProps { nationality: string; service_disbursement: string; service_notification: string; + service_feedback: string; } const API_URL = import.meta.env.VITE_APP_API_URL; const apiConfig: apiConfigProps = { + service_feedback: `${API_URL}/k`, // service_dashboard: `${API_URL}${import.meta.env.VITE_ENV != 'development' ? '/d' : ''}`, service_dashboard: `${API_URL}/d`, service_customer: `${API_URL}/c`, @@ -22,8 +24,7 @@ const apiConfig: apiConfigProps = { transaction: `${API_URL}/x`, service_disbursement: `${API_URL}/s`, service_notification: `${API_URL}/n`, - nationality: `https://tpay.shiblysolution.id/cms/api/mobile/list-country/ -` + nationality: `https://tpay.shiblysolution.id/cms/api/mobile/list-country/` }; export { apiConfig }; diff --git a/src/pages/members/feedback-member/FeedbackMember.tsx b/src/pages/members/feedback-member/FeedbackMember.tsx new file mode 100644 index 0000000..d8d8810 --- /dev/null +++ b/src/pages/members/feedback-member/FeedbackMember.tsx @@ -0,0 +1,40 @@ +import { Container, DataGridInner } from '@/components'; +import { ManageFeedbackMemberProvider } from './hooks/ManageFeedbackMemberContext'; +// import EditDialog from './blocks/EditDialog'; +// import DeleteDialog from './blocks/DeleteDialog'; +import { Breadcrumbs, Link } from '@mui/material'; +import { Helmet } from 'react-helmet'; + +const FeedbackMemberMaster = () => { + return ( + <> + TPAY | Manage Provider + + +

Manage Feedback Member

+ + + Dashboard + + + + Member + + + + Manage Feedback Member + + +
+ +
+ {/* + + */} +
+
+ + ); +}; + +export default FeedbackMemberMaster; diff --git a/src/pages/members/feedback-member/hooks/ManageFeedbackMemberContext.tsx b/src/pages/members/feedback-member/hooks/ManageFeedbackMemberContext.tsx new file mode 100644 index 0000000..41f986e --- /dev/null +++ b/src/pages/members/feedback-member/hooks/ManageFeedbackMemberContext.tsx @@ -0,0 +1,205 @@ +import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components'; +import { apiConfig } from '@/config/api.config'; +import { useCallApi } from '@/hooks'; +import { ColumnDef } from '@tanstack/react-table'; +import React, { createContext, useCallback, useMemo, useState } from 'react'; +import { Toaster } from 'sonner'; +// import ListToolbar from '../blocks/ListToolbar'; + +interface feedbackProps { + id: string; + name: string; + description: string; + type: string; + status: string; + transactionTypeId: string; + agentId: string; +} + +interface ContextProps { + feedback: feedbackProps[]; + showEditDialog: boolean; + handleEditDialog: (show: boolean, selected_sucos: string | null) => void; + showAddDialog: boolean; + handleAddDialog: (show: boolean) => void; + showDeleteDialog: boolean; + handleDeleteDialog: (show: boolean, selected_sucos: string | null) => void; + selectedfeedback: string | null; + getfeedbackLists: ( + limit: number, + page: number, + with_deleted: boolean, + order_field: any, + order_direction: any + ) => Promise<{ data: feedbackProps[]; totalCount: number } | undefined>; +} + +const initialProps: ContextProps = { + feedback: [], + showEditDialog: false, + handleEditDialog: () => {}, + showAddDialog: false, + handleAddDialog: () => {}, + showDeleteDialog: false, + handleDeleteDialog: () => {}, + selectedfeedback: null, + getfeedbackLists: async () => undefined +}; + +const ManageFeedbackMemberContext = createContext(initialProps); +const API_URL = apiConfig.service_feedback; + +const ManageFeedbackMemberProvider = ({ children }: { children: React.ReactNode }) => { + const [feedback, setFeedback] = useState([]); + const [showAddDialog, setShowAddDialog] = useState(false); + const [showEditDialog, setShowEditDialog] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [selectedfeedback, setSelectedfeedback] = useState(null); + const { GetData } = useCallApi(); + + const handleAddDialog = useCallback((show: boolean) => { + setShowAddDialog(show); + }, []); + + const handleEditDialog = useCallback((show: boolean, selected_feedback: string | null) => { + setShowEditDialog(show); + setSelectedfeedback(show ? selected_feedback : null); + }, []); + + const handleDeleteDialog = useCallback((show: boolean, selected_feedback: string | null) => { + setShowDeleteDialog(show); + setSelectedfeedback(show ? selected_feedback : null); + }, []); + + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => row.feedback_notes, + id: 'feedback_notes', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorFn: (row) => row.feedback_screenshot, + id: 'feedback_screenshot', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorFn: (row) => row.review_notes, + id: 'review_notes', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + }, + { + accessorFn: (row) => row.review_screenshot, + id: 'review_screenshot', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + meta: { + headerClassName: 'w-[250px]' + } + } + // , + // { + // id: 'actions', + // header: ({ column }) => , + // enableSorting: false, + // enableHiding: false, + // cell: (data) => { + // const row = data.row.original; + // return ( + // <> + // + // + // + // ); + // }, + // meta: { + // headerClassName: 'w-[100px] text-center', + // cellClassName: 'text-center' + // } + // } + ], + [handleEditDialog, handleDeleteDialog] + ); + + const getfeedbackLists = async (page: number, limit: number, sorting: any, filter: any) => { + try { + sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; + const response = await GetData(`${API_URL}/feedback/list`, { + limit, + page: page + 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc == false ? 'ASC' : 'DESC', + // filter: JSON.stringify(filter) + }); + // console.log(response?.data); + setFeedback(response?.data.list); + return { data: response?.data.list, totalCount: response?.data.total_count }; + } catch (error) { + console.error('Error fetching Feedback Member', error); + } + }; + + + return ( + + + + } + layout={{ card: true }} + sorting={[{ id: 'created_at', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + getfeedbackLists(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + + ); +}; + +export { ManageFeedbackMemberContext, ManageFeedbackMemberProvider}; +export type { feedbackProps }; diff --git a/src/pages/members/feedback-member/hooks/useManageFeedbackMemberContext.tsx b/src/pages/members/feedback-member/hooks/useManageFeedbackMemberContext.tsx new file mode 100644 index 0000000..e45bbc7 --- /dev/null +++ b/src/pages/members/feedback-member/hooks/useManageFeedbackMemberContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageFeedbackMemberContext } from './ManageFeedbackMemberContext'; + +const useManageProviderContext = () => { + const context = useContext(ManageFeedbackMemberContext); + + if (!context) throw new Error('useManageProviderContext must be used within AuthProvider'); + + return context; +}; + +export { useManageProviderContext }; diff --git a/src/pages/members/manage-members/blocks/ListToolBar.tsx b/src/pages/members/manage-members/blocks/ListToolBar.tsx index dbf32bb..89c8a1c 100644 --- a/src/pages/members/manage-members/blocks/ListToolBar.tsx +++ b/src/pages/members/manage-members/blocks/ListToolBar.tsx @@ -12,7 +12,7 @@ interface ListToolbarProps { const ListToolbar = ({ createMember, onReload, isReloading }: ListToolbarProps) => { - const [emailFilter, setEmailFilter] = useState(''); + const [groupFilter, setGroupFilter] = useState(''); const [usernameFilter, setUsernameFilter] = useState(''); const {table}=useDataGrid(); const handleUsernameChange = (e: React.ChangeEvent) => { @@ -20,9 +20,9 @@ const ListToolbar = ({ createMember, onReload, isReloading }: ListToolbarProps) table.getColumn('username')?.setFilterValue(e.target.value); }; - const handleEmailChange = (e: React.ChangeEvent) => { - setEmailFilter(e.target.value); - table.getColumn('email')?.setFilterValue(e.target.value); + const handleGroupChange = (e: React.ChangeEvent) => { + setGroupFilter(e.target.value); + table.getColumn('group_name')?.setFilterValue(e.target.value); }; return ( @@ -37,6 +37,13 @@ const ListToolbar = ({ createMember, onReload, isReloading }: ListToolbarProps) onChange={handleUsernameChange} className="input input-sm w-40" /> +

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

+ {transactionDetails?.origin_customer?.fullname ?? "-"} +

+

Amount

-

{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.amount)}

+

{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase?.amount) ?? new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.transfer.amount)}

Fee

@@ -292,7 +294,9 @@ const DetailApprovalTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

+ {transactionDetails?.origin_customer?.fullname ?? "-"} +

Amount

@@ -347,10 +351,10 @@ const DetailApprovalTransaction = () => {

{transactionDetails?.description}

-
-

Name

-

{transactionDetails?.type?.name || '-'}

-
+
+

Name

+

{transactionDetails?.type?.name || '-'}

+

Reference

@@ -370,19 +374,21 @@ const DetailApprovalTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

+ {transactionDetails?.origin_customer?.fullname ?? "-"} +

Phone Number

-

{transactionDetails?.origin_customer.msisdn}

+

{transactionDetails?.origin_customer?.msisdn ?? "-"}

Email

-

{transactionDetails?.origin_customer.email}

+

{transactionDetails?.origin_customer?.email ?? "-"}

Username

-

{transactionDetails?.origin_customer.username}

+

{transactionDetails?.origin_customer?.username ?? "-"}

@@ -391,24 +397,37 @@ const DetailApprovalTransaction = () => { {activeTab === 'destinationcustomer' && (

Destination Customer

-
-
-

Name

-

{transactionDetails?.transfer.destination_customer.fullname}

+ + {transactionDetails?.transfer?.destination_customer ? ( +
+
+

Name

+

+ {transactionDetails.transfer.destination_customer.fullname ?? "-"} +

+
+
+

MSISDN

+

+ {transactionDetails.transfer.destination_customer.msisdn ?? "-"} +

+
+
+

Email

+

+ {transactionDetails.transfer.destination_customer.email ?? "-"} +

+
+
+

Username

+

+ {transactionDetails.transfer.destination_customer.username ?? "-"} +

+
-
-

MSISDN

-

{transactionDetails?.transfer.destination_customer.msisdn}

-
-
-

Email

-

{transactionDetails?.transfer.destination_customer.email}

-
-
-

Username

-

{transactionDetails?.transfer.destination_customer.username}

-
-
+ ) : ( +

No data available

+ )}
)} diff --git a/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx index e608cd6..72c660d 100644 --- a/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx +++ b/src/pages/transaction/disbursement-saldo/TransactionDisbursement.tsx @@ -4,10 +4,11 @@ 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 { useState ,useEffect } from 'react'; import { useCallApi } from '@/hooks'; import { apiConfig } from '@/config/api.config'; import { toast } from 'sonner'; +import { getAuth } from '@/auth'; const TransactionDisbursement = () => { const [form, setForm] = useState({ @@ -15,8 +16,28 @@ const TransactionDisbursement = () => { amount: '', pin: '' }); + const [wallets, setWallets] = useState([]); const { GetData, PostData } = useCallApi(); + const parsedUser = getAuth()?.user; const API_URL = apiConfig.transaction; + const API_URL_WALLET = apiConfig.service_wallet + + useEffect(() => { + const fetchWallets = async () => { + try { + const response = await GetData(`${API_URL_WALLET}/dashboard/balance/account/${parsedUser.customer.id}`, {}); + if (response?.status === true) { + setWallets(response.data || []); + } else { + toast.warning(response?.message || 'Failed to fetch wallet data'); + } + } catch (error) { + toast.warning('Failed to fetch wallet data'); + } + }; + + fetchWallets(); + }, []); const handleSubmit = async (e: any) => { e.preventDefault(); @@ -61,6 +82,20 @@ const TransactionDisbursement = () => { Disbursement Saldo + {/* Wallet Section */} +
+

Your Wallets

+
+ {wallets.map((wallet: any) => ( +
+

{wallet.wallet}

+

+ {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(wallet.amount)} +

+
+ ))} +
+
diff --git a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx index 6d774d7..079aaf6 100644 --- a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx @@ -120,11 +120,11 @@ const DetailTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

{transactionDetails?.origin_customer?.fullname ?? "-"}

Amount

-

{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.amount)}

+

{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase?.amount) ?? new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.transfer.amount)}

Fee

@@ -291,7 +291,7 @@ const DetailTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

{transactionDetails?.origin_customer?.fullname ?? "-"}

Amount

@@ -367,19 +367,19 @@ const DetailTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer.fullname}

+

{transactionDetails?.origin_customer?.fullname ?? "-"}

Phone Number

-

{transactionDetails?.origin_customer.msisdn}

+

{transactionDetails?.origin_customer?.msisdn ?? "-"}

Email

-

{transactionDetails?.origin_customer.email}

+

{transactionDetails?.origin_customer?.email ?? "-"}

Username

-

{transactionDetails?.origin_customer.username}

+

{transactionDetails?.origin_customer?.username ?? "-"}

@@ -388,24 +388,37 @@ const DetailTransaction = () => { {activeTab === 'destinationcustomer' && (

Destination Customer

-
-
-

Name

-

{transactionDetails?.transfer.destination_customer.fullname}

+ + {transactionDetails?.transfer?.destination_customer ? ( +
+
+

Name

+

+ {transactionDetails.transfer.destination_customer.fullname ?? "-"} +

+
+
+

MSISDN

+

+ {transactionDetails.transfer.destination_customer.msisdn ?? "-"} +

+
+
+

Email

+

+ {transactionDetails.transfer.destination_customer.email ?? "-"} +

+
+
+

Username

+

+ {transactionDetails.transfer.destination_customer.username ?? "-"} +

+
-
-

MSISDN

-

{transactionDetails?.transfer.destination_customer.msisdn}

-
-
-

Email

-

{transactionDetails?.transfer.destination_customer.email}

-
-
-

Username

-

{transactionDetails?.transfer.destination_customer.username}

-
-
+ ) : ( +

No data available

+ )}
)} @@ -430,7 +443,7 @@ const DetailTransaction = () => {

Destination Wallet

{!transactionDetails?.transfer ? ( -
No Data available
+
No Data available
) : (
diff --git a/src/pages/transaction/topup/TransactionTopup.tsx b/src/pages/transaction/topup/TransactionTopup.tsx index 9552360..a05fb95 100644 --- a/src/pages/transaction/topup/TransactionTopup.tsx +++ b/src/pages/transaction/topup/TransactionTopup.tsx @@ -4,24 +4,46 @@ 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 { useState, useEffect } from 'react'; import { useCallApi } from '@/hooks'; import { apiConfig } from '@/config/api.config'; import { toast } from 'sonner'; +import { getAuth } from '@/auth'; const TransactionTopup = () => { const [form, setForm] = useState({ topupAmount: '', pin: '' }); + + const [wallets, setWallets] = useState([]); const { GetData, PostData } = useCallApi(); + const parsedUser = getAuth()?.user; const API_URL = apiConfig.transaction; + const API_URL_WALLET = apiConfig.service_wallet + + useEffect(() => { + const fetchWallets = async () => { + try { + const response = await GetData(`${API_URL_WALLET}/dashboard/balance/account/${parsedUser.customer.id}`, {}); + if (response?.status === true) { + setWallets(response.data || []); + } else { + toast.warning(response?.message || 'Failed to fetch wallet data'); + } + } catch (error) { + toast.warning('Failed to fetch wallet data'); + } + }; + + fetchWallets(); + }, []); const handleSubmit = async (e: any) => { e.preventDefault(); console.log('Submitted Data:', form); - if (form.pin == '' || form.topupAmount) { + if (form.pin == '' || form.topupAmount == '') { toast.warning('Please fill in all required fields.') return } @@ -60,6 +82,20 @@ const TransactionTopup = () => { Topup + {/* Wallet Section */} +
+

Your Wallets

+
+ {wallets.map((wallet: any) => ( +
+

{wallet.wallet}

+

+ {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(wallet.amount)} +

+
+ ))} +
+
diff --git a/src/routing/AppRoutingSetup.tsx b/src/routing/AppRoutingSetup.tsx index 786cd1e..fbb889e 100644 --- a/src/routing/AppRoutingSetup.tsx +++ b/src/routing/AppRoutingSetup.tsx @@ -42,9 +42,10 @@ import WalletRuleMaster from '@/pages/master/walletRule/WalletRuleMaster'; import WalletHistory from '@/pages/wallet/wallet-history/WalletHistory'; import WalletMaster from '@/pages/master/wallet/WalletMaster'; import CurrencyMaster from '@/pages/master/currency/CurrencyMaster'; +import FeedbackMemberMaster from '@/pages/members/feedback-member/FeedbackMember'; // DISBURSEMENT -import HistoryTransactionDisbursement from '@/pages/disbursement/history-transaction/HistoryTransaction' +import HistoryTransactionDisbursement from '@/pages/disbursement/history-transaction/HistoryTransaction'; // DISBURSEMENT const AppRoutingSetup = (): ReactElement => { @@ -84,6 +85,7 @@ const AppRoutingSetup = (): ReactElement => { } /> } /> } /> + } /> } /> @@ -98,8 +100,8 @@ const AppRoutingSetup = (): ReactElement => { } /> } /> - } /> - } /> + } /> + } /> } /> } /> } /> @@ -112,9 +114,11 @@ const AppRoutingSetup = (): ReactElement => { /> {/* DISBURSEMENT */} - } /> + } + /> {/* DISBURSEMENT */} - } />