This commit is contained in:
fro1991
2025-02-01 16:43:57 +07:00
parent 8a385410d8
commit c432df568a
69 changed files with 0 additions and 23530 deletions

View File

@ -1,39 +0,0 @@
import React from 'react';
import { Line } from 'react-chartjs-2';
import { Box, Typography } from '@mui/material';
import '../style/Chart.css';
const ChartBox = () => {
const data = {
labels: ['Jan 01', 'Jan 02', 'Jan 03', 'Jan 04', 'Jan 05', 'Jan 06'],
datasets: [
{
label: 'Cash In',
data: [50, 75, 200, 125, 150, 175],
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
fill: true, // No fill under the line
tension: 0.5, // Line curve
},
{
label: 'Cash Out',
data: [100, 90, 80, 70, 60, 50],
backgroundColor: 'rgba(255,99,132,0.4)',
borderColor: 'rgba(255,99,132,1)',
fill: true, // No fill under the line
tension: 0.5, // Line curve
},
],
};
return (
<Box sx={{ padding: 2, backgroundColor: '#fff', borderRadius: 2, boxShadow: 1 }}>
<Typography variant="h6" sx={{ marginBottom: 2 }}>
Account Activities
</Typography>
<Line data={data} />
</Box>
);
};
export default ChartBox;

View File

@ -1,95 +0,0 @@
import React, { useState, useEffect } from "react";
import {
AppBar,
Toolbar,
Typography,
IconButton,
Menu,
MenuItem,
Avatar,Button
} from "@mui/material";
import { Mail, AccountCircle } from "@mui/icons-material";
import "../style/Header.css";
import { useNavigate } from 'react-router-dom';
import Cookies from "js-cookie";
const Header = () => {
const [userData, setUserData] = useState('');
const [anchorEl, setAnchorEl] = useState(null);
const navigate = useNavigate();
useEffect(() => {
let username = Cookies.get('username');
setUserData(username)
}, []);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
function logoutBtn() {
Cookies.remove('token');
Cookies.remove('role');
Cookies.remove('userId');
Cookies.remove('username');
localStorage.removeItem('roles_list');
navigate('/login')
}
const open = Boolean(anchorEl);
return (
<AppBar position="fixed" sx={{ backgroundColor: "#f5f5f5", color: "#333" }}>
<Toolbar>
<Typography variant="h6" noWrap sx={{ flexGrow: 1 }}></Typography>
<IconButton>
<Mail />
</IconButton>
<IconButton
size="large"
edge="end"
aria-label="account"
aria-controls="account-menu"
aria-haspopup="true"
onClick={handleClick}
color="inherit"
>
<AccountCircle />
</IconButton>
<Button onClick={handleClick}
id="basic-button"
aria-controls={open ? 'account-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}>{userData}
</Button>
<Menu
id="account-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
onClick={handleClose}
transformOrigin={{ horizontal: "right", vertical: "top" }}
anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
title="User Profile"
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={() => navigate('/profile')}>
<Avatar sx={{ marginRight: 1 }} /> Profile
</MenuItem>
<MenuItem>
<Avatar sx={{ marginRight: 1 }} /> My Account
</MenuItem>
<MenuItem onClick={() => logoutBtn()}>Logout</MenuItem>
</Menu>
</Toolbar>
</AppBar>
);
};
export default Header;

View File

@ -1,163 +0,0 @@
// src/MyCharts.js
import React from 'react';
import { Line } from 'react-chartjs-2';
import { Doughnut } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, ArcElement } from 'chart.js';
import '../style/MemberActivity.css';
import {
Box,
List,
ListItem,
ListItemText,
Typography,
Divider,
} from "@mui/material";
import { CircularProgressbar, buildStyles } from "react-circular-progressbar";
import "react-circular-progressbar/dist/styles.css";
// Register Chart.js components
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, ArcElement);
const MyCharts = () => {
const percentage = 45;
// Level Chart (Line Chart) Data
const levelData = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [
{
label: 'Level Progress',
data: [20, 40, 60, 80, 100, 90, 70],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
},
],
};
// Circle Chart (Doughnut Chart) Data
const circleData = {
labels: ['Completed', 'Remaining'],
datasets: [
{
label: 'Completion',
data: [75, 25],
backgroundColor: ['rgb(75, 192, 192)', 'rgb(192, 75, 75)'],
borderColor: 'rgb(255, 255, 255)',
borderWidth: 1,
},
],
};
// Performance Chart (Bar Chart) Data
// const performanceData = {
// labels: ['Q1', 'Q2', 'Q3', 'Q4'],
// datasets: [
// {
// label: 'Performance',
// data: [50, 70, 90, 60],
// backgroundColor: 'rgb(75, 192, 192)',
// borderColor: 'rgb(0, 123, 255)',
// borderWidth: 1,
// },
// ],
// };
// Chart Options
const options = {
responsive: true,
plugins: {
legend: {
position: 'top',
},
},
};
return (
<div className="charts-container">
<div className="chart-item">
<Box boxShadow="0px 2px 5px rgba(0, 0, 0, 0.1)">
<h3>Level Chart</h3>
<Line data={levelData} options={options} />
</Box>
</div>
<div className="chart-item">
<Box boxShadow="0px 2px 5px rgba(0, 0, 0, 0.1)">
<h3>Circle Chart</h3>
<Doughnut data={circleData} options={options} />
</Box>
</div>
<div className="chart-item">
<h3>Performance Chart</h3>
{/* <Bar data={performanceData} options={options} /> */}
<Box
display="flex"
flexDirection="row"
width={300}
border="1px solid #ddd"
borderRadius={4}
overflow="hidden"
boxShadow="0px 2px 5px rgba(0, 0, 0, 0.1)"
>
{/* Sidebar Menu */}
<Box
width="40%"
bgcolor="#f9f9f9"
display="flex"
flexDirection="column"
borderRight="1px solid #ddd"
py={2}
>
<List disablePadding>
{[
"Settings",
"Subscription",
"Auto Renewal",
"Achievements",
"Logout",
].map((text, index) => (
<React.Fragment key={index}>
<ListItem button>
<ListItemText primary={text} />
</ListItem>
{index === 3 && <Divider />} {/* Divider after "Achievements" */}
</React.Fragment>
))}
</List>
</Box>
{/* Active User Section */}
<Box
width="60%"
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="center"
p={2}
>
<Typography variant="subtitle1" fontWeight="bold">
Active User
</Typography>
<Box width={80} mt={1}>
<CircularProgressbar
value={percentage}
text={`${percentage}%`}
styles={buildStyles({
textSize: "14px",
pathColor: "#4caf50",
textColor: "#4caf50",
trailColor: "#ddd",
pathTransitionDuration: 0.5,
})}
/>
</Box>
<Typography variant="body2" mt={1}>
{`${percentage}%`}
</Typography>
</Box>
</Box>
</div>
</div>
);
};
export default MyCharts;

View File

@ -1,403 +0,0 @@
import React, { useState, useEffect } from 'react';
import {
Drawer,
List,
ListItem,
ListItemText,
Accordion,
AccordionSummary,
AccordionDetails,
Typography,
Button,
// Divider,
Box,
Tooltip,
Avatar,
Link
} from '@mui/material';
import SettingsIcon from "@mui/icons-material/Settings";
import HelpIcon from "@mui/icons-material/Help";
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import InfoIcon from "@mui/icons-material/Info";
import Logout from "@mui/icons-material/Logout";
import { useNavigate } from 'react-router-dom';
import logo from '../logo/logo.jpeg';
import Cookies from "js-cookie";
import { Link as ReactRouterLink } from 'react-router-dom';
const Sidebar = () => {
const [userRole, setUserRole] = useState('');
const navigate = useNavigate();
const adminMenu = [
{
title: 'Group',
options: [
{
title: 'Manage Groups',
path: '/manage-groups'
}
],
},
{
title: 'Member',
options: [
{
title: 'Manage Members',
path: '/manage-members'
},
{
title: 'KYC',
path: '/manage-member-kyc'
}
],
},
{
title: 'Access',
options: [
{
title: 'Manage Access Type',
path: '/manage-access'
},
{
title: 'Create Member Credential',
path: '/manage-member-credential'
}
],
},
{
title: 'Account',
options: [
{
title: 'Manage Account',
path: '/manage-accounts'
},
{
title: 'Manage Currency',
path: '/manage-currency'
}
],
},
{
title: 'Transfer Type',
options: [
{
title: 'Manage Transfer Type',
path: '/manage-transfers'
}
],
},
{
title: 'Notification',
options: [
{
title: 'Manage Notification',
path: '/manage-notifications'
}
],
},
{
title: 'Menu',
options: [
{
title: 'Wellcome',
},
{
title: 'Menu Category',
},
{
title: 'Manage Menu',
path: '/manage-menu'
}
],
},
{
title: 'Message',
options: [
{
title: 'Inbox',
}
],
},
{
title: 'Webservice',
options: [
{
title: 'Manage Webservice',
path: '/manage-webservice'
}
],
},
{
title: 'Setting',
options: [
{
title: 'User Management',
path: '/user-management'
},
{
title: 'Role Management',
path: '/role-management'
},
{
title: 'Profile',
path: '/profile'
},
{
title: 'Setting',
path: '/setting'
},
{
title: 'Master Data',
path: '/master-data'
},
],
},
];
const esCrowMenu = [
{
title: 'Home',
options: [
{
title: 'Dashboard',
path: '/'
},
{
title: 'Transaction History',
path: '/transaction-history'
}
],
},
{
title: 'Member',
options: [
{
title: 'Manage Members',
path: '/manage-members'
},
],
},
{
title: 'Message',
options: [
{
title: 'Inbox',
}
],
},
{
title: 'Setting',
options: [
{
title: 'Setting',
path: '/setting'
}
],
},
]
const escrowSubMenu = [
{
title: 'Transaction',
options: [
{
title: 'Transfer',
path: '/transfer'
},
{
title: 'Ticket Confirmation',
path: '/ticket-confirmation'
}
],
}
]
const tdsMenu = [
{
title: 'Home',
path: '/'
},
{
title: 'Transaction Report',
options: [
{
title: 'Agent Balance',
path: '/agent-balance'
},
{
title: 'Deposit Report',
path: '/deposit-report'
},
{
title: 'Topup',
path: '/topup'
},
],
},
{
title: 'Operation',
options: [
{
title: 'Topup Approval',
path: '/topup-approval'
},
{
title: 'Topup Request',
path: '/topup-request'
},
{
title: 'Transfer',
path: '/operation-transfer'
},
],
},
{
title: 'User Management',
options: [
{
title: 'Agent Registered',
path: '/registered-agent'
},
{
title: 'Supervisor Registered',
path: '/registered-supervisor'
}
],
},
]
useEffect(() => {
let token = Cookies.get(`token`);
let role = Cookies.get(`role`);
if (token && role) setUserRole(role);
}, []);
function roleMenu() {
if (userRole === 'Super Admin') return adminMenu
if (userRole === 'escrow') return esCrowMenu
if (userRole === 'tds') return tdsMenu
return []
}
function logoutBtn() {
Cookies.remove('token');
Cookies.remove('role');
Cookies.remove('userId');
Cookies.remove('username');
localStorage.removeItem('roles_list');
navigate('/login');
}
return (
<Drawer
variant="permanent"
sx={{
width: 240,
'& .MuiDrawer-paper': {
width: 240,
boxSizing: 'border-box',
backgroundColor: '#BA151C',
color: '#fff',
},
}}
>
<Typography variant="h5" sx={{ textAlign: 'center', margin: 2 }}>
<Button onClick={() => navigate('/')} sx={{ textAlign: 'center', fontSize: '20px', color: 'wheat' }}>
<Avatar
src={logo}
alt="T-PAY"
sx={{ width: 40, height: 40, backgroundColor: 'red' }}
/>
T-PAY</Button>
</Typography>
{/* <Divider/> */}
<ListOfMenus roleMenu={roleMenu} navigate={navigate} label={`GENERAL`}/>
{
userRole === 'escrow' ? (
<ListOfMenus roleMenu={() => escrowSubMenu} navigate={navigate} label={`Transaction`}/>
) : ('')
}
{/* FOOTER */}
<Box
sx={{
backgroundColor: "black", // Dark grey color for the bottom
padding: 1, // Add padding for content
display: "flex",
alignItems: "center",
justifyContent: "space-between", // Align content in the bottom section
position: 'fixed',
bottom: 0,
maxWidth: 240,
marginLeft: -2,
}}
>
<Tooltip title="Setting" arrow>
<Button size='small'><SettingsIcon sx={{ color: "white" }} /></Button>
</Tooltip>
<Tooltip title="Fullscreen" arrow>
<Button size='small'><InfoIcon sx={{ color: "white" }} /></Button>
</Tooltip>
<Tooltip title="Help" arrow>
<Button size='small'><HelpIcon sx={{ color: "white" }} /></Button>
</Tooltip>
<Tooltip title="Logout" arrow>
<Button size='small' onClick={() => logoutBtn()}><Logout sx={{ color: "white" }} /></Button>
</Tooltip>
</Box>
</Drawer>
);
};
function ListOfMenus({roleMenu, navigate, label}) {
const [expanded, setExpanded] = useState(false);
const handleExpand = (index, menu) => {
if (menu.options) return setExpanded((prevExpanded) => (prevExpanded === index ? false : index));
};
function onClickParent(menu) {
if (menu.options) return false
return navigate(menu.path)
}
return (
<>
<p style={{ textAlign: 'left', marginLeft: '20px', fontSize: '12px' }}>{label}</p>
<List sx={{ marginBottom: 5 }}>
{roleMenu().map((menuItem, index) => (
<Accordion
key={index}
expanded={expanded === index}
onChange={() => handleExpand(index, menuItem)}
sx={{
backgroundColor: 'inherit',
color: '#fff',
boxShadow: 'none',
}}
>
<AccordionSummary expandIcon={menuItem.options ? <ExpandMoreIcon sx={{ color: '#fff' }} /> : ''}>
<SettingsIcon sx={{ color: "white" }} />
<Typography onClick={() => onClickParent(menuItem)} ml={1}>{menuItem.title}</Typography>
</AccordionSummary>
<AccordionDetails>
{menuItem.options && menuItem.options.map((option, subIndex) => (
<ListItem key={subIndex} sx={{ pl: 2 }}>
<ListItemText>
<Link to={option.path} component={ReactRouterLink} underline="none">
<Typography color='wheat' style={{ textAlign: 'left' }}>{option.title}</Typography>
</Link>
</ListItemText>
</ListItem>
))}
</AccordionDetails>
</Accordion>
))}
</List>
</>
)
}
export default Sidebar;

View File

@ -1,24 +0,0 @@
import React from 'react';
import { Card, CardContent, Typography } from '@mui/material';
import '../style/StatsCard.css'
const StatsCard = ({ title, value, growth }) => {
return (
<Card sx={{ minWidth: 200, boxShadow: 2 }}>
<CardContent>
<Typography variant="h6" color="text.secondary">
{title}
</Typography>
<Typography variant="h4">{value}</Typography>
<Typography
variant="body2"
sx={{ color: growth >= 0 ? 'green' : 'red' }}
>
{growth}% From last week
</Typography>
</CardContent>
</Card>
);
};
export default StatsCard;

View File

@ -1,35 +0,0 @@
import StatsCard from "../components/StatsCard";
import ChartBox from "../components/Chart";
import TransactionList from "../components/TransactionList";
import MemberActivity from "../components/MemberActivity";
import { Box, Grid } from "@mui/material";
export default function Summary() {
return (
<Box sx={{ padding: 3 }}>
<Grid container spacing={3}>
<Grid item xs={12} sm={6} md={3}>
<StatsCard title="Registered Users" value="2500" growth={4} />
</Grid>
<Grid item xs={12} sm={6} md={3}>
<StatsCard title="Unregistered Users" value="2350" growth={3} />
</Grid>
<Grid item xs={12} sm={6} md={3}>
<StatsCard title="Total Cash-in" value="2.5M" growth={34} />
</Grid>
<Grid item xs={12} sm={6} md={3}>
<StatsCard title="Total Cash-out" value="4.5M" growth={-12} />
</Grid>
</Grid>
<Box sx={{ marginTop: 4 }}>
<div className="charts-container">
<div className="chart-item" style={{ width: '65%' }}><ChartBox /></div>
<div className="chart-item" style={{ width: '30%' }}><TransactionList /></div>
</div>
</Box>
<Box sx={{ marginTop: 4 }}>
<MemberActivity />
</Box>
</Box>
)
}

View File

@ -1,90 +0,0 @@
import React from 'react';
import { tableCellClasses } from '@mui/material/TableCell';
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, styled, TablePagination } from '@mui/material';
const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
backgroundColor: `grey`,
color: theme.palette.common.white,
},
[`&.${tableCellClasses.body}`]: {
fontSize: 14,
},
}));
const StyledTableRow = styled(TableRow)(({ theme }) => ({
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.action.hover,
},
// hide last border
'&:last-child td, &:last-child th': {
border: 0,
},
}));
function ReusableTable({ columns, data }) {
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
return (
<>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
{columns.map((column, index) => (
<StyledTableCell align={index === columns.length - 1 ? "right" : "left"} key={column.id}>{column.label}</StyledTableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{data.map((row, index) => (
<StyledTableRow key={row.id || index}>
{columns.map((column, index) => (
<StyledTableCell align={index === columns.length - 1 ? "right" : "left"} key={column.id}>
{column.id === 'actions' && row.actions ? (
row.actions.map((action, actionIndex) => (
<Button
key={actionIndex}
variant="contained"
color={action.color || 'primary'}
onClick={() => action.onClick(row)}
style={{ marginRight: '5px' }}
size='small'
>
{action.label}
</Button>
))
) : (
row[column.id]
)}
</StyledTableCell>
))}
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</>
);
}
export default ReusableTable;

View File

@ -1,30 +0,0 @@
import React from 'react';
import { List, ListItem, ListItemText, Box, LinearProgress, Typography } from '@mui/material';
import '../style/TransactionList.css';
const TransactionList = () => {
const transactions = [
{ type: 'Member Transfer', percentage: 60 },
{ type: 'Bill Payment', percentage: 30 },
{ type: 'Topup', percentage: 20 },
{ type: 'Purchase', percentage: 10 },
];
return (
<Box sx={{ padding: 2, backgroundColor: '#fff', borderRadius: 2, boxShadow: 1 }}>
<Typography variant="h6" sx={{ marginBottom: 2 }}>
Top Transactions
</Typography>
<List>
{transactions.map((transaction, index) => (
<ListItem key={index} sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
<ListItemText primary={transaction.type} />
<LinearProgress variant="determinate" value={transaction.percentage} sx={{ width: '100%' }} />
</ListItem>
))}
</List>
</Box>
);
};
export default TransactionList;

View File

@ -1,46 +0,0 @@
// ErrorModal.js
import React from "react";
import { Modal, Box, Typography, Button } from "@mui/material";
const ErrorModal = ({ open, onClose, errorMessage }) => {
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
borderRadius: 2,
};
return (
<Modal
open={open}
onClose={onClose}
aria-labelledby="error-modal-title"
aria-describedby="error-modal-description"
>
<Box sx={style}>
<Typography id="error-modal-title" variant="h6" component="h2">
Error
</Typography>
<Typography id="error-modal-description" sx={{ mt: 2 }}>
{errorMessage}
</Typography>
<Button
variant="contained"
color="error"
onClick={onClose}
sx={{ mt: 2 }}
>
Close
</Button>
</Box>
</Modal>
);
};
export default ErrorModal;