usermanagement, role, etc

This commit is contained in:
unknown
2025-01-27 18:45:14 +07:00
parent 7772062831
commit dbcd5a736a
17 changed files with 1121 additions and 134 deletions

View File

@ -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 = () => {
</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>
);
};

133
src/pages/MasterData.js Normal file
View File

@ -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 (
<Box p={3}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Master Data</Typography>
</Box>
<Box p={3}>
<Grid container spacing={2}>
{/* First Table */}
{/* <ReusableTable columns={columns} data={users} /> */}
<Grid item xs={6}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Kecamatan</Typography>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Age</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData1.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.id}</TableCell>
<TableCell>{row.name}</TableCell>
<TableCell>{row.age}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
{/* Second Table */}
<Grid item xs={6}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Kelurahan</Typography>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Product</TableCell>
<TableCell>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData2.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.id}</TableCell>
<TableCell>{row.product}</TableCell>
<TableCell>{row.price}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
{/* 3rd Table */}
<Grid item xs={6}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Kabupaten</Typography>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Age</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData1.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.id}</TableCell>
<TableCell>{row.name}</TableCell>
<TableCell>{row.age}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
{/* 4th Table */}
<Grid item xs={6}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Kota</Typography>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Product</TableCell>
<TableCell>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tableData2.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.id}</TableCell>
<TableCell>{row.product}</TableCell>
<TableCell>{row.price}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
</Grid>
</Box>
</Box>
);
};
export default MasterDataPage;

362
src/pages/Profile.js Normal file
View File

@ -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 (
<Box sx={{ padding: 3 }}>
<WarningDialog // ERROR MSG
open={isModalOpen}
onClose={closeModal}
errorMessage={error}
/>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>User Profile</Typography>
</Box>
<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"
name="username"
variant="outlined"
fullWidth
value={formData.username}
onChange={handleChange}
required
disabled
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Name"
name="name"
variant="outlined"
fullWidth
value={formData.name}
onChange={handleChange}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Email"
name="email"
variant="outlined"
fullWidth
value={formData.email}
onChange={handleChange}
type="email"
required
/>
</Box>
<Box mb={2} m={2} sx={{ display: 'flex', justifyContent: 'flex-start' }}>
<FormLabel component="legend">Status :
<FormControlLabel required label="Aktif" control={
<Checkbox value={formData.status} name="status" onClick={handleChange}
checked={ formData.status === "Y" ? true : false } />
}/>
</FormLabel>
</Box>
{/* <Box mb={2} m={2}>
<TextField
label="NIK"
variant="outlined"
fullWidth
value={formData.nik}
onChange={handleChange}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Position"
variant="outlined"
fullWidth
value={formData.position}
onChange={handleChange}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Telp"
variant="outlined"
fullWidth
value={formData.telp}
onChange={handleChange}
required
/>
</Box>
<Box mb={2} m={2}>
<TextField
label="Address"
variant="outlined"
fullWidth
value={formData.address}
onChange={handleChange}
required
/>
</Box>
<Box mb={2} m={2}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Organization</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.organisasi}
label="Organization"
onChange={handleChange}
name='organisasi'
>
<MenuItem value={'Koperasi'}>Koperasi</MenuItem>
<MenuItem value={'Damkar'}>Damkar</MenuItem>
<MenuItem value={'Kemasyarakatan'}>Kemasyarakatan</MenuItem>
</Select>
</FormControl>
</Box>
<Box mb={2} m={2}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Devision</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.devisi}
label="Devision"
onChange={handleChange}
name='devisi'
>
<MenuItem value={`Staff`}>Staff</MenuItem>
<MenuItem value={`Lead`}>Lead</MenuItem>
<MenuItem value={`Manager`}>Manager</MenuItem>
</Select>
</FormControl>
</Box>
<Box mb={2} m={2}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Unit</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.unit}
label="Unit"
onChange={handleChange}
name='unit'
>
<MenuItem value={1}>Satu</MenuItem>
<MenuItem value={2}>Dua</MenuItem>
<MenuItem value={3}>Tiga</MenuItem>
</Select>
</FormControl>
</Box> */}
<Box mb={2} m={2}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Role</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.idRole}
label="Role"
onChange={handleChange}
name='idRole'
>
{
roles.map((el, idx) => (
<MenuItem key={idx} value={el.id}>{el.name}</MenuItem>
))
}
</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">
<Button style={{ marginRight: '5px' }} variant="contained">Cancel</Button>
<Button variant="contained" color="success">Submit</Button>
</Box>
</form>
</Paper>
</Box>
</Box>
<Box sx={{ padding: 3 }}>
<Box sx={{ padding: 3 }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>User Password</Typography>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<Box mb={2} m={2}>
<TextField
label="Old Password"
name="oldPassword"
value={formData.oldPassword}
onChange={handleChange}
fullWidth
type="password"
required
/>
</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;

View File

@ -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 (
<Container>
<Typography variant="h4" align="center" gutterBottom marginTop={5}>
@ -85,9 +154,9 @@ const RoleMenuTable = () => {
<AddIcon />
</IconButton>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary" onClick={() => setOpenDialog(true)}>Create Role</Button>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', pr: 2, }}>
<Button variant="contained" color="primary" onClick={() => setOpenDialog(true)}>Create Role</Button>
</Box>
{/* Table for roles and menus */}
<TableContainer component={Paper} style={{ marginTop: '20px' }}>
@ -95,26 +164,28 @@ const RoleMenuTable = () => {
<TableHead>
<TableRow>
<TableCell><strong>Role</strong></TableCell>
{menus.map((menu) => (
<TableCell key={menu} align="center"><strong>{menu}</strong></TableCell>
{menus.map((menu, idx) => (
<TableCell key={idx} align="center"><strong>{menu.name}</strong></TableCell>
))}
<TableCell><strong>Action</strong></TableCell>
</TableRow>
</TableHead>
<TableBody>
{roles.map((role) => (
<TableRow key={role}>
<TableCell>{role}</TableCell>
{menus.map((menu) => (
<TableCell key={menu} align="center">
<TableRow key={role.id}>
<TableCell>{role.name}</TableCell>
{menus.map((menu, idx) => (
<TableCell key={idx} align="center">
<Checkbox
checked={roleMenus[role].includes(menu)}
onChange={() => 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
)}
/>
</TableCell>
))}
<TableCell align="center">
<Button>Delete</Button>
<Button onClick={() => deleteRole(role)}>Delete</Button>
</TableCell>
</TableRow>
))}
@ -150,8 +221,8 @@ const RoleMenuTable = () => {
<Dialog open={confirmDialog.open} onClose={() => handleConfirm(false)}>
<DialogTitle>Confirm Menu Selection</DialogTitle>
<DialogContent>
Are you sure you want to {roleMenus[confirmDialog.role]?.includes(confirmDialog.menu) ? 'remove' : 'add'}
the menu <strong>{confirmDialog.menu}</strong> for role <strong>{confirmDialog.role}</strong>?
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">

View File

@ -25,7 +25,11 @@ const SettingPage = () => {
return (
<Box sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-start', pr: 2, }}>
<Typography sx={{ color: 'gray', fontSize: '30px' }}>Setting</Typography>
</Box>
<Typography sx={{ color: 'gray', size: 'xl' }}>Manage Webservice</Typography>
<Box sx={{ padding: 3 }}>
<Box sx={{ padding: 3 }}>
<Paper sx={{ width: '100%', overflow: 'hidden' }}>

View File

@ -1,65 +1,111 @@
// Import React and Material-UI components
import React, { useState, useEffect } from 'react';
import {
Paper, Button, Dialog, DialogActions, DialogContent, DialogTitle, TableContainer,
Checkbox, FormControlLabel, Box, Typography, TextField, Grid
Paper, Button, Dialog, DialogActions, DialogContent, DialogTitle, TableContainer, FormLabel,
Checkbox, FormControlLabel, Box, Typography, TextField, Grid, MenuItem, InputLabel, Select, FormControl
} from '@mui/material';
import ReusableTable from '../components/Table';
import { fetchApi } from '../config/axios';
import WarningDialog from '../components/WarningDialog'; // ERROR MSG
const columns = [
{ id: 'username', label: 'Username' },
{ id: 'name', label: 'Name' },
{ id: 'email', label: 'Email' },
{ id: 'roles', label: 'Roles' },
{ id: 'role_name', label: 'Roles' },
{ id: 'status', label: 'Status' },
{ id: 'created_at', label: 'Created' },
{ id: 'actions', label: 'Actions' },
];
const initialUsers = [
{ id: 1, name: 'John Doe', email: 'john@example.com', roles: ['User'] },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', roles: ['Admin'] },
{ id: 3, name: 'Alice Johnson', email: 'alice@example.com', roles: [] }
];
const availableRoles = ['User', 'Admin', 'Editor'];
const initiateForm = {
username: '',
name: '',
email: '',
status: '',
id_role: '',
password: '',
confirmPassword: '',
// nik: '',
// position: '',
// telp: '',
// address: '',
// organisasi: '',
// devisi: '',
// unit: '',
}
export default function UserManagement() {
const [users, setUsers] = useState(initialUsers);
const [users, setUsers] = useState([]);
const [open, setOpen] = useState(false);
const [selectedUser, setSelectedUser] = useState(null);
const [selectedRoles, setSelectedRoles] = useState([]);
const [roles, setRoles] = useState([]);
const [openDialog, setOpenDialog] = useState(false);
const [formData, setFormData] = useState({
name: '',
email: '',
telp: '',
address: '',
password: '',
confirmPassword: '',
});
const [errors, setErrors] = useState({
passwordMatch: false,
});
const [labelDialog, setLabelDialog] = useState('');
const [formData, setFormData] = useState(initiateForm);
const [errors, setErrors] = useState({ passwordMatch: false, });
const [isModalOpen, setIsModalOpen] = useState(false); // ERROR MSG
const [error, setError] = useState(""); // ERROR MSG
useEffect(() => {
fetchUserRoles()
fetchUser()
// eslint-disable-next-line
}, []);
async function fetchUser(params) {
let temp = users.map(el => {
el.actions = [
{ label: 'Edit Role', color: 'primary', onClick: (row) => handleOpen(row) },
{ label: 'Delete', color: 'secondary', onClick: (row) => handleDelete(row) },
{ label: 'View', color: 'info', onClick: (row) => alert(`Viewing ${row.name}`) },
]
return el
})
setUsers(temp)
try {
let fetchUsers = await fetchApi('/api/user/list', 'GET', null, {
limit: 5,
page: 1,
with_deleted: true,
order_field: 'id',
order_direction: 'ASC'
});
console.log(fetchUsers);
if (fetchUsers.data && fetchUsers.data.data) {
let resFetchUsers = fetchUsers.data.data.list
let temp = resFetchUsers.map(el => {
if (el.status === 'Y') el.status = 'Aktif'
else el.status ='Tidak Aktif'
el.actions = [
{ label: 'Edit', color: 'info', onClick: (row) => handleOpen(row) },
{ label: 'Delete', color: 'secondary', onClick: (row) => handleDelete(row) },
]
return el
})
setUsers(temp)
}
} 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: 5,
page: 1,
with_deleted: true,
order_field: 'id',
order_direction: 'ASC'
});
if (userRoles.data && userRoles.data.data) setRoles(userRoles.data.data.list)
} catch (error) {
console.log(error);
handleError(`${error.message}. \n ${error.response.data.error}`)
}
}
const handleOpen = (user) => {
setSelectedUser(user);
setSelectedRoles(user.roles);
setOpen(true);
setLabelDialog(`Edit User`)
setFormData(user)
setOpenDialog(true)
// setSelectedUser(user);
// setSelectedRoles(user.role_name);
// setOpen(true);
};
const handleClose = () => {
@ -103,29 +149,66 @@ export default function UserManagement() {
}
};
const handleSubmit = () => {
if (!errors.passwordMatch) {
console.log('Form Data:', formData);
setOpen(false);
setFormData({
name: '',
email: '',
telp: '',
address: '',
password: '',
confirmPassword: '',
});
const handleSubmit = async () => {
try {
if (!errors.passwordMatch) {
console.log('Form Data:', formData);
// setOpen(false);
// setFormData(initiateForm);
}
console.log(formData);
formData.status = "Y";
if (labelDialog === `Create User`) {
delete formData.confirmPassword
let createUser = await fetchApi('/api/user/create', 'POST', formData);
console.log(createUser);
} else if (labelDialog === `Edit User`) {
delete formData.created_at
delete formData.updated_at
delete formData.role_name
delete formData.actions
delete formData.confirmPassword
console.log(formData);
let editUser = await fetchApi(`/api/user/update/${formData.id}`, 'PUT', formData);
console.log('editUser', editUser);
}
await fetchUser()
setOpenDialog(false)
} catch (error) {
console.log(error);
handleError(`${error.message}. \n ${error.response.data.error}`)
}
}
const createNewUserBtn = () => {
setLabelDialog(`Create User`);
setFormData(initiateForm);
setOpenDialog(true);
}
const handleError = (msg) => { // ERROR MSG
setError(msg);
setIsModalOpen(true);
};
const closeModal = () => { // ERROR MSG
setIsModalOpen(false);
setError("");
};
return (
<Box sx={{ padding: 3 }}>
<WarningDialog // ERROR MSG
open={isModalOpen}
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={() => setOpenDialog(true)}>Create New User</Button>
<Button variant="contained" color="primary" onClick={() => createNewUserBtn()}>Create New User</Button>
</Box>
<TableContainer component={Paper} sx={{ marginTop: 3 }}>
<ReusableTable columns={columns} data={users} />
@ -133,16 +216,16 @@ export default function UserManagement() {
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Add Roles to {selectedUser?.name}</DialogTitle>
<DialogContent>
{availableRoles.map((role) => (
{roles.map((role) => (
<FormControlLabel
key={role}
key={role.id}
control={
<Checkbox
checked={selectedRoles.includes(role)}
onChange={() => handleRoleChange(role)}
checked={selectedRoles.includes(role.name)}
onChange={() => handleRoleChange(role.name)}
/>
}
label={role}
label={role.name}
/>
))}
</DialogContent>
@ -158,9 +241,20 @@ export default function UserManagement() {
</TableContainer>
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} maxWidth="sm" fullWidth>
<DialogTitle>Create User</DialogTitle>
<DialogTitle>{labelDialog}</DialogTitle>
<DialogContent sx={{ marginTop: 2 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
sx={{ marginTop: 2 }}
label="Username"
name="username"
value={formData.username}
onChange={handleChange}
fullWidth
required
/>
</Grid>
<Grid item xs={12}>
<TextField
sx={{ marginTop: 2 }}
@ -183,6 +277,32 @@ export default function UserManagement() {
required
/>
</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
sx={{ marginTop: 2 }}
label="Nik"
name="nik"
value={formData.nik}
onChange={handleChange}
fullWidth
required
/>
</Grid>
<Grid item xs={12}>
<TextField
sx={{ marginTop: 2 }}
label="Position"
name="position"
value={formData.position}
onChange={handleChange}
fullWidth
required
/>
</Grid>
<Grid item xs={12}>
<TextField
label="Telephone"
@ -206,6 +326,76 @@ export default function UserManagement() {
required
/>
</Grid>
<Grid item xs={12}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Organization</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.organisasi}
label="Organization"
onChange={handleChange}
name='organisasi'
>
<MenuItem value={'Koperasi'}>Koperasi</MenuItem>
<MenuItem value={'Damkar'}>Damkar</MenuItem>
<MenuItem value={'Kemasyarakatan'}>Kemasyarakatan</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Devision</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.devisi}
label="Devision"
onChange={handleChange}
name='devisi'
>
<MenuItem value={`Staff`}>Staff</MenuItem>
<MenuItem value={`Lead`}>Lead</MenuItem>
<MenuItem value={`Manager`}>Manager</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Unit</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.unit}
label="Unit"
onChange={handleChange}
name='unit'
>
<MenuItem value={1}>Satu</MenuItem>
<MenuItem value={2}>Dua</MenuItem>
<MenuItem value={3}>Tiga</MenuItem>
</Select>
</FormControl>
</Grid> */}
<Grid item xs={12}>
<FormControl fullWidth required>
<InputLabel id="organization-label">Role</InputLabel>
<Select
labelId="organization-label"
id="organization"
value={formData.id_role}
label="Role"
onChange={handleChange}
name='id_role'
>
{
roles.map((el, idx) => (
<MenuItem key={idx} value={el.id}>{el.name}</MenuItem>
))
}
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<TextField
label="Password"
@ -239,7 +429,9 @@ export default function UserManagement() {
<Button
onClick={handleSubmit}
color="primary"
disabled={!formData.name || !formData.email || !formData.telp || !formData.address || !formData.password || errors.passwordMatch}
disabled={!formData.name || !formData.email || !formData.password || errors.passwordMatch || !formData.id_role
|| !formData.status || !formData.username
}
>
Submit
</Button>