tpay client

This commit is contained in:
unknown
2025-01-07 16:25:37 +07:00
parent 6f1eac180a
commit cabc5be6a3
40 changed files with 4186 additions and 106 deletions

View File

@ -1,25 +0,0 @@
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;

39
src/components/Chart.js vendored Normal file
View File

@ -0,0 +1,39 @@
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;

76
src/components/Header.js Normal file
View File

@ -0,0 +1,76 @@
import React, { useState } from "react";
import {
AppBar,
Toolbar,
Typography,
IconButton,
Menu,
MenuItem,
Avatar,
} from "@mui/material";
import { Mail, AccountCircle } from "@mui/icons-material";
import "../style/Header.css";
import { useNavigate } from 'react-router-dom';
const Header = () => {
const [anchorEl, setAnchorEl] = useState(null);
const navigate = useNavigate();
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
function logoutBtn() {
localStorage.removeItem("authToken");
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>
<Menu
id="account-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
onClick={handleClose}
transformOrigin={{ horizontal: "right", vertical: "top" }}
anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
>
<MenuItem>
<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

@ -0,0 +1,163 @@
// 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;

372
src/components/SideBar.js Normal file
View File

@ -0,0 +1,372 @@
import React, { useState } from 'react';
import {
Drawer,
List,
ListItem,
ListItemText,
Accordion,
AccordionSummary,
AccordionDetails,
Typography,
Button,
// Divider,
Box,
Tooltip,
Avatar
} 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';
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: 'Setting',
path: '/setting'
}
],
},
];
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: '/transfer'
},
],
},
{
title: 'User Management',
options: [
{
title: 'Agent Registered',
path: '/agent'
},
{
title: 'Supervisor Registered',
path: '/supervisor'
}
],
},
]
function roleMenu() {
setUserRole('escrow')
if (userRole === 'admin') return adminMenu
if (userRole === 'escrow') return esCrowMenu
if (userRole === 'tds') return tdsMenu
return []
}
function logoutBtn() {
localStorage.removeItem("authToken");
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/Logo.jpeg"
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 button key={subIndex} sx={{ pl: 2 }}>
<ListItemText>
<Typography onClick={() => navigate(option.path)} color='wheat' style={{ textAlign: 'left' }}>{option.title}</Typography>
</ListItemText>
</ListItem>
))}
</AccordionDetails>
</Accordion>
))}
</List>
</>
)
}
export default Sidebar;

View File

@ -0,0 +1,24 @@
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;

35
src/components/Summary.js Normal file
View File

@ -0,0 +1,35 @@
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

@ -0,0 +1,30 @@
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

@ -0,0 +1,59 @@
import React, { useState } from "react";
import {
TextField,
Button,
Box,
Typography,
Paper,
} from "@mui/material";
const TicketConfirmationPage = () => {
// State for form fields
const [ticketId, setTicketId] = useState("");
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (ticketId) {
console.log("Registered with:", { ticketId });
} else {
alert("Please fill in all fields.");
}
};
return (
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Ticket Confirmation</Typography>
</Box>
<Box sx={{ paddingTop: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '20px' }}>Confirm Ticket</Typography>
</Box>
<Box sx={{ padding: 6 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<form onSubmit={handleSubmit}>
<Box mb={2} m={2}>
<TextField
label="Ticket ID"
variant="outlined"
fullWidth
value={ticketId}
onChange={(e) => setTicketId(e.target.value)}
required
/>
</Box>
<Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px' }} variant="contained">Reset</Button>
<Button variant="contained" color="success">Submit</Button>
</Box>
</form>
</Paper>
</Box>
</Box>
</Box>
);
};
export default TicketConfirmationPage;

View File

@ -0,0 +1,57 @@
import * as React from 'react';
import { Box, Typography, Button, Grid, Card, CardContent } from '@mui/material';
export default function TransactionHistory() {
const accounts = [
{
title: "Merchant Account",
description: "Rekening Merchant"
},
{
title: "Deposit Account",
description: "Rekening Deposit"
},
{
title: "Cash out/in account to bank",
description: "Pooling account to maintain cash in/out member to bank"
}
];
return (
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Transaction History</Typography>
</Box>
<Box p={3}>
<Typography variant="h5" gutterBottom>
Select Account
</Typography>
<Grid container spacing={2}>
{accounts.map((account, index) => (
<Grid item xs={12} key={index}>
<Card variant="outlined">
<CardContent>
<Grid container justifyContent="space-between" alignItems="center">
<Grid item>
<Typography variant="h6" color="textSecondary">{account.title}</Typography>
</Grid>
<Grid item>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography variant="body2" color="textSecondary">{account.description}</Typography>
</Box>
</Grid>
<Grid item>
<Button variant="contained" color="success">
View
</Button>
</Grid>
</Grid>
</CardContent>
</Card>
</Grid>
))}
</Grid>
</Box>
</Box>
);
}

View File

@ -0,0 +1,93 @@
import React, { useState } from "react";
import {
TextField,
Button,
Box,
Typography,
Paper,
} from "@mui/material";
const TransferPage = () => {
// State for form fields
const [name, setName] = useState("");
const [email, setEmail] = useState("");
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (name && email) {
// Handle registration logic, like calling an API to create the user
console.log("Registered with:", { name, email });
} else {
alert("Please fill in all fields.");
}
};
return (
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Transaction</Typography>
</Box>
<Box sx={{ paddingTop: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '20px' }}>Transfer</Typography>
</Box>
<Box sx={{ padding: 6 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<form onSubmit={handleSubmit}>
<Box mb={2} m={2}>
<TextField
label="Transaction Type"
variant="outlined"
fullWidth
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Destination Account"
variant="outlined"
fullWidth
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Amount"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
type="text"
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Description"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
type="text"
required
/>
</Box>
<Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px' }} variant="contained">Reset</Button>
<Button variant="contained" color="success">Submit</Button>
</Box>
</form>
</Paper>
</Box>
</Box>
</Box>
);
};
export default TransferPage;

View File

@ -1,14 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./routes/routes";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
);
// If you want to start measuring performance in your app, pass a function

BIN
src/logo/Logo.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -36,3 +36,21 @@
transform: rotate(360deg);
}
}
.main-content {
margin-left: 250px;
padding: 20px;
background-color: #f9f9f9;
min-height: 100vh;
}
.stats {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.stats-card {
flex: 1;
}

17
src/pages/Dashboard.js Normal file
View File

@ -0,0 +1,17 @@
// import logo from "./logo.svg";
import "./Dashboard.css";
import Chart from "chart.js/auto";
import { CategoryScale } from "chart.js";
import Summary from "../components/Summary";
Chart.register(CategoryScale);
function Dasboard() {
return (
<div className="App">
<Summary />
</div>
);
}
export default Dasboard;

79
src/pages/Login.js Normal file
View File

@ -0,0 +1,79 @@
import React, { useState } from "react";
import { TextField, Button, Box, Typography, Grid, Paper } from "@mui/material";
import {Link, useNavigate } from 'react-router-dom';
const LoginPage = () => {
// State for email and password
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (email && password) {
// Handle login logic here, for example, API call
console.log("Logged in with:", { email, password });
localStorage.setItem('authToken', email)
navigate('/');
} else {
alert("Please fill in both fields.");
}
};
return (
<Grid
container
justifyContent="center"
alignItems="center"
style={{ minHeight: "100vh", backgroundColor: "#f4f6f8" }}
>
<Grid item xs={12} sm={6} md={4}>
<Paper elevation={3} sx={{ padding: 3 }}>
<Typography variant="h5" align="center" gutterBottom>
Login
</Typography>
<form onSubmit={handleSubmit}>
<Box mb={2}>
<TextField
label="Email"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
required
/>
</Box>
<Box mb={2}>
<TextField
label="Password"
variant="outlined"
fullWidth
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
required
/>
</Box>
<Box mt={2} textAlign="center">
<Button>
<Link to="/register">Register</Link>
</Button>
<Button
variant="contained"
color="primary"
type="submit"
fullWidth
>
Login
</Button>
</Box>
</form>
</Paper>
</Grid>
</Grid>
);
};
export default LoginPage;

156
src/pages/ManageAccess.js Normal file
View File

@ -0,0 +1,156 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'name', label: 'Name', minWidth: 100 },
{
id: 'internalName',
label: 'Internal Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'description',
label: 'Description',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 5,
"data": [
{
"description": "Default PIN Credential",
"id": 1,
"internalName": "pin_credential",
"name": "PIN Credential"
},
{
"description": "Partner Secret Auth Credential",
"id": 2,
"internalName": "secret_auth",
"name": "Secret Auth"
},
{
"description": "Partner API Key",
"id": 3,
"internalName": "api_key",
"name": "APIKey"
},
{
"description": "Web Access Credential",
"id": 4,
"internalName": "web_credential",
"name": "Web Credential"
},
{
"description": "One To Many Transfers",
"id": 5,
"internalName": "otm_tpay",
"name": "OTM TPay"
}
],
"recordsTotal": 5
};
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Access</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

211
src/pages/ManageAccount.js Normal file
View File

@ -0,0 +1,211 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'name', label: 'Name', minWidth: 100 },
{
id: 'description',
label: 'Description',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'systemAccount',
label: 'System Account',
minWidth: 170,
align: 'right',
},
{ id: 'createdDate', label: 'Created Date', minWidth: 100 },
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
function generateData(data, column) {
if (column === 'systemAccount') return data ? 'true' : 'false';
return data;
}
const rows = {
"recordsFiltered": 5,
"data": [
{
"createdDate": "2019-12-05T09:18:06.000+0000",
"creditLimit": null,
"currency": null,
"description": "Rekening Member eMoney",
"formattedCreatedDate": "2019-12-05 18:18:06",
"formattedCreditLimit": null,
"formattedLowerCreditLimit": null,
"formattedUpperCreditLimit": null,
"group": null,
"id": 1,
"lowerCreditLimit": null,
"name": "eMoney Account",
"systemAccount": false,
"upperCreditLimit": null
},
{
"createdDate": "2019-12-11T07:44:29.000+0000",
"creditLimit": null,
"currency": null,
"description": "Topup Account",
"formattedCreatedDate": "2019-12-11 16:44:29",
"formattedCreditLimit": null,
"formattedLowerCreditLimit": null,
"formattedUpperCreditLimit": null,
"group": null,
"id": 24,
"lowerCreditLimit": null,
"name": "Topup Account",
"systemAccount": true,
"upperCreditLimit": null
},
{
"createdDate": "2019-12-05T09:19:19.000+0000",
"creditLimit": null,
"currency": null,
"description": "Rekening Merchant",
"formattedCreatedDate": "2019-12-05 18:19:19",
"formattedCreditLimit": null,
"formattedLowerCreditLimit": null,
"formattedUpperCreditLimit": null,
"group": null,
"id": 39,
"lowerCreditLimit": null,
"name": "Merchant Account",
"systemAccount": false,
"upperCreditLimit": null
},
{
"createdDate": "2019-12-05T09:19:25.000+0000",
"creditLimit": null,
"currency": null,
"description": "Rekening Deposit",
"formattedCreatedDate": "2019-12-05 18:19:25",
"formattedCreditLimit": null,
"formattedLowerCreditLimit": null,
"formattedUpperCreditLimit": null,
"group": null,
"id": 40,
"lowerCreditLimit": null,
"name": "Deposit Account",
"systemAccount": false,
"upperCreditLimit": null
},
{
"createdDate": "2021-04-13T16:45:13.000+0000",
"creditLimit": null,
"currency": null,
"description": "Pooling account to maintain cash in/out member to bank",
"formattedCreatedDate": "2021-04-14 01:45:13",
"formattedCreditLimit": null,
"formattedLowerCreditLimit": null,
"formattedUpperCreditLimit": null,
"group": null,
"id": 41,
"lowerCreditLimit": null,
"name": "Cash out/in account to bank",
"systemAccount": true,
"upperCreditLimit": null
}
],
"recordsTotal": 5
};
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Account</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : generateData(value, column.id)
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

View File

@ -0,0 +1,113 @@
import React, { useState } from "react";
import {
TextField,
Button,
Box,
Typography,
Paper,
InputLabel,
Select,
MenuItem
} from "@mui/material";
const SettingPage = () => {
// State for form fields
const [accessType, setAccessType] = useState("");
const [username, setUsername] = useState("");
const [credential, setCredential] = useState("");
const [confirmCredential, setConfirmCredential] = useState("");
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (credential !== confirmCredential) {
alert("Credentials do not match!");
return;
}
if (accessType && username && credential && setConfirmCredential) {
// Handle registration logic, like calling an API to create the user
console.log("Registered with:", { accessType, username, credential });
} else {
alert("Please fill in all fields.");
}
};
return (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Access</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ padding: 3 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Member Credential</Typography>
<form onSubmit={handleSubmit}>
<Box mb={2} m={2}>
<InputLabel id="demo-simple-select-label">Access Type</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={accessType}
label="Access Type"
variant="outlined"
fullWidth
required
onChange={(e) => setAccessType(e.target.value)}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
{/* <TextField
label="Access Type"
variant="outlined"
fullWidth
value={accessType}
onChange={(e) => setAccessType(e.target.value)}
required
/> */}
</Box>
<Box mb={2} m={2}>
<TextField
label="Username"
variant="outlined"
fullWidth
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Credential"
variant="outlined"
fullWidth
value={credential}
onChange={(e) => setCredential(e.target.value)}
type="password"
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Confirm Credential"
variant="outlined"
fullWidth
value={confirmCredential}
onChange={(e) => setConfirmCredential(e.target.value)}
type="password"
required
/>
</Box>
<Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px'}} variant="contained">Edit</Button>
<Button variant="contained" color="success">Submit</Button>
</Box>
</form>
</Paper>
</Box>
</Box>
</Box>
);
};
export default SettingPage;

128
src/pages/ManageCurrency.js Normal file
View File

@ -0,0 +1,128 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'name', label: 'Name', minWidth: 100 },
{ id: 'code', label: 'Code', minWidth: 100 },
{ id: 'prefix', label: 'Prefix', minWidth: 100 },
{ id: 'trailer', label: 'Trailer', minWidth: 100 },
{ id: 'format', label: 'Format', minWidth: 100 },
{ id: 'grouping', label: 'Grouping Separator', minWidth: 100 },
{ id: 'decimal', label: 'Decimal Separator', minWidth: 100 },
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 1,
"data": [
{
"code": "USD",
"decimal": ".",
"format": "#,##0.00",
"grouping": ",",
"id": 2,
"name": "Dollar",
"prefix": "$",
"trailer": ""
}
],
"recordsTotal": 1
};
export default function ManageCurrency() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Currency</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Group</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

142
src/pages/ManageGroups.js Normal file
View File

@ -0,0 +1,142 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'createdDate', label: 'Created Date', minWidth: 100 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'description',
label: 'Description',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
function createData(id, name, description, population, size) {
const today = new Date();
return { id, name, description, population, size, createdDate: today.toString()};
}
const rows = [
createData(1,'India', 'IN', 1324171354, 3287263),
createData(2,'China', 'CN', 1403500365, 9596961),
createData(3,'Italy', 'IT', 60483973, 301340),
createData(4,'United States', 'US', 327167434, 9833520),
createData(5,'Canada', 'CA', 37602103, 9984670),
createData(6,'Australia', 'AU', 25475400, 7692024),
createData(7,'Germany', 'DE', 83019200, 357578),
createData(8,'Ireland', 'IE', 4857000, 70273),
createData(9,'Mexico', 'MX', 126577691, 1972550),
createData(10,'Japan', 'JP', 126317000, 377973),
createData(11,'France', 'FR', 67022000, 640679),
createData(12,'United Kingdom', 'GB', 67545757, 242495),
createData(13,'Russia', 'RU', 146793744, 17098246),
createData(14,'Nigeria', 'NG', 200962417, 923768),
createData(15,'Brazil', 'BR', 210147125, 8515767),
];
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Group</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Group</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

240
src/pages/ManageMembers.js Normal file
View File

@ -0,0 +1,240 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'username', label: 'Username', minWidth: 100 },
{
id: 'group',
label: 'Group',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'name',
label: 'Name',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'email',
label: 'Email',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'createdDate',
label: 'Created Date',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 35023,
"data": [
{
"createdDate": "2024-12-29 15:56:00",
"groupID": 36871,
"name": "Tomas Pinto Amaral",
"id": 36871,
"msisdn": "67074546696",
"email": "tomasamaral1302@gmail.com",
"username": "67074546696",
"group": "REGULER"
},
{
"createdDate": "2024-12-28 23:15:00",
"groupID": 36870,
"name": "Eleioterio Jeronimo Dos Santos Belmonte",
"id": 36870,
"msisdn": "67074677364",
"email": "Ellebambros6@gmail.con",
"username": "67074677364",
"group": "REGULER"
},
{
"createdDate": "2024-12-28 06:52:00",
"groupID": 36869,
"name": "Joao de Brito ximenes ",
"id": 36869,
"msisdn": "67073650842",
"email": "ximenesjhon42@gmail.com",
"username": "67073650842",
"group": "REGULER"
},
{
"createdDate": "2024-12-28 03:44:00",
"groupID": 36868,
"name": "nelson da costa moniz calau",
"id": 36868,
"msisdn": "67078525938",
"email": "calaunelson842@gmail.com",
"username": "67078525938",
"group": "REGULER"
},
{
"createdDate": "2024-12-27 10:35:00",
"groupID": 36867,
"name": "Arcenia Maria Martins",
"id": 36867,
"msisdn": "67078601536",
"email": "arceniamartins04@gmail.com",
"username": "67078601536",
"group": "REGULER"
},
{
"createdDate": "2024-12-26 22:29:00",
"groupID": 36866,
"name": "Yakov",
"id": 36866,
"msisdn": "79604742286",
"email": "makarevichyakov2004@gmail.com",
"username": "79604742286",
"group": "REGULER"
},
{
"createdDate": "2024-12-23 15:44:00",
"groupID": 36865,
"name": "Juliao Baptista",
"id": 36865,
"msisdn": "67078248108",
"email": "juliao.baptista.1988@gmail.com",
"username": "67078248108",
"group": "REGULER"
},
{
"createdDate": "2024-12-20 15:48:00",
"groupID": 36864,
"name": "Celicia A. Lina da Silva Pereira",
"id": 36864,
"msisdn": "67073565079",
"email": "abulinadasilva@gamail.com",
"username": "67073565079",
"group": "PREMIUM"
},
{
"createdDate": "2024-12-19 23:26:00",
"groupID": 36863,
"name": "Noe Afonso guterres",
"id": 36863,
"msisdn": "67077775543",
"email": "noeguterres9@gmail.com",
"username": "67077775543",
"group": "REGULER"
},
{
"createdDate": "2024-12-19 20:08:00",
"groupID": 36862,
"name": "Leandro Simões De Araújo ",
"id": 36862,
"msisdn": "67073854248",
"email": "leoandroaraujo016@gmail.com",
"username": "67073854248",
"group": "REGULER"
}
],
"recordsTotal": 35023
};
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Member</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

142
src/pages/ManageMenu.js Normal file
View File

@ -0,0 +1,142 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'createdDate', label: 'Created Date', minWidth: 100 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'description',
label: 'Description',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
function createData(id, name, description, population, size) {
const today = new Date();
return { id, name, description, population, size, createdDate: today.toString()};
}
const rows = [
createData(1,'India', 'IN', 1324171354, 3287263),
createData(2,'China', 'CN', 1403500365, 9596961),
createData(3,'Italy', 'IT', 60483973, 301340),
createData(4,'United States', 'US', 327167434, 9833520),
createData(5,'Canada', 'CA', 37602103, 9984670),
createData(6,'Australia', 'AU', 25475400, 7692024),
createData(7,'Germany', 'DE', 83019200, 357578),
createData(8,'Ireland', 'IE', 4857000, 70273),
createData(9,'Mexico', 'MX', 126577691, 1972550),
createData(10,'Japan', 'JP', 126317000, 377973),
createData(11,'France', 'FR', 67022000, 640679),
createData(12,'United Kingdom', 'GB', 67545757, 242495),
createData(13,'Russia', 'RU', 146793744, 17098246),
createData(14,'Nigeria', 'NG', 200962417, 923768),
createData(15,'Brazil', 'BR', 210147125, 8515767),
];
export default function ManageMenus() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Menu</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

View File

@ -0,0 +1,141 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'moduleURL',
label: 'Destination Module',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 2,
"data": [
{
"enabled": false,
"id": 1,
"moduleURL": "https://tpay.tl/middle-tpay/notif/sender",
"name": "notifSender",
"notificationType": null,
"transferTypeID": null
},
{
"enabled": false,
"id": 2,
"moduleURL": "https://tpay.tl/middle-tpay/notif/receiver",
"name": "notifBenefeciary",
"notificationType": null,
"transferTypeID": null
}
],
"recordsTotal": 2
}
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Notification</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

View File

@ -0,0 +1,257 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{ id: 'fromAccountName', label: 'From Account', minWidth: 100 },
{ id: 'toAccountName', label: 'To Account', minWidth: 100 },
{
id: 'description',
label: 'Description',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 21,
"data": [
{
"description": "Transaction for Payment Mytelkomcel",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 58,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Payment Mytelkomcel",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Disburse transaction EDTL from user to Agent",
"fromAccountName": "Merchant Account",
"fromAccounts": 39,
"id": 57,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.00,
"name": "Disburse transaction EDTL",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Transaction for payment EDTL",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 56,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Sosa Token EDTL",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Disburs myloja to agent",
"fromAccountName": "Merchant Account",
"fromAccounts": 39,
"id": 55,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Disburs myloja to agent",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Purchase Pulsa",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 54,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.00,
"name": "Rekarga Pulsa",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Transaction for payment MyLoja",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 53,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Payment MyLoja",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Cashout Member to Bank Account",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 52,
"maxAmount": 300.00,
"maxCount": 10,
"minAmount": 1.00,
"name": "Dada Osan P24",
"otpThreshold": 0.00,
"toAccountName": "Cash out/in account to bank",
"toAccounts": 41
},
{
"description": "Topup Member e-money from Bank",
"fromAccountName": "Cash out/in account to bank",
"fromAccounts": 41,
"id": 51,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 1.00,
"name": "Top up P24",
"otpThreshold": 0.00,
"toAccountName": "eMoney Account",
"toAccounts": 1
},
{
"description": "Transaction for buying voucher games ",
"fromAccountName": "eMoney Account",
"fromAccounts": 1,
"id": 50,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Payment GamesTL",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
},
{
"description": "Partner disburse to agent or driver account",
"fromAccountName": "Merchant Account",
"fromAccounts": 39,
"id": 49,
"maxAmount": 0.00,
"maxCount": 0,
"minAmount": 0.01,
"name": "Disburse agent or driver",
"otpThreshold": 0.00,
"toAccountName": "Merchant Account",
"toAccounts": 39
}
],
"recordsTotal": 21
};
export default function ManageGroups() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Transfer Type</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

View File

@ -0,0 +1,254 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'username',
label: 'Username',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'active',
label: 'Enabled',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'secureTransaction',
label: 'Secure',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
const rows = {
"recordsFiltered": 13,
"data": [
{
"active": true,
"group": null,
"hash": "edtl",
"id": 20,
"name": "dw-tpay-edtl",
"password": "123456",
"permissionID": null,
"secureTransaction": true,
"username": "doku_tpay_edtl"
},
{
"active": true,
"group": null,
"hash": "scheduler",
"id": 19,
"name": "scheduler",
"password": "123456",
"permissionID": null,
"secureTransaction": false,
"username": "scheduler"
},
{
"active": true,
"group": null,
"hash": "YL29DDQ66XZJ67TH",
"id": 18,
"name": "tpay-biller-nontransactional",
"password": "tpay-biller",
"permissionID": null,
"secureTransaction": false,
"username": "tpay-biller-nontransactional"
},
{
"active": true,
"group": null,
"hash": "YL29DDQ66XZJ67TH",
"id": 17,
"name": "tpay-biller",
"password": "tpay-biller",
"permissionID": null,
"secureTransaction": true,
"username": "tpay-biller"
},
{
"active": true,
"group": null,
"hash": "p24",
"id": 16,
"name": "dw-tpay-p24-nontransactional",
"password": "123456",
"permissionID": null,
"secureTransaction": false,
"username": "dokup24tpaynontransactional"
},
{
"active": true,
"group": null,
"hash": "p24",
"id": 15,
"name": "dw-tpay-p24",
"password": "123456",
"permissionID": null,
"secureTransaction": true,
"username": "dokup24tpay"
},
{
"active": true,
"group": null,
"hash": "doku",
"id": 14,
"name": "dw-mobileapi-tpay-non-transactional",
"password": "123456",
"permissionID": null,
"secureTransaction": false,
"username": "doku_dev_non"
},
{
"active": true,
"group": null,
"hash": "dokusimpel",
"id": 13,
"name": "simpel-ads-tpay",
"password": "simpel",
"permissionID": null,
"secureTransaction": false,
"username": "simpel"
},
{
"active": true,
"group": null,
"hash": "doku",
"id": 12,
"name": "dw-mobileapi-tpay",
"password": "123456",
"permissionID": null,
"secureTransaction": true,
"username": "doku_dev"
},
{
"active": true,
"group": null,
"hash": "MW7389B8ikj83990",
"id": 11,
"name": "Middleware Bank",
"password": "123456",
"permissionID": null,
"secureTransaction": false,
"username": "mwbank"
}
],
"recordsTotal": 13
}
export default function ManageWebservice() {
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);
};
function generateData(data, column) {
if (column === 'secureTransaction' || column === 'active') return data ? 'true' : 'false';
return data;
}
return (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Webservice</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : generateData(value, column.id)
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

142
src/pages/MemberKYC.js Normal file
View File

@ -0,0 +1,142 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import { Box, Typography, Button, TextField } from '@mui/material';
import IconButton from '@mui/material/IconButton';
import SearchIcon from '@mui/icons-material/Search';
const columns = [
{ id: 'id', label: 'ID', minWidth: 50 },
{ id: 'createdDate', label: 'Created Date', minWidth: 100 },
{
id: 'name',
label: 'Name',
minWidth: 100,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'description',
label: 'Description',
minWidth: 170,
align: 'right',
format: (value) => value.toLocaleString('en-US'),
},
{
id: 'action',
label: 'Action',
minWidth: 170,
align: 'right',
format: (value) => value.toFixed(2),
},
];
function createData(id, name, description, population, size) {
const today = new Date();
return { id, name, description, population, size, createdDate: today.toString()};
}
const rows = [
createData(1,'India', 'IN', 1324171354, 3287263),
createData(2,'China', 'CN', 1403500365, 9596961),
createData(3,'Italy', 'IT', 60483973, 301340),
createData(4,'United States', 'US', 327167434, 9833520),
createData(5,'Canada', 'CA', 37602103, 9984670),
createData(6,'Australia', 'AU', 25475400, 7692024),
createData(7,'Germany', 'DE', 83019200, 357578),
createData(8,'Ireland', 'IE', 4857000, 70273),
createData(9,'Mexico', 'MX', 126577691, 1972550),
createData(10,'Japan', 'JP', 126317000, 377973),
createData(11,'France', 'FR', 67022000, 640679),
createData(12,'United Kingdom', 'GB', 67545757, 242495),
createData(13,'Russia', 'RU', 146793744, 17098246),
createData(14,'Nigeria', 'NG', 200962417, 923768),
createData(15,'Brazil', 'BR', 210147125, 8515767),
];
export default function MemberKyc() {
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 (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Member KYC</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary">Create New Member</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', pr: 2, }}>
<TextField id="standard-basic" label="Search" variant="standard" />
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
</Box>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{
column.id === 'action' ? (
<Button>Details</Button>
) : value
}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
</Box>
</Box>
);
}

141
src/pages/Register.js Normal file
View File

@ -0,0 +1,141 @@
import React, { useState } from "react";
import {Link} from 'react-router-dom';
import {
TextField,
Button,
Box,
Typography,
Grid,
Paper,
InputAdornment,
IconButton,
FormControl,
InputLabel,
OutlinedInput,
} from "@mui/material";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
const RegisterPage = () => {
// State for form fields
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
// Handle password visibility toggle
const handleClickShowPassword = () => setShowPassword(!showPassword);
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (password !== confirmPassword) {
alert("Passwords do not match!");
return;
}
if (name && email && password && confirmPassword) {
// Handle registration logic, like calling an API to create the user
console.log("Registered with:", { name, email, password });
} else {
alert("Please fill in all fields.");
}
};
return (
<Grid
container
justifyContent="center"
alignItems="center"
style={{ minHeight: "100vh", backgroundColor: "#f4f6f8" }}
>
<Grid item xs={12} sm={6} md={4}>
<Paper elevation={3} sx={{ padding: 3 }}>
<Typography variant="h5" align="center" gutterBottom>
Create an Account
</Typography>
<form onSubmit={handleSubmit}>
<Box mb={2}>
<TextField
label="Name"
variant="outlined"
fullWidth
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</Box>
<Box mb={2}>
<TextField
label="Email"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
required
/>
</Box>
<Box mb={2}>
<FormControl variant="outlined" fullWidth required>
<InputLabel>Password</InputLabel>
<OutlinedInput
label="Password"
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
endAdornment={
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
</Box>
<Box mb={2}>
<FormControl variant="outlined" fullWidth required>
<InputLabel>Confirm Password</InputLabel>
<OutlinedInput
label="Confirm Password"
type={showPassword ? "text" : "password"}
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
endAdornment={
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
</Box>
<Box mt={2} textAlign="center">
<Button>
<Link to="/login">Login</Link>
</Button>
<Button
variant="contained"
color="primary"
type="submit"
fullWidth
>
Register
</Button>
</Box>
</form>
</Paper>
</Grid>
</Grid>
);
};
export default RegisterPage;

77
src/pages/Setting.js Normal file
View File

@ -0,0 +1,77 @@
import React, { useState } from "react";
import {
TextField,
Button,
Box,
Typography,
Paper,
} from "@mui/material";
const SettingPage = () => {
// State for form fields
const [name, setName] = useState("");
const [email, setEmail] = useState("");
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (name && email) {
// Handle registration logic, like calling an API to create the user
console.log("Registered with:", { name, email });
} else {
alert("Please fill in all fields.");
}
};
return (
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Webservice</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ padding: 3 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<form onSubmit={handleSubmit}>
<Box mb={2} m={2}>
<TextField
label="Username"
variant="outlined"
fullWidth
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Name"
variant="outlined"
fullWidth
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Email"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
required
/>
</Box>
<Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px'}} variant="contained">Edit</Button>
<Button variant="contained" color="success">Submit</Button>
</Box>
</form>
</Paper>
</Box>
</Box>
</Box>
);
};
export default SettingPage;

95
src/routes/routes.js Normal file
View File

@ -0,0 +1,95 @@
import React from 'react';
import { Routes, Route, useLocation, Navigate } from 'react-router-dom';
import "../pages/Dashboard.css";
import Sidebar from "../components/SideBar";
import Header from "../components/Header";
import { Box, Toolbar } from "@mui/material";
// GENERAL
import Dasboard from '../pages/Dashboard';
import LoginPage from '../pages/Login';
import RegisterPage from '../pages/Register';
// ADMIN
import ManageTransfers from '../pages/ManageTransfers';
import ManageNotifications from '../pages/ManageNotifications';
import ManageAccess from '../pages/ManageAccess';
import ManageAccounts from '../pages/ManageAccount';
import ManageGroups from '../pages/ManageGroups';
import ManageMembers from '../pages/ManageMembers';
import ManageMenus from '../pages/ManageMenu';
import MemberKyc from '../pages/MemberKYC';
import ManageCredential from '../pages/ManageCredential';
import ManageCurrency from '../pages/ManageCurrency';
import ManageWebservice from '../pages/ManageWebservice';
import SettingPage from '../pages/Setting';
// ESCROW
import TransactionHistory from '../escrowPages/TransactionHistory';
import TransferPage from '../escrowPages/Transfer';
import TicketConfirmationPage from '../escrowPages/TicketConfirmation';
// Mock Authentication Function
const isAuthenticated = () => {
return localStorage.getItem("authToken") !== null;
};
// Middleware Component for Protected Routes
const ProtectedRoute = ({ children }) => {
if (!isAuthenticated()) {
return <Navigate to="/login" replace />;
}
return children;
};
const Layout = ({ children }) => {
const location = useLocation();
// Define routes where the Navbar should not appear
const hideNavbarRoutes = ['/login', "/register"];
const shouldShowLayout = !hideNavbarRoutes.includes(location.pathname);
return (
<>
{shouldShowLayout &&
(
<div className="App">
<Box sx={{ display: "flex", backgroundColor: "#f5f5f5", color: "#333" }}>
<Sidebar />
<Box sx={{ flexGrow: 1 }}>
<Header />
<Toolbar />
<main>{children}</main>
</Box>
</Box>
</div>
)
}
</>
);
};
function App() {
return (
<Routes>
{/* GENERAL */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route exact path="/" element={<ProtectedRoute><Layout><Dasboard /></Layout></ProtectedRoute>} />
{/* ADMIN */}
<Route path="/manage-groups" element={<ProtectedRoute><Layout><ManageGroups /></Layout></ProtectedRoute>} />
<Route path="/manage-members" element={<ProtectedRoute><Layout><ManageMembers /></Layout></ProtectedRoute>} />
<Route path="/manage-member-credential" element={<ProtectedRoute><Layout><ManageCredential /></Layout></ProtectedRoute>} />
<Route path="/manage-access" element={<ProtectedRoute><Layout><ManageAccess /></Layout></ProtectedRoute>} />
<Route path="/manage-accounts" element={<ProtectedRoute><Layout><ManageAccounts /></Layout></ProtectedRoute>} />
<Route path="/manage-currency" element={<ProtectedRoute><Layout><ManageCurrency /></Layout></ProtectedRoute>} />
<Route path="/manage-transfers" element={<ProtectedRoute><Layout><ManageTransfers /></Layout></ProtectedRoute>} />
<Route path="/manage-notifications" element={<ProtectedRoute><Layout><ManageNotifications /></Layout></ProtectedRoute>} />
<Route path="/manage-menu" element={<ProtectedRoute><Layout><ManageMenus /></Layout></ProtectedRoute>} />
<Route path="/manage-webservice" element={<ProtectedRoute><Layout><ManageWebservice /></Layout></ProtectedRoute>} />
<Route path="/manage-member-kyc" element={<ProtectedRoute><Layout><MemberKyc /></Layout></ProtectedRoute>} />
<Route path="/setting" element={<ProtectedRoute><Layout><SettingPage /></Layout></ProtectedRoute>} />
{/* ESCROW */}
<Route path="/transaction-history" element={<ProtectedRoute><Layout><TransactionHistory /></Layout></ProtectedRoute>} />
<Route path="/transfer" element={<ProtectedRoute><Layout><TransferPage /></Layout></ProtectedRoute>} />
<Route path="/ticket-confirmation" element={<ProtectedRoute><Layout><TicketConfirmationPage /></Layout></ProtectedRoute>} />
</Routes>
);
}
export default App;

13
src/style/Chart.css Normal file
View File

@ -0,0 +1,13 @@
.chart {
margin: 20px 250px 0 270px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.chart h3 {
margin-bottom: 20px;
color: #333;
font-size: 18px;
}

26
src/style/Header.css Normal file
View File

@ -0,0 +1,26 @@
.header {
height: 60px;
background-color: #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
margin-left: 250px;
border-bottom: 1px solid #ddd;
}
.welcome h4 {
margin: 0;
font-size: 18px;
color: #333;
}
.actions i {
margin-left: 20px;
font-size: 20px;
cursor: pointer;
}
.actions i:hover {
color: #d32f2f;
}

View File

@ -0,0 +1,18 @@
/* src/MyCharts.css */
.charts-container {
display: flex;
justify-content: space-between;
gap: 20px;
flex-wrap: wrap;
padding: 20px;
}
.chart-item {
width: 30%;
min-width: 250px;
text-align: center;
}
.chart-item h3 {
margin-bottom: 10px;
}

29
src/style/SideBar.css Normal file
View File

@ -0,0 +1,29 @@
.sidebar {
width: 250px;
background-color: #d32f2f;
color: #fff;
height: 100vh;
position: fixed;
top: 0;
left: 0;
padding: 20px;
}
.sidebar h2 {
font-size: 24px;
margin-bottom: 20px;
}
.sidebar ul {
list-style-type: none;
padding: 0;
}
.sidebar ul li {
margin: 15px 0;
cursor: pointer;
}
.sidebar ul li:hover {
text-decoration: underline;
}

35
src/style/StatsCard.css Normal file
View File

@ -0,0 +1,35 @@
.stats-card {
width: 200px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
text-align: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.stats-card h4 {
font-size: 16px;
color: #666;
margin: 0 0 10px;
}
.stats-card h2 {
font-size: 28px;
margin: 0;
color: #333;
}
.stats-card span {
font-size: 14px;
display: block;
margin-top: 10px;
}
.stats-card span.positive {
color: green;
}
.stats-card span.negative {
color: red;
}

View File

@ -0,0 +1,38 @@
.transaction-list {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
padding: 20px;
margin: 20px 250px 0 270px;
}
.transaction-list h3 {
margin-bottom: 20px;
color: #333;
font-size: 18px;
}
.transaction-list ul {
list-style-type: none;
padding: 0;
}
.transaction-list li {
margin: 15px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.progress {
width: 70%;
background-color: #eee;
height: 8px;
border-radius: 4px;
overflow: hidden;
}
.progress-bar {
height: 8px;
background-color: #d32f2f;
}