diff --git a/package-lock.json b/package-lock.json index 8b161f3..a2de86d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.2.1", "@mui/material": "^6.2.1", + "@reduxjs/toolkit": "^2.5.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/user-event": "^13.5.0", "ajv": "^8.17.1", @@ -23,8 +24,10 @@ "react-chartjs-2": "^5.2.0", "react-circular-progressbar": "^2.1.0", "react-dom": "^18.3.1", + "react-redux": "^9.2.0", "react-router-dom": "^7.1.1", "react-scripts": "5.0.1", + "redux": "^5.0.1", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -3370,6 +3373,38 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.5.0.tgz", + "integrity": "sha512-awNe2oTodsZ6LmRqmkFhtb/KH03hUhxOamEQy411m3Njj3BbFvoBovxo4Q1cBWnV1ErprVj9MlF0UPXkng0eyg==", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4309,6 +4344,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" + }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -13665,6 +13705,28 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -13861,6 +13923,19 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", @@ -14017,6 +14092,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -16070,6 +16150,14 @@ "requires-port": "^1.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 3d22a2a..216e2da 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.2.1", "@mui/material": "^6.2.1", + "@reduxjs/toolkit": "^2.5.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/user-event": "^13.5.0", "ajv": "^8.17.1", @@ -18,8 +19,10 @@ "react-chartjs-2": "^5.2.0", "react-circular-progressbar": "^2.1.0", "react-dom": "^18.3.1", + "react-redux": "^9.2.0", "react-router-dom": "^7.1.1", "react-scripts": "5.0.1", + "redux": "^5.0.1", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/public/index.html b/public/index.html index a82a2e7..ae4285e 100644 --- a/public/index.html +++ b/public/index.html @@ -2,14 +2,14 @@ - + - + - T-Pay Dashboard + T-Pay| Dashboard diff --git a/public/logo.jpeg b/public/logo.jpeg new file mode 100644 index 0000000..5f2edf3 Binary files /dev/null and b/public/logo.jpeg differ diff --git a/src/components/Header.js b/src/components/Header.js index 1d1ea4d..1928297 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -34,7 +34,9 @@ const Header = () => { function logoutBtn() { Cookies.remove('token'); Cookies.remove('role'); + Cookies.remove('userId'); Cookies.remove('username'); + localStorage.removeItem('roles_list'); navigate('/login') } @@ -77,7 +79,7 @@ const Header = () => { 'aria-labelledby': 'basic-button', }} > - + navigate('/profile')}> Profile diff --git a/src/components/SideBar.js b/src/components/SideBar.js index 5c1d320..ed74bf3 100644 --- a/src/components/SideBar.js +++ b/src/components/SideBar.js @@ -131,10 +131,6 @@ const Sidebar = () => { { title: 'Setting', options: [ - { - title: 'Setting', - path: '/setting' - }, { title: 'User Management', path: '/user-management' @@ -142,7 +138,19 @@ const Sidebar = () => { { title: 'Role Management', path: '/role-management' - } + }, + { + title: 'Profile', + path: '/profile' + }, + { + title: 'Setting', + path: '/setting' + }, + { + title: 'Master Data', + path: '/master-data' + }, ], }, ]; @@ -275,7 +283,9 @@ const Sidebar = () => { function logoutBtn() { Cookies.remove('token'); Cookies.remove('role'); + Cookies.remove('userId'); Cookies.remove('username'); + localStorage.removeItem('roles_list'); navigate('/login'); } diff --git a/src/components/WarningDialog.js b/src/components/WarningDialog.js new file mode 100644 index 0000000..eb80a0e --- /dev/null +++ b/src/components/WarningDialog.js @@ -0,0 +1,46 @@ +// ErrorModal.js +import React from "react"; +import { Modal, Box, Typography, Button } from "@mui/material"; + +const ErrorModal = ({ open, onClose, errorMessage }) => { + const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 400, + bgcolor: "background.paper", + border: "2px solid #000", + boxShadow: 24, + p: 4, + borderRadius: 2, + }; + + return ( + + + + Error + + + {errorMessage} + + + + + ); +}; + +export default ErrorModal; diff --git a/src/config/axios.js b/src/config/axios.js index 38553d5..677fa0f 100644 --- a/src/config/axios.js +++ b/src/config/axios.js @@ -1,18 +1,26 @@ import axios from 'axios'; +import Cookies from "js-cookie"; + +const token = Cookies.get(`token`) || null; +const headers = { + "Access-Control-Allow-Origin": "*", + "content-type":"application/json", +}; +if (token) headers["Authorization"] = `Bearer ${token}`; const instance = axios.create({ baseURL: 'https://api.telkomcel.tl/tpay-stg-dash-api/', - headers: { - "Access-Control-Allow-Origin": "*", - "content-type":"application/json", - }, + headers: headers }) -export async function fetchApi(path, method, data) { +export async function fetchApi(path, method, data, params) { + let query = params || {}; + query.token = token let response = await instance({ method: method, url: path, - data: data + data: data, + params: query }); return response } \ No newline at end of file diff --git a/src/index.js b/src/index.js index 0f58506..7d78253 100644 --- a/src/index.js +++ b/src/index.js @@ -4,14 +4,18 @@ import "./index.css"; import App from "./routes/routes"; import reportWebVitals from "./reportWebVitals"; import { BrowserRouter } from "react-router-dom"; +import { Provider } from 'react-redux'; +import store from './store/store'; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - - - - - + + + + + + + ); // If you want to start measuring performance in your app, pass a function diff --git a/src/pages/Login.js b/src/pages/Login.js index e9eb9af..3408aa0 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -1,8 +1,9 @@ import React, { useState } from "react"; -import { TextField, Button, Box, Typography, Grid, Paper } from "@mui/material"; +import { TextField, Button, Box, Typography, Grid, Paper, Avatar, Divider } from "@mui/material"; import {Link, useNavigate } from 'react-router-dom'; import Cookies from "js-cookie"; import { fetchApi } from '../config/axios'; +import logo from '../logo/logo.jpeg'; const LoginPage = () => { // State for email and password @@ -18,17 +19,24 @@ const LoginPage = () => { // GET CREDIENTIAL let user = await fetchApi('/api/login', 'POST', { username, password }); if (user.data && user.data.data) { - let userLogin = user.data.data; - Cookies.set('token', userLogin.token.access_token, { expires: 7, path: '/' }); - Cookies.set('role', userLogin.role_name); - Cookies.set('username', userLogin.user.username); - // localStorage.setItem('token', userLogin.token.access_token) + let resUserLogin = user.data.data; + console.log('resUserLogin', resUserLogin); + let roleList = JSON.stringify(resUserLogin.roles_list); + Cookies.set('token', resUserLogin.token.access_token, { expires: 1, path: '/' }); + Cookies.set('role', resUserLogin.role_name, { expires: 1, path: '/' }); + Cookies.set('userId', resUserLogin.user.id, { expires: 1, path: '/' }); + Cookies.set('username', resUserLogin.user.username, { expires: 1, path: '/' }); + // Cookies.set('roles_list', roleList, { expires: 1, path: '/' }); + localStorage.setItem('roles_list', roleList) + navigate('/'); + } else { + alert(user.response.data.message); } - navigate('/'); } else { alert("Please fill in both fields."); } } catch (error) { + alert(error.response.data.message); console.log(error); } }; @@ -84,6 +92,39 @@ const LoginPage = () => { + + {/* Divider (Horizontal Line) */} + + + {/* Content */} + + + T-PAY + + + © 2025 TelinDigital Solution + + ); }; diff --git a/src/pages/MasterData.js b/src/pages/MasterData.js new file mode 100644 index 0000000..f5f31e2 --- /dev/null +++ b/src/pages/MasterData.js @@ -0,0 +1,133 @@ +import React, { useState } from "react"; +import { Grid, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Box, Typography } from '@mui/material'; +import ReusableTable from '../components/Table'; + +const MasterDataPage = () => { + const tableData1 = [ + { id: 1, name: 'John Doe', age: 25 }, + { id: 2, name: 'Jane Smith', age: 30 }, + { id: 3, name: 'John Doe', age: 25 }, + { id: 4, name: 'Jane Smith', age: 30 }, + { id: 5, name: 'John Doe', age: 25 }, + ]; + + const tableData2 = [ + { id: 1, product: 'Laptop', price: '$1000' }, + { id: 2, product: 'Phone', price: '$600' }, + ]; + + return ( + + + Master Data + + + + {/* First Table */} + + {/* */} + + + Kecamatan + + + + + ID + Name + Age + + + + {tableData1.map((row) => ( + + {row.id} + {row.name} + {row.age} + + ))} + +
+
+
+ + {/* Second Table */} + + Kelurahan + + + + + ID + Product + Price + + + + {tableData2.map((row) => ( + + {row.id} + {row.product} + {row.price} + + ))} + +
+
+
+ {/* 3rd Table */} + + Kabupaten + + + + + ID + Name + Age + + + + {tableData1.map((row) => ( + + {row.id} + {row.name} + {row.age} + + ))} + +
+
+
+ + {/* 4th Table */} + + Kota + + + + + ID + Product + Price + + + + {tableData2.map((row) => ( + + {row.id} + {row.product} + {row.price} + + ))} + +
+
+
+
+
+
+ ); +}; + +export default MasterDataPage; \ No newline at end of file diff --git a/src/pages/Profile.js b/src/pages/Profile.js new file mode 100644 index 0000000..a924733 --- /dev/null +++ b/src/pages/Profile.js @@ -0,0 +1,362 @@ +import React, { useState, useEffect } from 'react'; +import { + TextField, + Button, + Box, + 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 = () => { + // State for form fields + const [formData, setFormData] = useState({ + username: '', + name: '', + email: '', + status: '', + idRole: '', + password: '', + oldPassword: '', + confirmPassword: '', + newPassword: '' + // nik: '', + // position: '', + // telp: '', + // address: '', + // organisasi: '', + // devisi: '', + // unit: '', + }); + const [roles, setRoles] = useState([]); + const [isModalOpen, setIsModalOpen] = useState(false); // ERROR MSG + const [error, setError] = useState(""); // ERROR MSG + + useEffect(() => { + fetchUser() + fetchUserRoles() + // eslint-disable-next-line + }, []); + + async function fetchUser(params) { + try { + let userId = Cookies.get(`userId`); + 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) { + try { + let userRoles = await fetchApi('/api/user_role/list', 'GET', null, { + limit: 10, + page: 1, + with_deleted: true, + order_field: 'id', + 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 + 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."); + // } + }; + + const handleChange = (e) => { + let { name, value } = e.target; + if (name === 'status' && value === "Y") value = "N" + else if (name === 'status' && value === "N") value = "Y" + setFormData((prev) => ({ ...prev, [name]: value })); + }; + + const handleError = (msg) => { // ERROR MSG + setError(msg); + setIsModalOpen(true); + }; + + const closeModal = () => { // ERROR MSG + setIsModalOpen(false); + setError(""); + }; + + 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 ( + + + + User Profile + + + + +
+ + + + + + + + + + + Status : + + }/> + + + {/* + + + + + + + + + + + + + + Organization + + + + + + Devision + + + + + + Unit + + + */} + + + Role + + + + + + + + + + + +
+
+
+
+ + + + User Password + + + + + + + + + + + + + + + + + + +
+ ); +}; + +export default ProfilePage; \ No newline at end of file diff --git a/src/pages/RoleManagement.js b/src/pages/RoleManagement.js index 7b9e49e..7d98ef4 100644 --- a/src/pages/RoleManagement.js +++ b/src/pages/RoleManagement.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { Container, Typography, @@ -20,58 +20,127 @@ import { Box } from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; +import { fetchApi } from '../config/axios'; // Initial list of roles and menus -const initialRoles = ['Admin', 'Escrow', 'Agent']; -const menus = [ - 'Dashboard', - 'Users', - 'Reports', - 'Settings', - 'Notifications', - 'Profile', - 'Help', - 'Logs', - 'Analytics', - 'Billing', -]; +// const initialRoles = ['Admin', 'Escrow', 'Agent']; +// const menus = [ +// 'Dashboard', +// 'Users', +// 'Reports', +// 'Settings', +// 'Notifications', +// 'Profile', +// 'Help', +// 'Logs', +// 'Analytics', +// 'Billing', +// ]; const RoleMenuTable = () => { - const [roles, setRoles] = useState(initialRoles); - const [roleMenus, setRoleMenus] = useState( - initialRoles.reduce((acc, role) => ({ ...acc, [role]: [] }), {}) - ); + const [roles, setRoles] = useState([]); + // const [roleMenus, setRoleMenus] = useState([]); + const [menus, setMenus] = useState([]); const [openDialog, setOpenDialog] = useState(false); const [newRole, setNewRole] = useState(''); - const [confirmDialog, setConfirmDialog] = useState({ open: false, role: '', menu: '' }); + const [confirmDialog, setConfirmDialog] = useState({ + open: false, roleName: '', menuData: [], roleId: '', menuId: '', status: null, menuName: '' + }); + + useEffect(() => { + fetchData() + // eslint-disable-next-line + }, []); - const handleCheckboxChange = (role, menu) => { - setConfirmDialog({ open: true, role, menu }); - }; - - const handleConfirm = (confirm) => { - const { role, menu } = confirmDialog; - if (confirm) { - setRoleMenus((prev) => { - const isChecked = prev[role].includes(menu); - const updatedMenus = isChecked - ? prev[role].filter((m) => m !== menu) - : [...prev[role], menu]; - return { ...prev, [role]: updatedMenus }; + async function fetchData(params) { + try { + let userRole = await fetchApi('/api/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) + + console.log('role',userRole); + console.log('menu',userMenu); + if (userRole.data && userRole.data.data) setRoles(userRole.data.data.list) + } catch (error) { + console.log(error); } - setConfirmDialog({ open: false, role: '', menu: '' }); + } + + const handleCheckboxChange = (roleName, menuData, roleId, menuId, status, menuName) => { + setConfirmDialog({ open: true, roleName, menuData, roleId, menuId, status, menuName }); }; - const handleAddRole = () => { - if (newRole.trim() && !roles.includes(newRole)) { - setRoles((prevRoles) => [...prevRoles, newRole]); - setRoleMenus((prevMenus) => ({ ...prevMenus, [newRole]: [] })); + const handleConfirm = async (confirm) => { + const { roleName, menuData, roleId, menuId, status } = confirmDialog; + try { + if (confirm) { + console.log(confirm,confirmDialog); + 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 () => { + try { + 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) => { + try { + let resDeleteRole = await fetchApi(`/api/user_role/delete/${role.id}/true`, 'DELETE'); + console.log(resDeleteRole); + await fetchData(); + } catch (error) { + console.log(error); + } + } + return ( @@ -85,9 +154,9 @@ const RoleMenuTable = () => { - - - + + + {/* Table for roles and menus */} @@ -95,26 +164,28 @@ const RoleMenuTable = () => { Role - {menus.map((menu) => ( - {menu} + {menus.map((menu, idx) => ( + {menu.name} ))} Action {roles.map((role) => ( - - {role} - {menus.map((menu) => ( - + + {role.name} + {menus.map((menu, idx) => ( + handleCheckboxChange(role, menu)} + 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 + )} /> ))} - + ))} @@ -150,8 +221,8 @@ const RoleMenuTable = () => { handleConfirm(false)}> Confirm Menu Selection - Are you sure you want to {roleMenus[confirmDialog.role]?.includes(confirmDialog.menu) ? 'remove' : 'add'} - the menu {confirmDialog.menu} for role {confirmDialog.role}? + Are you sure you want to {confirmDialog.status ? 'remove ' : 'add '} + the menu {confirmDialog.menuName} for role {confirmDialog.roleName}? + @@ -133,16 +216,16 @@ export default function UserManagement() { Add Roles to {selectedUser?.name} - {availableRoles.map((role) => ( + {roles.map((role) => ( handleRoleChange(role)} + checked={selectedRoles.includes(role.name)} + onChange={() => handleRoleChange(role.name)} /> } - label={role} + label={role.name} /> ))} @@ -158,9 +241,20 @@ export default function UserManagement() { setOpenDialog(false)} maxWidth="sm" fullWidth> - Create User + {labelDialog} + + + + + Status + } label="Aktif" /> + + {/* + + + + + + + + Organization + + + + + + Devision + + + + + + Unit + + + */} + + + Role + + + Submit diff --git a/src/routes/routes.js b/src/routes/routes.js index cfe80f0..3cdb5c5 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -1,13 +1,15 @@ -import React from 'react'; +import React, { useEffect } 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"; +import Cookies from "js-cookie"; // GENERAL import Dasboard from '../pages/Dashboard'; import LoginPage from '../pages/Login'; import RegisterPage from '../pages/Register'; +import ProfilePage from '../pages/Profile'; // ADMIN import ManageTransfers from '../pages/ManageTransfers'; import ManageNotifications from '../pages/ManageNotifications'; @@ -23,6 +25,7 @@ import ManageWebservice from '../pages/ManageWebservice'; import SettingPage from '../pages/Setting'; import UserManagement from '../pages/UserManagement'; import RoleMenus from '../pages/RoleManagement'; +import MasterDataPage from '../pages/MasterData'; // ESCROW import TransactionHistory from '../escrowPages/TransactionHistory'; import TransferPage from '../escrowPages/Transfer'; @@ -36,7 +39,6 @@ import TopUpRequest from '../tdsPages/TopUpRequest'; import OperationTransfer from '../tdsPages/Transfer'; import RegisteredAgent from '../tdsPages/RegisteredAgent'; import RegisteredSupervisor from '../tdsPages/RegisteredSupervisor'; -import Cookies from "js-cookie"; // Mock Authentication Function const isAuthenticated = () => { @@ -80,12 +82,23 @@ const Layout = ({ children }) => { }; function App() { + let roles_list = JSON.parse(localStorage.getItem('roles_list')); + const location = useLocation(); + + useEffect(() => { + console.log(roles_list); + console.log(location); + + }, [roles_list, location]); + return ( {/* GENERAL */} } /> } /> } /> + {/* GENERAL AFTER LOGIN */} + } /> {/* ADMIN */} } /> } /> @@ -101,6 +114,7 @@ function App() { } /> } /> } /> + } /> {/* ESCROW */} } /> } /> diff --git a/src/store/store.js b/src/store/store.js new file mode 100644 index 0000000..ac85160 --- /dev/null +++ b/src/store/store.js @@ -0,0 +1,9 @@ +import { configureStore } from '@reduxjs/toolkit'; + +export default configureStore({ + reducer: { + users: () => { + return {} + } + }, +}) \ No newline at end of file