update base url

This commit is contained in:
fro1991
2025-02-01 15:51:22 +07:00
parent 291d37265f
commit f35405f431
9 changed files with 1206 additions and 1145 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
REACT_APP_BASE_URL=/dashboard
REACT_APP_API_URL=https://tpay.shiblysolution.id/api/

View File

@ -1,58 +1,58 @@
{ {
"name": "new-tpay", "name": "new-tpay",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@mui/icons-material": "^6.2.1", "@mui/icons-material": "^6.2.1",
"@mui/material": "^6.2.1", "@mui/material": "^6.2.1",
"@reduxjs/toolkit": "^2.5.0", "@reduxjs/toolkit": "^2.5.0",
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"ajv-keywords": "^5.1.0", "ajv-keywords": "^5.1.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"chart.js": "^4.4.7", "chart.js": "^4.4.7",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"react": "^18.3.1", "react": "^18.3.1",
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"react-router-dom": "^7.1.1", "react-router-dom": "^7.1.1",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"redux": "^5.0.1", "redux": "^5.0.1",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
"start": "react-scripts start eslint-disable-next-line", "start": "react-scripts start eslint-disable-next-line",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
"react-app", "react-app",
"react-app/jest" "react-app/jest"
] ]
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
">0.2%", ">0.2%",
"not dead", "not dead",
"not op_mini all" "not op_mini all"
], ],
"development": [ "development": [
"last 1 chrome version", "last 1 chrome version",
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-private-property-in-object": "^7.25.9", "@babel/plugin-transform-private-property-in-object": "^7.25.9",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.1.0" "@testing-library/react": "^16.1.0"
} }
} }

View File

@ -1,31 +1,32 @@
import axios from 'axios'; import axios from "axios"
import Cookies from "js-cookie"; import Cookies from "js-cookie"
const token = Cookies.get(`token`) || null; const token = Cookies.get(`token`) || null
const headers = { const headers = {
"Access-Control-Allow-Origin": "*", // "Access-Control-Allow-Origin": "*",
"content-type":"application/json", // "content-type": "application/json",
}; }
if (token) headers["Authorization"] = `Bearer ${token}`; if (token) headers["Authorization"] = `Bearer ${token}`
const instance = axios.create({ const instance = axios.create({
baseURL: `https://tpay.shiblysolution.id/dashboard/`, // baseURL: `https://tpay.shiblysolution.id/dashboard/`,
// baseURL: 'https://api.telkomcel.tl/tpay-stg-dash-api/', // baseURL: 'https://api.telkomcel.tl/tpay-stg-dash-api/',
headers: headers baseURL: process.env.REACT_APP_API_URL,
headers: headers,
}) })
export async function fetchApi(path, method, data, params) { export async function fetchApi(path, method, data, params) {
try { try {
let query = params || {}; let query = params || {}
query.token = token query.token = token
let response = await instance({ let response = await instance({
method: method, method: method,
url: path, url: path,
data: data, data: data,
params: query params: query,
}); })
return response return response
} catch (error) { } catch (error) {
alert(error.message) alert(error.message)
} }
} }

View File

@ -1,24 +1,24 @@
import React from "react"; import React from "react"
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client"
import "./index.css"; import "./index.css"
import App from "./routes/routes"; import App from "./routes/routes"
import reportWebVitals from "./reportWebVitals"; import reportWebVitals from "./reportWebVitals"
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom"
import { Provider } from 'react-redux'; import { Provider } from "react-redux"
import store from './store/store'; import store from "./store/store"
const root = ReactDOM.createRoot(document.getElementById("root")); const root = ReactDOM.createRoot(document.getElementById("root"))
root.render( root.render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter basename={process.env.REACT_APP_BASE_URL}>
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode> </React.StrictMode>
</BrowserRouter> </BrowserRouter>
</Provider> </Provider>
); )
// If you want to start measuring performance in your app, pass a function // If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log)) // to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals(); reportWebVitals()

View File

@ -1,135 +1,109 @@
import React, { useState } from "react"; import React, { useState } from "react"
import { TextField, Button, Box, Typography, Grid, Paper, Avatar, Divider } from "@mui/material"; import { TextField, Button, Box, Typography, Grid, Paper, Avatar, Divider } from "@mui/material"
import {Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from "react-router-dom"
import Cookies from "js-cookie"; import Cookies from "js-cookie"
import { fetchApi } from '../config/axios'; import { fetchApi } from "../config/axios"
import logo from '../logo/logo.jpeg'; import logo from "../logo/logo.jpeg"
const LoginPage = () => { const LoginPage = () => {
// State for email and password // State for email and password
const [username, setUsername] = useState(""); const [username, setUsername] = useState("")
const [password, setPassword] = useState(""); const [password, setPassword] = useState("")
const navigate = useNavigate(); const navigate = useNavigate()
// Handle form submission // Handle form submission
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
try { try {
e.preventDefault(); e.preventDefault()
if (username && password) { if (username && password) {
// GET CREDIENTIAL // GET CREDIENTIAL
let user = await fetchApi('/api/login', 'POST', { username, password }); let user = await fetchApi("/d/login", "POST", { username, password })
if (user) { if (user) {
if (user.data && user.data.data) { if (user.data && user.data.data) {
let resUserLogin = user.data.data; let resUserLogin = user.data.data
console.log('resUserLogin', resUserLogin); console.log("resUserLogin", resUserLogin)
let roleList = JSON.stringify(resUserLogin.roles_list); let roleList = JSON.stringify(resUserLogin.roles_list)
Cookies.set('token', resUserLogin.token.access_token, { expires: 1, path: '/' }); Cookies.set("token", resUserLogin.token.access_token, { expires: 1, path: "/" })
Cookies.set('role', resUserLogin.role_name, { expires: 1, path: '/' }); Cookies.set("role", resUserLogin.role_name, { expires: 1, path: "/" })
Cookies.set('userId', resUserLogin.user.id, { expires: 1, path: '/' }); Cookies.set("userId", resUserLogin.user.id, { expires: 1, path: "/" })
Cookies.set('username', resUserLogin.user.username, { expires: 1, path: '/' }); Cookies.set("username", resUserLogin.user.username, { expires: 1, path: "/" })
// Cookies.set('roles_list', roleList, { expires: 1, path: '/' }); // Cookies.set('roles_list', roleList, { expires: 1, path: '/' });
localStorage.setItem('roles_list', roleList) localStorage.setItem("roles_list", roleList)
navigate('/'); navigate("/")
} else { } else {
alert(user.response.data.message); alert(user.response.data.message)
} }
} }
} else { } else {
alert("Please fill in both fields."); alert("Please fill in both fields.")
} }
} catch (error) { } catch (error) {
if (error.response) alert(error.response.data.message) if (error.response) alert(error.response.data.message)
else alert(error.message) else alert(error.message)
console.log(error); console.log(error)
} }
}; }
return ( return (
<Grid <Grid container justifyContent="center" alignItems="center" style={{ minHeight: "100vh", backgroundColor: "#f4f6f8" }}>
container <Grid item xs={12} sm={6} md={4}>
justifyContent="center" <Paper elevation={3} sx={{ padding: 3 }}>
alignItems="center" <Typography variant="h5" align="center" gutterBottom>
style={{ minHeight: "100vh", backgroundColor: "#f4f6f8" }} Login
> </Typography>
<Grid item xs={12} sm={6} md={4}> <form onSubmit={handleSubmit}>
<Paper elevation={3} sx={{ padding: 3 }}> <Box mb={2}>
<Typography variant="h5" align="center" gutterBottom> <TextField label="Email" variant="outlined" fullWidth value={username} onChange={(e) => setUsername(e.target.value)} type="text" required />
Login </Box>
</Typography> <Box mb={2}>
<form onSubmit={handleSubmit}> <TextField label="Password" variant="outlined" fullWidth value={password} onChange={(e) => setPassword(e.target.value)} type="password" required />
<Box mb={2}> </Box>
<TextField <Box mt={2} textAlign="center">
label="Email" <Button>
variant="outlined" <Link to="/register">Register</Link>
fullWidth </Button>
value={username} <Button variant="contained" color="primary" type="submit" fullWidth>
onChange={(e) => setUsername(e.target.value)} Login
type="text" </Button>
required </Box>
/> </form>
</Box> </Paper>
<Box mb={2}> </Grid>
<TextField <Box
label="Password" sx={{
variant="outlined" width: "100%",
fullWidth position: "fixed",
value={password} bottom: 0,
onChange={(e) => setPassword(e.target.value)} textAlign: "center",
type="password" bgcolor: "#f9f9f9", // Background color
required py: 2, // Padding
/> }}
</Box> >
<Box mt={2} textAlign="center"> {/* Divider (Horizontal Line) */}
<Button> <Divider sx={{ mb: 2 }} />
<Link to="/register">Register</Link>
</Button>
<Button
variant="contained"
color="primary"
type="submit"
fullWidth
>
Login
</Button>
</Box>
</form>
</Paper>
</Grid>
<Box
sx={{
width: "100%",
position: "fixed",
bottom: 0,
textAlign: "center",
bgcolor: "#f9f9f9", // Background color
py: 2, // Padding
}}
>
{/* Divider (Horizontal Line) */}
<Divider sx={{ mb: 2 }} />
{/* Content */}
<Box justifyItems={'center'}
sx={{
display: "flex",
alignItems: "center", // Align items vertically
justifyContent: "center", // Center content horizontally
gap: 1, // Space between logo and text
mt: 2, // Optional margin-top
}}>
<Avatar
src={logo}
alt="T-PAY"
sx={{ backgroundColor: 'red', width: '50px', height: '50px' }}
/>
<Typography variant="h6" sx={{ fontWeight: "bold" }}>T-PAY</Typography>
</Box>
<Typography variant="body2" sx={{ color: "gray" }}>
© 2025 TelinDigital Solution
</Typography>
</Box>
</Grid>
);
};
export default LoginPage; {/* Content */}
<Box
justifyItems={"center"}
sx={{
display: "flex",
alignItems: "center", // Align items vertically
justifyContent: "center", // Center content horizontally
gap: 1, // Space between logo and text
mt: 2, // Optional margin-top
}}
>
<Avatar src={logo} alt="T-PAY" sx={{ backgroundColor: "red", width: "50px", height: "50px" }} />
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
T-PAY
</Typography>
</Box>
<Typography variant="body2" sx={{ color: "gray" }}>
© 2025 TelinDigital Solution
</Typography>
</Box>
</Grid>
)
}
export default LoginPage

View File

@ -1,184 +1,144 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from "react"
import { import { TextField, Button, Box, Typography, Paper, FormControl, Select, InputLabel, MenuItem, FormControlLabel, Checkbox, FormLabel } from "@mui/material"
TextField, import { fetchApi } from "../config/axios"
Button, import WarningDialog from "../components/WarningDialog"
Box, import Cookies from "js-cookie"
Typography,
Paper,
FormControl,
Select,
InputLabel,
MenuItem,
FormControlLabel,
Checkbox,
FormLabel
} from "@mui/material";
import { fetchApi } from '../config/axios';
import WarningDialog from '../components/WarningDialog';
import Cookies from "js-cookie";
const ProfilePage = () => { const ProfilePage = () => {
// State for form fields // State for form fields
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
username: '', username: "",
name: '', name: "",
email: '', email: "",
status: '', status: "",
idRole: '', idRole: "",
password: '', password: "",
oldPassword: '', oldPassword: "",
confirmPassword: '', confirmPassword: "",
newPassword: '' newPassword: "",
// nik: '', // nik: '',
// position: '', // position: '',
// telp: '', // telp: '',
// address: '', // address: '',
// organisasi: '', // organisasi: '',
// devisi: '', // devisi: '',
// unit: '', // unit: '',
}); })
const [roles, setRoles] = useState([]); const [roles, setRoles] = useState([])
const [isModalOpen, setIsModalOpen] = useState(false); // ERROR MSG const [isModalOpen, setIsModalOpen] = useState(false) // ERROR MSG
const [error, setError] = useState(""); // ERROR MSG const [error, setError] = useState("") // ERROR MSG
useEffect(() => { useEffect(() => {
fetchUser() fetchUser()
fetchUserRoles() fetchUserRoles()
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, [])
async function fetchUser(params) { async function fetchUser(params) {
try { try {
let userId = Cookies.get(`userId`); let userId = Cookies.get(`userId`)
let token = Cookies.get(`token`); let token = Cookies.get(`token`)
let fetchUsers = await fetchApi(`/api/user/detail/${userId}`, 'GET', null, { token: token });
// setFormData({})
console.log(fetchUsers);
setFormData(fetchUsers.data.data)
} catch (error) {
console.log(error);
handleError(`${error.message}. \n ${error.response.data.error}`)
}
}
async function fetchUserRoles(params) { let fetchUsers = await fetchApi(`d/user/detail/${userId}`, "GET", null, { token: token })
try { // setFormData({})
let userRoles = await fetchApi('/api/user_role/list', 'GET', null, { console.log(fetchUsers)
limit: 10, setFormData(fetchUsers.data.data)
page: 1, } catch (error) {
with_deleted: true, console.log(error)
order_field: 'id', handleError(`${error.message}. \n ${error.response.data.error}`)
order_direction: 'ASC' }
}); }
console.log(userRoles);
if (userRoles.data && userRoles.data.data) setRoles(userRoles.data.data.list)
} catch (error) {
console.log(error);
handleError(`${error.message}. \n ${error.response.data.error}`)
}
}
// Handle form submission async function fetchUserRoles(params) {
const handleSubmit = (e) => { try {
e.preventDefault(); let userRoles = await fetchApi("d/user_role/list", "GET", null, {
// if (name && email) { limit: 10,
// // Handle registration logic, like calling an API to create the user page: 1,
// console.log("Registered with:", { name, email }); with_deleted: true,
// } else { order_field: "id",
// alert("Please fill in all fields."); order_direction: "ASC",
// } })
}; console.log(userRoles)
const handleChange = (e) => { if (userRoles.data && userRoles.data.data) setRoles(userRoles.data.data.list)
let { name, value } = e.target; } catch (error) {
if (name === 'status' && value === "Y") value = "N" console.log(error)
else if (name === 'status' && value === "N") value = "Y" handleError(`${error.message}. \n ${error.response.data.error}`)
setFormData((prev) => ({ ...prev, [name]: value })); }
}; }
const handleError = (msg) => { // ERROR MSG // Handle form submission
setError(msg); const handleSubmit = (e) => {
setIsModalOpen(true); 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.");
// }
}
const closeModal = () => { // ERROR MSG const handleChange = (e) => {
setIsModalOpen(false); let { name, value } = e.target
setError(""); if (name === "status" && value === "Y") value = "N"
}; else if (name === "status" && value === "N") value = "Y"
setFormData((prev) => ({ ...prev, [name]: value }))
async function updatePassword() { }
try {
let updatePassword = await fetchApi(`/api/user/update_password`, 'PUT', {
password: formData.password,
retype_password: formData.confirmPassword
});
console.log(updatePassword);
} catch (error) {
console.log(error);
}
}
return ( const handleError = (msg) => {
<Box sx={{ padding: 3 }}> // ERROR MSG
<WarningDialog // ERROR MSG setError(msg)
open={isModalOpen} setIsModalOpen(true)
onClose={closeModal} }
errorMessage={error}
/> const closeModal = () => {
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}> // ERROR MSG
<Typography sx={{ color: 'gray', fontSize: '30px' }}>User Profile</Typography> setIsModalOpen(false)
</Box> setError("")
<Box sx={{ padding: 3 }}> }
<Box sx={{ padding: 3 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}> async function updatePassword() {
<form onSubmit={handleSubmit}> try {
<Box mb={2} m={2}> let updatePassword = await fetchApi(`d/user/update_password`, "PUT", {
<TextField password: formData.password,
label="Username" retype_password: formData.confirmPassword,
name="username" })
variant="outlined" console.log(updatePassword)
fullWidth } catch (error) {
value={formData.username} console.log(error)
onChange={handleChange} }
required }
disabled
/> return (
</Box> <Box sx={{ padding: 3 }}>
<Box mb={2} m={2}> <WarningDialog // ERROR MSG
<TextField open={isModalOpen}
label="Name" onClose={closeModal}
name="name" errorMessage={error}
variant="outlined" />
fullWidth <Box sx={{ display: "flex", justifyContent: "flex-start", pr: 2 }}>
value={formData.name} <Typography sx={{ color: "gray", fontSize: "30px" }}>User Profile</Typography>
onChange={handleChange} </Box>
required <Box sx={{ padding: 3 }}>
/> <Box sx={{ padding: 3 }}>
</Box> <Paper sx={{ width: "100%", overflow: "hidden" }}>
<Box mb={2} m={2}> <form onSubmit={handleSubmit}>
<TextField <Box mb={2} m={2}>
label="Email" <TextField label="Username" name="username" variant="outlined" fullWidth value={formData.username} onChange={handleChange} required disabled />
name="email" </Box>
variant="outlined" <Box mb={2} m={2}>
fullWidth <TextField label="Name" name="name" variant="outlined" fullWidth value={formData.name} onChange={handleChange} required />
value={formData.email} </Box>
onChange={handleChange} <Box mb={2} m={2}>
type="email" <TextField label="Email" name="email" variant="outlined" fullWidth value={formData.email} onChange={handleChange} type="email" required />
required </Box>
/> <Box mb={2} m={2} sx={{ display: "flex", justifyContent: "flex-start" }}>
</Box> <FormLabel component="legend">
<Box mb={2} m={2} sx={{ display: 'flex', justifyContent: 'flex-start' }}> Status :
<FormLabel component="legend">Status : <FormControlLabel required label="Aktif" control={<Checkbox value={formData.status} name="status" onClick={handleChange} checked={formData.status === "Y" ? true : false} />} />
<FormControlLabel required label="Aktif" control={ </FormLabel>
<Checkbox value={formData.status} name="status" onClick={handleChange} </Box>
checked={ formData.status === "Y" ? true : false } /> {/* <Box mb={2} m={2}>
}/>
</FormLabel>
</Box>
{/* <Box mb={2} m={2}>
<TextField <TextField
label="NIK" label="NIK"
variant="outlined" variant="outlined"
@ -269,94 +229,62 @@ const ProfilePage = () => {
</Select> </Select>
</FormControl> </FormControl>
</Box> */} </Box> */}
<Box mb={2} m={2}> <Box mb={2} m={2}>
<FormControl fullWidth required> <FormControl fullWidth required>
<InputLabel id="organization-label">Role</InputLabel> <InputLabel id="organization-label">Role</InputLabel>
<Select <Select labelId="organization-label" id="organization" value={formData.idRole} label="Role" onChange={handleChange} name="idRole">
labelId="organization-label" {roles.map((el, idx) => (
id="organization" <MenuItem key={idx} value={el.id}>
value={formData.idRole} {el.name}
label="Role" </MenuItem>
onChange={handleChange} ))}
name='idRole' </Select>
> </FormControl>
{ </Box>
roles.map((el, idx) => ( <Box mb={2} m={2}>
<MenuItem key={idx} value={el.id}>{el.name}</MenuItem> <TextField label="Password" name="password" value={formData.password} onChange={handleChange} fullWidth type="password" required disabled />
)) </Box>
}
</Select>
</FormControl>
</Box>
<Box mb={2} m={2}>
<TextField
label="Password"
name="password"
value={formData.password}
onChange={handleChange}
fullWidth
type="password"
required
disabled
/>
</Box>
<Box mt={2} mb={2} textAlign="center"> <Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px' }} variant="contained">Cancel</Button> <Button style={{ marginRight: "5px" }} variant="contained">
<Button variant="contained" color="success">Submit</Button> Cancel
</Box> </Button>
</form> <Button variant="contained" color="success">
</Paper> Submit
</Box> </Button>
</Box> </Box>
</form>
</Paper>
</Box>
</Box>
<Box sx={{ padding: 3 }}> <Box sx={{ padding: 3 }}>
<Box sx={{ padding: 3 }}> <Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>User Password</Typography> <Typography sx={{ color: "gray", fontSize: "30px" }}>User Password</Typography>
<Paper sx={{ width: '100%', overflow: 'hidden' }}> <Paper sx={{ width: "100%", overflow: "hidden" }}>
<Box mb={2} m={2}> <Box mb={2} m={2}>
<TextField <TextField label="Old Password" name="oldPassword" value={formData.oldPassword} onChange={handleChange} fullWidth type="password" required />
label="Old Password" </Box>
name="oldPassword" <Box mb={2} m={2}>
value={formData.oldPassword} <TextField label="New Password" name="newPassword" value={formData.newPassword} onChange={handleChange} fullWidth type="password" required />
onChange={handleChange} </Box>
fullWidth <Box mb={2} m={2}>
type="password" <TextField label="Confirm Password" name="confirmPassword" value={formData.confirmPassword} onChange={handleChange} fullWidth type="password" required />
required </Box>
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="New Password"
name="newPassword"
value={formData.newPassword}
onChange={handleChange}
fullWidth
type="password"
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
fullWidth
type="password"
required
/>
</Box>
<Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: '5px' }} variant="contained">Cancel</Button>
<Button variant="contained" onClick={() => updatePassword} color="success">Update</Button>
</Box>
</Paper>
</Box>
</Box>
</Box>
);
};
export default ProfilePage; <Box mt={2} mb={2} textAlign="center">
<Button style={{ marginRight: "5px" }} variant="contained">
Cancel
</Button>
<Button variant="contained" onClick={() => updatePassword} color="success">
Update
</Button>
</Box>
</Paper>
</Box>
</Box>
</Box>
)
}
export default ProfilePage

View File

@ -1,26 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from "react"
import { import { Container, Typography, Button, Dialog, DialogTitle, DialogContent, DialogActions, TextField, IconButton, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Checkbox, Paper, Box } from "@mui/material"
Container, import AddIcon from "@mui/icons-material/Add"
Typography, import { fetchApi } from "../config/axios"
Button,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
IconButton,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Checkbox,
Paper,
Box
} from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import { fetchApi } from '../config/axios';
// Initial list of roles and menus // Initial list of roles and menus
// const initialRoles = ['Admin', 'Escrow', 'Agent']; // const initialRoles = ['Admin', 'Escrow', 'Agent'];
@ -38,203 +19,200 @@ import { fetchApi } from '../config/axios';
// ]; // ];
const RoleMenuTable = () => { const RoleMenuTable = () => {
const [roles, setRoles] = useState([]); const [roles, setRoles] = useState([])
// const [roleMenus, setRoleMenus] = useState([]); // const [roleMenus, setRoleMenus] = useState([]);
const [menus, setMenus] = useState([]); const [menus, setMenus] = useState([])
const [openDialog, setOpenDialog] = useState(false); const [openDialog, setOpenDialog] = useState(false)
const [newRole, setNewRole] = useState(''); const [newRole, setNewRole] = useState("")
const [confirmDialog, setConfirmDialog] = useState({ const [confirmDialog, setConfirmDialog] = useState({
open: false, roleName: '', menuData: [], roleId: '', menuId: '', status: null, menuName: '' open: false,
}); roleName: "",
menuData: [],
useEffect(() => { roleId: "",
fetchData() menuId: "",
// eslint-disable-next-line status: null,
}, []); menuName: "",
})
async function fetchData(params) { useEffect(() => {
try { fetchData()
let userRole = await fetchApi('/api/user_role/list', 'GET', null, { // eslint-disable-next-line
limit: 5, }, [])
page: 1,
with_deleted: true,
order_field: 'id',
order_direction: 'ASC'
});
let userMenu = await fetchApi('/api/menus/list', 'GET', null, {
limit: 50,
page: 1,
with_deleted: true,
order_field: 'id',
order_direction: 'ASC'
});
setMenus(userMenu.data.data.list)
console.log('role',userRole);
console.log('menu',userMenu);
if (userRole.data && userRole.data.data) setRoles(userRole.data.data.list)
} catch (error) {
console.log(error);
}
}
const handleCheckboxChange = (roleName, menuData, roleId, menuId, status, menuName) => { async function fetchData(params) {
setConfirmDialog({ open: true, roleName, menuData, roleId, menuId, status, menuName }); try {
}; let userRole = await fetchApi("d/user_role/list", "GET", null, {
limit: 5,
page: 1,
with_deleted: true,
order_field: "id",
order_direction: "ASC",
})
let userMenu = await fetchApi("/api/menus/list", "GET", null, {
limit: 50,
page: 1,
with_deleted: true,
order_field: "id",
order_direction: "ASC",
})
setMenus(userMenu.data.data.list)
const handleConfirm = async (confirm) => { console.log("role", userRole)
const { roleName, menuData, roleId, menuId, status } = confirmDialog; console.log("menu", userMenu)
try { if (userRole.data && userRole.data.data) setRoles(userRole.data.data.list)
if (confirm) { } catch (error) {
console.log(confirm,confirmDialog); console.log(error)
if (status) { }
let generateRoles = menuData.filter(el => +el !== +menuId); }
console.log(generateRoles);
let userMenu = await fetchApi(`/api/user_role/update/${roleId}`, 'PUT', {
name: roleName,
roles: generateRoles,
status: "Y"
})
console.log(userMenu);
await fetchData()
} else {
let generateRoles = menuData.filter(el => +el !== +menuId);
generateRoles.push(`${menuId}`)
console.log(generateRoles);
let userMenu = await fetchApi(`/api/user_role/update/${roleId}`, 'PUT', {
name: roleName,
roles: generateRoles,
status: "Y"
})
console.log(userMenu);
await fetchData()
}
}
setConfirmDialog({ open: false, role: '', menu: '' });
} catch (error) {
console.log(error);
}
};
const handleAddRole = async () => { const handleCheckboxChange = (roleName, menuData, roleId, menuId, status, menuName) => {
try { setConfirmDialog({ open: true, roleName, menuData, roleId, menuId, status, menuName })
await fetchApi('/api/user_role/create', 'POST', { }
"name": newRole,
"roles": [],
"status": "Y"
});
await fetchData();
} catch (error) {
console.log(error);
}
setNewRole('');
setOpenDialog(false);
};
const deleteRole = async (role) => { const handleConfirm = async (confirm) => {
try { const { roleName, menuData, roleId, menuId, status } = confirmDialog
let resDeleteRole = await fetchApi(`/api/user_role/delete/${role.id}/true`, 'DELETE'); try {
console.log(resDeleteRole); if (confirm) {
await fetchData(); console.log(confirm, confirmDialog)
} catch (error) { if (status) {
console.log(error); let generateRoles = menuData.filter((el) => +el !== +menuId)
} console.log(generateRoles)
} let userMenu = await fetchApi(`d/user_role/update/${roleId}`, "PUT", {
name: roleName,
roles: generateRoles,
status: "Y",
})
console.log(userMenu)
await fetchData()
} else {
let generateRoles = menuData.filter((el) => +el !== +menuId)
generateRoles.push(`${menuId}`)
console.log(generateRoles)
let userMenu = await fetchApi(`d/user_role/update/${roleId}`, "PUT", {
name: roleName,
roles: generateRoles,
status: "Y",
})
console.log(userMenu)
await fetchData()
}
}
setConfirmDialog({ open: false, role: "", menu: "" })
} catch (error) {
console.log(error)
}
}
return ( const handleAddRole = async () => {
<Container> try {
<Typography variant="h4" align="center" gutterBottom marginTop={5}> await fetchApi("d/user_role/create", "POST", {
Role Menu Management name: newRole,
</Typography> roles: [],
<IconButton status: "Y",
style={{ position: 'absolute', top: 16, right: 16 }} })
color="primary" await fetchData()
onClick={() => setOpenDialog(true)} } catch (error) {
> console.log(error)
<AddIcon /> }
</IconButton> setNewRole("")
setOpenDialog(false)
}
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}> const deleteRole = async (role) => {
<Button variant="contained" color="primary" onClick={() => setOpenDialog(true)}>Create Role</Button> try {
</Box> let resDeleteRole = await fetchApi(`d/user_role/delete/${role.id}/true`, "DELETE")
console.log(resDeleteRole)
await fetchData()
} catch (error) {
console.log(error)
}
}
{/* Table for roles and menus */} return (
<TableContainer component={Paper} style={{ marginTop: '20px' }}> <Container>
<Table> <Typography variant="h4" align="center" gutterBottom marginTop={5}>
<TableHead> Role Menu Management
<TableRow> </Typography>
<TableCell><strong>Role</strong></TableCell> <IconButton style={{ position: "absolute", top: 16, right: 16 }} color="primary" onClick={() => setOpenDialog(true)}>
{menus.map((menu, idx) => ( <AddIcon />
<TableCell key={idx} align="center"><strong>{menu.name}</strong></TableCell> </IconButton>
))}
<TableCell><strong>Action</strong></TableCell>
</TableRow>
</TableHead>
<TableBody>
{roles.map((role) => (
<TableRow key={role.id}>
<TableCell>{role.name}</TableCell>
{menus.map((menu, idx) => (
<TableCell key={idx} align="center">
<Checkbox
checked={(role.roles.find(el => +el === menu.id)) ? true : false}
onChange={() => handleCheckboxChange(
role.name, role.roles, role.id, menu.id, (role.roles.find(el => +el === menu.id)) ? true : false, menu.name
)}
/>
</TableCell>
))}
<TableCell align="center">
<Button onClick={() => deleteRole(role)}>Delete</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{/* Dialog for adding new role */} <Box sx={{ display: "flex", justifyContent: "flex-end", alignItems: "center", pr: 2 }}>
<Dialog open={openDialog} onClose={() => setOpenDialog(false)}> <Button variant="contained" color="primary" onClick={() => setOpenDialog(true)}>
<DialogTitle>Add New Role</DialogTitle> Create Role
<DialogContent> </Button>
<TextField </Box>
autoFocus
margin="dense"
label="Role Name"
type="text"
fullWidth
value={newRole}
onChange={(e) => setNewRole(e.target.value)}
/>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)} color="secondary">
Cancel
</Button>
<Button onClick={handleAddRole} color="primary">
Add
</Button>
</DialogActions>
</Dialog>
{/* Confirmation Dialog for checkbox */} {/* Table for roles and menus */}
<Dialog open={confirmDialog.open} onClose={() => handleConfirm(false)}> <TableContainer component={Paper} style={{ marginTop: "20px" }}>
<DialogTitle>Confirm Menu Selection</DialogTitle> <Table>
<DialogContent> <TableHead>
Are you sure you want to <strong>{confirmDialog.status ? 'remove ' : 'add '}</strong> <TableRow>
the menu <strong>{confirmDialog.menuName}</strong> for role <strong>{confirmDialog.roleName}</strong>? <TableCell>
</DialogContent> <strong>Role</strong>
<DialogActions> </TableCell>
<Button onClick={() => handleConfirm(false)} color="secondary"> {menus.map((menu, idx) => (
Cancel <TableCell key={idx} align="center">
</Button> <strong>{menu.name}</strong>
<Button onClick={() => handleConfirm(true)} color="primary"> </TableCell>
Confirm ))}
</Button> <TableCell>
</DialogActions> <strong>Action</strong>
</Dialog> </TableCell>
</Container> </TableRow>
); </TableHead>
}; <TableBody>
{roles.map((role) => (
<TableRow key={role.id}>
<TableCell>{role.name}</TableCell>
{menus.map((menu, idx) => (
<TableCell key={idx} align="center">
<Checkbox checked={role.roles.find((el) => +el === menu.id) ? true : false} onChange={() => handleCheckboxChange(role.name, role.roles, role.id, menu.id, role.roles.find((el) => +el === menu.id) ? true : false, menu.name)} />
</TableCell>
))}
<TableCell align="center">
<Button onClick={() => deleteRole(role)}>Delete</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
export default RoleMenuTable; {/* Dialog for adding new role */}
<Dialog open={openDialog} onClose={() => setOpenDialog(false)}>
<DialogTitle>Add New Role</DialogTitle>
<DialogContent>
<TextField autoFocus margin="dense" label="Role Name" type="text" fullWidth value={newRole} onChange={(e) => setNewRole(e.target.value)} />
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)} color="secondary">
Cancel
</Button>
<Button onClick={handleAddRole} color="primary">
Add
</Button>
</DialogActions>
</Dialog>
{/* Confirmation Dialog for checkbox */}
<Dialog open={confirmDialog.open} onClose={() => handleConfirm(false)}>
<DialogTitle>Confirm Menu Selection</DialogTitle>
<DialogContent>
Are you sure you want to <strong>{confirmDialog.status ? "remove " : "add "}</strong>
the menu <strong>{confirmDialog.menuName}</strong> for role <strong>{confirmDialog.roleName}</strong>?
</DialogContent>
<DialogActions>
<Button onClick={() => handleConfirm(false)} color="secondary">
Cancel
</Button>
<Button onClick={() => handleConfirm(true)} color="primary">
Confirm
</Button>
</DialogActions>
</Dialog>
</Container>
)
}
export default RoleMenuTable

View File

@ -1,287 +1,247 @@
// Import React and Material-UI components // Import React and Material-UI components
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from "react"
import { import { Paper, Button, Dialog, DialogActions, DialogContent, DialogTitle, TableContainer, FormLabel, Checkbox, FormControlLabel, Box, Typography, TextField, Grid, MenuItem, InputLabel, Select, FormControl } from "@mui/material"
Paper, Button, Dialog, DialogActions, DialogContent, DialogTitle, TableContainer, FormLabel, import ReusableTable from "../components/Table"
Checkbox, FormControlLabel, Box, Typography, TextField, Grid, MenuItem, InputLabel, Select, FormControl import { fetchApi } from "../config/axios"
} from '@mui/material'; import WarningDialog from "../components/WarningDialog" // ERROR MSG
import ReusableTable from '../components/Table';
import { fetchApi } from '../config/axios';
import WarningDialog from '../components/WarningDialog'; // ERROR MSG
const columns = [ const columns = [
{ id: 'username', label: 'Username' }, { id: "username", label: "Username" },
{ id: 'name', label: 'Name' }, { id: "name", label: "Name" },
{ id: 'email', label: 'Email' }, { id: "email", label: "Email" },
{ id: 'role_name', label: 'Roles' }, { id: "role_name", label: "Roles" },
{ id: 'status', label: 'Status' }, { id: "status", label: "Status" },
{ id: 'created_at', label: 'Created' }, { id: "created_at", label: "Created" },
{ id: 'actions', label: 'Actions' }, { id: "actions", label: "Actions" },
]; ]
const initiateForm = { const initiateForm = {
username: '', username: "",
name: '', name: "",
email: '', email: "",
status: '', status: "",
id_role: '', id_role: "",
password: '', password: "",
confirmPassword: '', confirmPassword: "",
// nik: '', // nik: '',
// position: '', // position: '',
// telp: '', // telp: '',
// address: '', // address: '',
// organisasi: '', // organisasi: '',
// devisi: '', // devisi: '',
// unit: '', // unit: '',
} }
export default function UserManagement() { export default function UserManagement() {
const [users, setUsers] = useState([]); const [users, setUsers] = useState([])
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false)
const [selectedUser, setSelectedUser] = useState(null); const [selectedUser, setSelectedUser] = useState(null)
const [selectedRoles, setSelectedRoles] = useState([]); const [selectedRoles, setSelectedRoles] = useState([])
const [roles, setRoles] = useState([]); const [roles, setRoles] = useState([])
const [openDialog, setOpenDialog] = useState(false); const [openDialog, setOpenDialog] = useState(false)
const [labelDialog, setLabelDialog] = useState(''); const [labelDialog, setLabelDialog] = useState("")
const [formData, setFormData] = useState(initiateForm); const [formData, setFormData] = useState(initiateForm)
const [errors, setErrors] = useState({ passwordMatch: false, }); const [errors, setErrors] = useState({ passwordMatch: false })
const [isModalOpen, setIsModalOpen] = useState(false); // ERROR MSG const [isModalOpen, setIsModalOpen] = useState(false) // ERROR MSG
const [error, setError] = useState(""); // ERROR MSG const [error, setError] = useState("") // ERROR MSG
useEffect(() => { useEffect(() => {
fetchUserRoles() fetchUserRoles()
fetchUser() fetchUser()
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, [])
async function fetchUser(params) { async function fetchUser(params) {
try { try {
let fetchUsers = await fetchApi('/api/user/list', 'GET', null, { let fetchUsers = await fetchApi("d/user/list", "GET", null, {
limit: 5, limit: 5,
page: 1, page: 1,
with_deleted: true, with_deleted: true,
order_field: 'id', order_field: "id",
order_direction: 'ASC' order_direction: "ASC",
}); })
console.log(fetchUsers); console.log(fetchUsers)
if (fetchUsers.data && fetchUsers.data.data) { if (fetchUsers.data && fetchUsers.data.data) {
let resFetchUsers = fetchUsers.data.data.list let resFetchUsers = fetchUsers.data.data.list
let temp = resFetchUsers.map(el => { let temp = resFetchUsers.map((el) => {
if (el.status === 'Y') el.status = 'Aktif' if (el.status === "Y") el.status = "Aktif"
else el.status ='Tidak Aktif' else el.status = "Tidak Aktif"
el.actions = [ el.actions = [
{ label: 'Edit', color: 'info', onClick: (row) => handleOpen(row) }, { label: "Edit", color: "info", onClick: (row) => handleOpen(row) },
{ label: 'Delete', color: 'secondary', onClick: (row) => handleDelete(row) }, { label: "Delete", color: "secondary", onClick: (row) => handleDelete(row) },
] ]
return el return el
}) })
setUsers(temp) setUsers(temp)
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error)
handleError(`${error.message}. \n ${error.response.data.error}`) handleError(`${error.message}. \n ${error.response.data.error}`)
} }
} }
async function fetchUserRoles(params) { async function fetchUserRoles(params) {
try { try {
let userRoles = await fetchApi('/api/user_role/list', 'GET', null, { let userRoles = await fetchApi("d/user_role/list", "GET", null, {
limit: 5, limit: 5,
page: 1, page: 1,
with_deleted: true, with_deleted: true,
order_field: 'id', order_field: "id",
order_direction: 'ASC' order_direction: "ASC",
}); })
if (userRoles.data && userRoles.data.data) setRoles(userRoles.data.data.list) if (userRoles.data && userRoles.data.data) setRoles(userRoles.data.data.list)
} catch (error) { } catch (error) {
console.log(error); console.log(error)
handleError(`${error.message}. \n ${error.response.data.error}`) handleError(`${error.message}. \n ${error.response.data.error}`)
} }
} }
const handleOpen = (user) => { const handleOpen = (user) => {
setLabelDialog(`Edit User`) setLabelDialog(`Edit User`)
setFormData(user) setFormData(user)
setOpenDialog(true) setOpenDialog(true)
// setSelectedUser(user); // setSelectedUser(user);
// setSelectedRoles(user.role_name); // setSelectedRoles(user.role_name);
// setOpen(true); // setOpen(true);
}; }
const handleClose = () => { const handleClose = () => {
setOpen(false); setOpen(false)
setSelectedUser(null); setSelectedUser(null)
setSelectedRoles([]); setSelectedRoles([])
}; }
const handleRoleChange = (role) => { const handleRoleChange = (role) => {
setSelectedRoles((prevRoles) => setSelectedRoles((prevRoles) => (prevRoles.includes(role) ? prevRoles.filter((r) => r !== role) : [...prevRoles, role]))
prevRoles.includes(role) }
? prevRoles.filter((r) => r !== role)
: [...prevRoles, role]
);
};
const handleDelete = (row) => { const handleDelete = (row) => {
const newData = users.filter((item) => item.id !== row.id); const newData = users.filter((item) => item.id !== row.id)
setUsers(newData); setUsers(newData)
alert(`Deleted ${row.name}`); alert(`Deleted ${row.name}`)
}; }
const handleSave = () => { const handleSave = () => {
setUsers((prevUsers) => setUsers((prevUsers) => prevUsers.map((user) => (user.id === selectedUser.id ? { ...user, roles: selectedRoles } : user)))
prevUsers.map((user) => handleClose()
user.id === selectedUser.id ? { ...user, roles: selectedRoles } : user }
)
);
handleClose();
};
const handleChange = (e) => { const handleChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target
setFormData((prev) => ({ ...prev, [name]: value })); setFormData((prev) => ({ ...prev, [name]: value }))
if (name === 'confirmPassword' || name === 'password') { if (name === "confirmPassword" || name === "password") {
setErrors((prev) => ({ setErrors((prev) => ({
...prev, ...prev,
passwordMatch: name === 'confirmPassword' ? value !== formData.password : formData.confirmPassword !== value, passwordMatch: name === "confirmPassword" ? value !== formData.password : formData.confirmPassword !== value,
})); }))
} }
}; }
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
if (!errors.passwordMatch) { if (!errors.passwordMatch) {
console.log('Form Data:', formData); console.log("Form Data:", formData)
// setOpen(false); // setOpen(false);
// setFormData(initiateForm); // setFormData(initiateForm);
} }
console.log(formData); console.log(formData)
formData.status = "Y"; formData.status = "Y"
if (labelDialog === `Create User`) { if (labelDialog === `Create User`) {
delete formData.confirmPassword delete formData.confirmPassword
let createUser = await fetchApi('/api/user/create', 'POST', formData); let createUser = await fetchApi("d/user/create", "POST", formData)
console.log(createUser); console.log(createUser)
} else if (labelDialog === `Edit User`) { } else if (labelDialog === `Edit User`) {
delete formData.created_at delete formData.created_at
delete formData.updated_at delete formData.updated_at
delete formData.role_name delete formData.role_name
delete formData.actions delete formData.actions
delete formData.confirmPassword delete formData.confirmPassword
console.log(formData); console.log(formData)
let editUser = await fetchApi(`/api/user/update/${formData.id}`, 'PUT', formData); let editUser = await fetchApi(`d/user/update/${formData.id}`, "PUT", formData)
console.log('editUser', editUser); console.log("editUser", editUser)
} }
await fetchUser() await fetchUser()
setOpenDialog(false) setOpenDialog(false)
} catch (error) { } catch (error) {
console.log(error); console.log(error)
handleError(`${error.message}. \n ${error.response.data.error}`) handleError(`${error.message}. \n ${error.response.data.error}`)
} }
} }
const createNewUserBtn = () => { const createNewUserBtn = () => {
setLabelDialog(`Create User`); setLabelDialog(`Create User`)
setFormData(initiateForm); setFormData(initiateForm)
setOpenDialog(true); setOpenDialog(true)
} }
const handleError = (msg) => { // ERROR MSG const handleError = (msg) => {
setError(msg); // ERROR MSG
setIsModalOpen(true); setError(msg)
}; setIsModalOpen(true)
}
const closeModal = () => { // ERROR MSG
setIsModalOpen(false);
setError("");
};
return ( const closeModal = () => {
<Box sx={{ padding: 3 }}> // ERROR MSG
<WarningDialog // ERROR MSG setIsModalOpen(false)
open={isModalOpen} setError("")
onClose={closeModal} }
errorMessage={error}
/>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>User Management</Typography>
</Box>
<Box p={3}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary" onClick={() => createNewUserBtn()}>Create New User</Button>
</Box>
<TableContainer component={Paper} sx={{ marginTop: 3 }}>
<ReusableTable columns={columns} data={users} />
<Dialog open={open} onClose={handleClose}> return (
<DialogTitle>Add Roles to {selectedUser?.name}</DialogTitle> <Box sx={{ padding: 3 }}>
<DialogContent> <WarningDialog // ERROR MSG
{roles.map((role) => ( open={isModalOpen}
<FormControlLabel onClose={closeModal}
key={role.id} errorMessage={error}
control={ />
<Checkbox <Box sx={{ display: "flex", justifyContent: "flex-start", pr: 2 }}>
checked={selectedRoles.includes(role.name)} <Typography sx={{ color: "gray", fontSize: "30px" }}>User Management</Typography>
onChange={() => handleRoleChange(role.name)} </Box>
/> <Box p={3}>
} <Box sx={{ display: "flex", justifyContent: "flex-end", alignItems: "center", pr: 2 }}>
label={role.name} <Button variant="contained" color="primary" onClick={() => createNewUserBtn()}>
/> Create New User
))} </Button>
</DialogContent> </Box>
<DialogActions> <TableContainer component={Paper} sx={{ marginTop: 3 }}>
<Button onClick={handleClose} color="secondary"> <ReusableTable columns={columns} data={users} />
Cancel
</Button>
<Button onClick={handleSave} color="primary" variant="contained">
Save
</Button>
</DialogActions>
</Dialog>
</TableContainer>
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} maxWidth="sm" fullWidth> <Dialog open={open} onClose={handleClose}>
<DialogTitle>{labelDialog}</DialogTitle> <DialogTitle>Add Roles to {selectedUser?.name}</DialogTitle>
<DialogContent sx={{ marginTop: 2 }}> <DialogContent>
<Grid container spacing={2}> {roles.map((role) => (
<Grid item xs={12}> <FormControlLabel key={role.id} control={<Checkbox checked={selectedRoles.includes(role.name)} onChange={() => handleRoleChange(role.name)} />} label={role.name} />
<TextField ))}
sx={{ marginTop: 2 }} </DialogContent>
label="Username" <DialogActions>
name="username" <Button onClick={handleClose} color="secondary">
value={formData.username} Cancel
onChange={handleChange} </Button>
fullWidth <Button onClick={handleSave} color="primary" variant="contained">
required Save
/> </Button>
</Grid> </DialogActions>
<Grid item xs={12}> </Dialog>
<TextField </TableContainer>
sx={{ marginTop: 2 }}
label="Name" <Dialog open={openDialog} onClose={() => setOpenDialog(false)} maxWidth="sm" fullWidth>
name="name" <DialogTitle>{labelDialog}</DialogTitle>
value={formData.name} <DialogContent sx={{ marginTop: 2 }}>
onChange={handleChange} <Grid container spacing={2}>
fullWidth <Grid item xs={12}>
required <TextField sx={{ marginTop: 2 }} label="Username" name="username" value={formData.username} onChange={handleChange} fullWidth required />
/> </Grid>
</Grid> <Grid item xs={12}>
<Grid item xs={12}> <TextField sx={{ marginTop: 2 }} label="Name" name="name" value={formData.name} onChange={handleChange} fullWidth required />
<TextField </Grid>
label="Email" <Grid item xs={12}>
name="email" <TextField label="Email" name="email" value={formData.email} onChange={handleChange} fullWidth type="email" required />
value={formData.email} </Grid>
onChange={handleChange} <Grid item xs={12}>
fullWidth <FormLabel component="legend">Status</FormLabel>
type="email" <FormControlLabel control={<Checkbox name="status" defaultChecked onChange={handleChange} value={formData.status === "Y" ? true : false} />} label="Aktif" />
required </Grid>
/> {/* <Grid item xs={12}>
</Grid>
<Grid item xs={12}>
<FormLabel component="legend">Status</FormLabel>
<FormControlLabel control={<Checkbox name='status' defaultChecked onChange={handleChange} value={formData.status === 'Y' ? true : false}/>} label="Aktif" />
</Grid>
{/* <Grid item xs={12}>
<TextField <TextField
sx={{ marginTop: 2 }} sx={{ marginTop: 2 }}
label="Nik" label="Nik"
@ -377,68 +337,36 @@ export default function UserManagement() {
</Select> </Select>
</FormControl> </FormControl>
</Grid> */} </Grid> */}
<Grid item xs={12}> <Grid item xs={12}>
<FormControl fullWidth required> <FormControl fullWidth required>
<InputLabel id="organization-label">Role</InputLabel> <InputLabel id="organization-label">Role</InputLabel>
<Select <Select labelId="organization-label" id="organization" value={formData.id_role} label="Role" onChange={handleChange} name="id_role">
labelId="organization-label" {roles.map((el, idx) => (
id="organization" <MenuItem key={idx} value={el.id}>
value={formData.id_role} {el.name}
label="Role" </MenuItem>
onChange={handleChange} ))}
name='id_role' </Select>
> </FormControl>
{ </Grid>
roles.map((el, idx) => ( <Grid item xs={12}>
<MenuItem key={idx} value={el.id}>{el.name}</MenuItem> <TextField label="Password" name="password" value={formData.password} onChange={handleChange} fullWidth type="password" required />
)) </Grid>
} <Grid item xs={12}>
</Select> <TextField label="Confirm Password" name="confirmPassword" value={formData.confirmPassword} onChange={handleChange} fullWidth type="password" error={errors.passwordMatch} helperText={errors.passwordMatch ? "Passwords do not match" : ""} required />
</FormControl> </Grid>
</Grid> </Grid>
<Grid item xs={12}> </DialogContent>
<TextField <DialogActions>
label="Password" <Button onClick={() => setOpenDialog(false)} color="secondary">
name="password" Cancel
value={formData.password} </Button>
onChange={handleChange} <Button onClick={handleSubmit} color="primary" disabled={!formData.name || !formData.email || !formData.password || errors.passwordMatch || !formData.id_role || !formData.status || !formData.username}>
fullWidth Submit
type="password" </Button>
required </DialogActions>
/> </Dialog>
</Grid> </Box>
<Grid item xs={12}> </Box>
<TextField )
label="Confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
fullWidth
type="password"
error={errors.passwordMatch}
helperText={errors.passwordMatch ? "Passwords do not match" : ""}
required
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)} color="secondary">
Cancel
</Button>
<Button
onClick={handleSubmit}
color="primary"
disabled={!formData.name || !formData.email || !formData.password || errors.passwordMatch || !formData.id_role
|| !formData.status || !formData.username
}
>
Submit
</Button>
</DialogActions>
</Dialog>
</Box>
</Box>
);
} }

View File

@ -1,134 +1,384 @@
import React, { useEffect } from 'react'; import React, { useEffect } from "react"
import { Routes, Route, useLocation, Navigate } from 'react-router-dom'; import { Routes, Route, useLocation, Navigate } from "react-router-dom"
import "../pages/Dashboard.css"; import "../pages/Dashboard.css"
import Sidebar from "../components/SideBar"; import Sidebar from "../components/SideBar"
import Header from "../components/Header"; import Header from "../components/Header"
import { Box, Toolbar } from "@mui/material"; import { Box, Toolbar } from "@mui/material"
import Cookies from "js-cookie"; import Cookies from "js-cookie"
// GENERAL // GENERAL
import Dasboard from '../pages/Dashboard'; import Dasboard from "../pages/Dashboard"
import LoginPage from '../pages/Login'; import LoginPage from "../pages/Login"
import RegisterPage from '../pages/Register'; import RegisterPage from "../pages/Register"
import ProfilePage from '../pages/Profile'; import ProfilePage from "../pages/Profile"
// ADMIN // ADMIN
import ManageTransfers from '../pages/ManageTransfers'; import ManageTransfers from "../pages/ManageTransfers"
import ManageNotifications from '../pages/ManageNotifications'; import ManageNotifications from "../pages/ManageNotifications"
import ManageAccess from '../pages/ManageAccess'; import ManageAccess from "../pages/ManageAccess"
import ManageAccounts from '../pages/ManageAccount'; import ManageAccounts from "../pages/ManageAccount"
import ManageGroups from '../pages/ManageGroups'; import ManageGroups from "../pages/ManageGroups"
import ManageMembers from '../pages/ManageMembers'; import ManageMembers from "../pages/ManageMembers"
import ManageMenus from '../pages/ManageMenu'; import ManageMenus from "../pages/ManageMenu"
import MemberKyc from '../pages/MemberKYC'; import MemberKyc from "../pages/MemberKYC"
import ManageCredential from '../pages/ManageCredential'; import ManageCredential from "../pages/ManageCredential"
import ManageCurrency from '../pages/ManageCurrency'; import ManageCurrency from "../pages/ManageCurrency"
import ManageWebservice from '../pages/ManageWebservice'; import ManageWebservice from "../pages/ManageWebservice"
import SettingPage from '../pages/Setting'; import SettingPage from "../pages/Setting"
import UserManagement from '../pages/UserManagement'; import UserManagement from "../pages/UserManagement"
import RoleMenus from '../pages/RoleManagement'; import RoleMenus from "../pages/RoleManagement"
import MasterDataPage from '../pages/MasterData'; import MasterDataPage from "../pages/MasterData"
// ESCROW // ESCROW
import TransactionHistory from '../escrowPages/TransactionHistory'; import TransactionHistory from "../escrowPages/TransactionHistory"
import TransferPage from '../escrowPages/Transfer'; import TransferPage from "../escrowPages/Transfer"
import TicketConfirmationPage from '../escrowPages/TicketConfirmation'; import TicketConfirmationPage from "../escrowPages/TicketConfirmation"
// TDS // TDS
import AgentBalance from '../tdsPages/AgentBalance'; import AgentBalance from "../tdsPages/AgentBalance"
import DepositReport from '../tdsPages/DepostiReport'; import DepositReport from "../tdsPages/DepostiReport"
import TopUp from '../tdsPages/TopUp'; import TopUp from "../tdsPages/TopUp"
import TopUpApproval from '../tdsPages/TopUpApproval'; import TopUpApproval from "../tdsPages/TopUpApproval"
import TopUpRequest from '../tdsPages/TopUpRequest'; import TopUpRequest from "../tdsPages/TopUpRequest"
import OperationTransfer from '../tdsPages/Transfer'; import OperationTransfer from "../tdsPages/Transfer"
import RegisteredAgent from '../tdsPages/RegisteredAgent'; import RegisteredAgent from "../tdsPages/RegisteredAgent"
import RegisteredSupervisor from '../tdsPages/RegisteredSupervisor'; import RegisteredSupervisor from "../tdsPages/RegisteredSupervisor"
// Mock Authentication Function // Mock Authentication Function
const isAuthenticated = () => { const isAuthenticated = () => {
let token = Cookies.get(`token`); let token = Cookies.get(`token`)
let role = Cookies.get(`role`); let role = Cookies.get(`role`)
if (token && role) return true if (token && role) return true
return false return false
}; }
// Middleware Component for Protected Routes // Middleware Component for Protected Routes
const ProtectedRoute = ({ children }) => { const ProtectedRoute = ({ children }) => {
if (!isAuthenticated()) { if (!isAuthenticated()) {
return <Navigate to="/login" replace />; return <Navigate to="/login" replace />
} }
return children; 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() {
let roles_list = JSON.parse(localStorage.getItem('roles_list'));
const location = useLocation();
useEffect(() => {
console.log(roles_list, location);
}, [roles_list, location]);
return (
<Routes>
{/* GENERAL */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route exact path="/" element={<ProtectedRoute><Layout><Dasboard /></Layout></ProtectedRoute>} />
{/* GENERAL AFTER LOGIN */}
<Route path="/profile" element={<ProtectedRoute><Layout><ProfilePage /></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>} />
<Route path="/user-management" element={<ProtectedRoute><Layout><UserManagement /></Layout></ProtectedRoute>} />
<Route path="/role-management" element={<ProtectedRoute><Layout><RoleMenus /></Layout></ProtectedRoute>} />
<Route path="/master-data" element={<ProtectedRoute><Layout><MasterDataPage /></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>} />
{/* TDS */}
<Route path="/agent-balance" element={<ProtectedRoute><Layout><AgentBalance /></Layout></ProtectedRoute>} />
<Route path="/deposit-report" element={<ProtectedRoute><Layout><DepositReport /></Layout></ProtectedRoute>} />
<Route path="/topup" element={<ProtectedRoute><Layout><TopUp /></Layout></ProtectedRoute>} />
<Route path="/topup-approval" element={<ProtectedRoute><Layout><TopUpApproval /></Layout></ProtectedRoute>} />
<Route path="/topup-request" element={<ProtectedRoute><Layout><TopUpRequest /></Layout></ProtectedRoute>} />
<Route path="/operation-transfer" element={<ProtectedRoute><Layout><OperationTransfer /></Layout></ProtectedRoute>} />
<Route path="/registered-agent" element={<ProtectedRoute><Layout><RegisteredAgent /></Layout></ProtectedRoute>} />
<Route path="/registered-supervisor" element={<ProtectedRoute><Layout><RegisteredSupervisor /></Layout></ProtectedRoute>} />
</Routes>
);
} }
export default App; 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() {
let roles_list = JSON.parse(localStorage.getItem("roles_list"))
const location = useLocation()
useEffect(() => {
console.log(roles_list, location)
}, [roles_list, location])
return (
<Routes>
{/* GENERAL */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route
exact
path="/"
element={
<ProtectedRoute>
<Layout>
<Dasboard />
</Layout>
</ProtectedRoute>
}
/>
{/* GENERAL AFTER LOGIN */}
<Route
path="/profile"
element={
<ProtectedRoute>
<Layout>
<ProfilePage />
</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>
}
/>
<Route
path="/user-management"
element={
<ProtectedRoute>
<Layout>
<UserManagement />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/role-management"
element={
<ProtectedRoute>
<Layout>
<RoleMenus />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/master-data"
element={
<ProtectedRoute>
<Layout>
<MasterDataPage />
</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>
}
/>
{/* TDS */}
<Route
path="/agent-balance"
element={
<ProtectedRoute>
<Layout>
<AgentBalance />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/deposit-report"
element={
<ProtectedRoute>
<Layout>
<DepositReport />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/topup"
element={
<ProtectedRoute>
<Layout>
<TopUp />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/topup-approval"
element={
<ProtectedRoute>
<Layout>
<TopUpApproval />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/topup-request"
element={
<ProtectedRoute>
<Layout>
<TopUpRequest />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/operation-transfer"
element={
<ProtectedRoute>
<Layout>
<OperationTransfer />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/registered-agent"
element={
<ProtectedRoute>
<Layout>
<RegisteredAgent />
</Layout>
</ProtectedRoute>
}
/>
<Route
path="/registered-supervisor"
element={
<ProtectedRoute>
<Layout>
<RegisteredSupervisor />
</Layout>
</ProtectedRoute>
}
/>
</Routes>
)
}
export default App