From 22e3624965b5d53b210e6eab1b660c7da981f207 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2025 14:10:09 +0700 Subject: [PATCH] add agent balance --- .../members/agent-balance/AgentBalance.tsx | 278 ++++++++++++++++++ src/pages/members/agent-balance/Column.tsx | 146 +++++++++ .../members/agent-balance/ListToolbar.tsx | 82 ++++++ .../members/manage-members/ManageMembers.tsx | 22 +- src/routing/AppRoutingSetup.tsx | 2 + 5 files changed, 525 insertions(+), 5 deletions(-) create mode 100644 src/pages/members/agent-balance/AgentBalance.tsx create mode 100644 src/pages/members/agent-balance/Column.tsx create mode 100644 src/pages/members/agent-balance/ListToolbar.tsx diff --git a/src/pages/members/agent-balance/AgentBalance.tsx b/src/pages/members/agent-balance/AgentBalance.tsx new file mode 100644 index 0000000..9b98258 --- /dev/null +++ b/src/pages/members/agent-balance/AgentBalance.tsx @@ -0,0 +1,278 @@ +import { DataTable } from '@/components/ui/DataTable'; +import { getColumns } from './Column'; +import { apiConfig } from '@/config/api.config'; +import axios, { AxiosResponse } from 'axios'; +import { Helmet } from 'react-helmet'; +import { + DialogContent, + MenuItem, + Radio, + RadioGroup, + FormControlLabel, + FormControl, + Dialog, + DialogTitle, + Typography, + Button, + Box, + Breadcrumbs, + Link +} from '@mui/material'; +import { useState, useEffect } from 'react'; +import CloseIcon from '@mui/icons-material/Close'; +import Divider from '@mui/material/Divider'; +import ConfirmDialog from '@/components/confirm'; +import { toast } from 'sonner'; +import { Container, DataGridLoader, DataGridProvider, LoaderTransparant } from '@/components'; +import { ListToolBar } from './ListToolbar'; +import { RefreshCw } from 'lucide-react'; +import { setgroups } from 'process'; +const BASE_URL = apiConfig.service_customer; + +let initBalance = { + id: '', + msisdn: '', + fullname: '', + username: '', + agent_name: '', + balance_emoney: '', + balance_merchant: '', + balance_point: '', + balance_deposit: '' +}; + +const AgentBalance = () => { + const [isDialogOpen, setIsDialogOpen] = useState(false); + const [loading, setLoading] = useState(false); + const [dataBalance, setDataBalance] = useState([]); + const [formData, setFormData] = useState(initBalance); + const [pageIndex, setPageIndex] = useState(1); + const [pageSize, setPageSize] = useState(10); + const [dialogType, setDialogType] = useState(''); + const [dialogOpen, setDialogOpen] = useState(false); + const [isReloading, setIsReloading] = useState(false); + + useEffect(() => { + fetchAgentBalance(); + }, []); + + async function fetchAgentBalance(): Promise { + setIsReloading(true); + try { + let balances = await axios.get(`${BASE_URL}/customer/agent-balance`, { + params: { + limit: 20, + page: 1, + with_deleted: false, + order_field: 'created_at', + order_direction: 'DESC' + } + }); + let temp = 1; + let resBalance = balances.data.data.list.map((el: any) => { + el.no = temp++; + return el; + }); + setDataBalance(resBalance); + } catch (error: any) { + alert(error.message); + console.log(error); + } finally { + setIsReloading(false); + } + } + + const openDialog = () => setIsDialogOpen(true); + const closeDialog = () => { + setIsDialogOpen(false); + setFormData(initBalance); + }; + + // const handleChange = (e: React.ChangeEvent) => { + // setFormData({ + // ...formData, + // [e.target.name]: e.target.value + // }); + // }; + + // const handleSubmit = async (e: React.FormEvent) => { + // e.preventDefault(); + // // if (!formData.groupName) return toast.warning(`Group name can not be empty!`); + // setIsDialogOpen(false); + // setDialogOpen(true); + // }; + + function createGroup() { + setDialogType('create'); + openDialog(); + } + + const handleUpdate = (group: any) => { + setDialogType('update'); + setIsDialogOpen(true); + }; + + const handleReload = () => { + setIsReloading(true); + fetchAgentBalance(); + }; + + // const handleYes = async () => { + // setIsReloading(true); + // try { + // if (dialogType === 'create') { + // await axios.post(`${BASE_URL}/groups/create`, { + // name: formData.groupName, + // status: formData.status, + // description: formData.description, + // created_at: new Date() + // }); + // toast.success(`Success create group`); + // } + // } catch (error: any) { + // console.log(error); + // toast.error(error.message); + // } finally { + // setDialogOpen(false); + // closeDialog(); + // await fetchAgentBalance(); + // setLoading(false); + // } + // }; + + // function setShowAddDialog(el: any) { + // setIsDialogOpen(el); + // } + + if (loading) return ; + + return ( + <> + + TPAY | Agent Balance + + + {/* setDialogOpen(false)} + title="Confirm Action" + content={''} + onYes={handleYes} + onNo={() => setDialogOpen(false)} + /> */} +

Agent Balances

+ + + Dashboard + + + + Members + + + + Agent Balances + + + {/*
*/} + +
+ {isReloading && ( + + )} + + } + layout={{ card: 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" + /> + + +
+
+ + +
+ +
+
+
+
*/} +
+ + ); +}; + +export default AgentBalance; diff --git a/src/pages/members/agent-balance/Column.tsx b/src/pages/members/agent-balance/Column.tsx new file mode 100644 index 0000000..a188e8b --- /dev/null +++ b/src/pages/members/agent-balance/Column.tsx @@ -0,0 +1,146 @@ +import { KeenIcon } from '@/components'; +import { Button } from '@/components/ui/button'; +import { ColumnDef } from '@tanstack/react-table'; +import { ArrowUpDown } from 'lucide-react'; +import moment from 'moment'; + +export type AgentBalance = { + id: string, + msisdn: string, + fullname: string, + username: string, + agent_name: string, + balance_emoney: string, + balance_merchant: string, + balance_point: string, + balance_deposit: string +}; + +export const getColumns = (handleUpdate: (data: any) => void): ColumnDef[] => [ + { + accessorKey: 'no', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'msisdn', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'fullname', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'username', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'agent_name', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'balance_emoney', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'balance_merchant', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'balance_point', + header: ({ column }) => { + return ( + + ); + } + }, + { + accessorKey: 'balance_deposit', + header: ({ column }) => { + return ( + + ); + } + }, +]; diff --git a/src/pages/members/agent-balance/ListToolbar.tsx b/src/pages/members/agent-balance/ListToolbar.tsx new file mode 100644 index 0000000..5e9f421 --- /dev/null +++ b/src/pages/members/agent-balance/ListToolbar.tsx @@ -0,0 +1,82 @@ +import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; +import { Button } from '@/components/ui/button'; +import React, { useState } from 'react'; + +interface ListToolBarProps { + createGroup: () => void; + onReload: () => void; + isReloading: boolean; +} + +const ListToolBar = ({ createGroup, onReload, isReloading }: ListToolBarProps) => { + const { table } = useDataGrid(); + const [usernameFilter, setUsernameFilter] = useState(''); + const [msisdn, setMsisdn] = useState(''); + const [fullname, setFullname] = useState(''); + const [merchantName, setMerchantName] = useState(''); + + const handleUsernameChange = (e: React.ChangeEvent) => { + setUsernameFilter(e.target.value); + table.getColumn('username')?.setFilterValue(e.target.value); + }; + + const filtermsisdn = (e: React.ChangeEvent) => { + setMsisdn(e.target.value); + table.getColumn('msisdn')?.setFilterValue(e.target.value); + }; + + const filterfullname = (e: React.ChangeEvent) => { + setFullname(e.target.value); + table.getColumn('fullname')?.setFilterValue(e.target.value); + }; + + const filtermerchantname = (e: React.ChangeEvent) => { + setMerchantName(e.target.value); + table.getColumn('agent_name')?.setFilterValue(e.target.value); + }; + + return ( +
+
+
+
+ + + + +
+
+ {/* */} + + + +
+
+
+
+ ); +}; + +export { ListToolBar }; diff --git a/src/pages/members/manage-members/ManageMembers.tsx b/src/pages/members/manage-members/ManageMembers.tsx index 01d9785..3739311 100644 --- a/src/pages/members/manage-members/ManageMembers.tsx +++ b/src/pages/members/manage-members/ManageMembers.tsx @@ -18,7 +18,7 @@ const BASE_URL_CUSTOMER = apiConfig.service_customer; const BASE_URL = apiConfig.service_customer; const ManageMembers = () => { - const [loading, setLoading] = useState(false); + // const [loading, setLoading] = useState(false); const [members, setMembers] = useState([]); const [selectedMember, setSelectedMember] = useState(''); const [member, setMember] = useState(initialMember); @@ -28,6 +28,9 @@ const ManageMembers = () => { const [dialogType, setDialogType] = useState(''); const [groups, setGroups] = useState([]); const [isReloading, setIsReloading] = useState(false); + const [currentPage, setCurrentPage] = useState(0); + const [totalItems, setTotalItems] = useState(10); + const closeDialog = () => { setIsDialogOpen(false); setMember(initialMember); @@ -36,6 +39,7 @@ const ManageMembers = () => { useEffect(() => { fetchCustomers(); + fetchMasters(); }, []); async function fetchCustomers(): Promise { @@ -44,7 +48,7 @@ const ManageMembers = () => { let customers = await axios.get(`${BASE_URL}/customer/list`, { params: { limit: 30, - page: 1, + page: 1 + currentPage, with_deleted: false, order_field: 'created_at', order_direction: 'DESC' @@ -61,8 +65,17 @@ const ManageMembers = () => { return el; }); setMembers(resMembers); - // setIsReloading(false); + } catch (error: any) { + toast.error(error.message); + console.log(error); + } finally { + setIsReloading(false); + } + } + async function fetchMasters(): Promise { + setIsReloading(true); + try { let getProfession: any = await axios.get(`${BASE_URL_MASTER_DATA}/profession/list`, { params: { limit: 50, @@ -87,7 +100,6 @@ const ManageMembers = () => { toast.error(error.message); console.log(error); } finally { - // setLoading(false); setIsReloading(false); } } @@ -269,7 +281,7 @@ const ManageMembers = () => { )} { } /> } /> } /> + } /> } />