[WMS-55] Create/Edit User
This commit is contained in:
@@ -52,6 +52,7 @@ import PublicRoutes from 'routes/PublicRoutes';
|
||||
import reduxStore from './redux/Store';
|
||||
import { protectedRoutes as routes } from './routes/index';
|
||||
import PrivateRoute from './routes/PrivateRoute';
|
||||
import MDAlert from 'components/MDAlert';
|
||||
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
@@ -168,6 +169,7 @@ export default function App() {
|
||||
{getRoutes(routes)}
|
||||
<Route path="*" element={<Navigate to="/" />} />
|
||||
</Routes>
|
||||
{/* <MDAlert dismissible><span>Submitted Successfully!</span></MDAlert> */}
|
||||
</ThemeProvider>
|
||||
<ToastContainer />
|
||||
</PersistGate>
|
||||
|
||||
3
src/components/AllocationManager/AllocationManager.component.scss
Executable file
3
src/components/AllocationManager/AllocationManager.component.scss
Executable file
@@ -0,0 +1,3 @@
|
||||
.c-AllocationManager {
|
||||
|
||||
}
|
||||
40
src/components/AllocationManager/AllocationManager.jsx
Executable file
40
src/components/AllocationManager/AllocationManager.jsx
Executable file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Grid, Typography } from '@mui/material';
|
||||
import MDBox from 'components/MDBox';
|
||||
import TransferList from 'components/MDTransferList';
|
||||
import './AllocationManager.component.scss';
|
||||
|
||||
const AllocationManager = props => {
|
||||
const {boxStyleOverride, component, gridStyleOverride, list, md, title, variant, xs} = props;
|
||||
return <Grid item className="c-AllocationManager" xs={xs || 12} md={md || 6} sx={gridStyleOverride}>
|
||||
<MDBox
|
||||
sx={boxStyleOverride || ({
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid #c2c2c2',
|
||||
borderTop: '7px solid #007aff',
|
||||
padding: '12px',
|
||||
borderRadius: '4px'
|
||||
})}
|
||||
>
|
||||
<Typography gutterBottom variant={variant || 'h6'} component={component || 'div'}>
|
||||
{title}
|
||||
</Typography>
|
||||
<TransferList list={list || []} />
|
||||
</MDBox>
|
||||
</Grid>;
|
||||
};
|
||||
|
||||
AllocationManager.propTypes = {
|
||||
boxStyleOverride: PropTypes.object,
|
||||
component: PropTypes.string,
|
||||
gridStyleOverride: PropTypes.object,
|
||||
list: PropTypes.array,
|
||||
md: PropTypes.number,
|
||||
styleOverride: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
variant: PropTypes.string,
|
||||
xs: PropTypes.number
|
||||
};
|
||||
|
||||
export default AllocationManager;
|
||||
8
src/components/AllocationManager/AllocationManager.test.js
Executable file
8
src/components/AllocationManager/AllocationManager.test.js
Executable file
@@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
import AllocationManager from "./AllocationManager";
|
||||
|
||||
describe("AllocationManager", () => {
|
||||
it("renders without error", () => {
|
||||
|
||||
});
|
||||
});
|
||||
3
src/components/AllocationManager/index.js
Executable file
3
src/components/AllocationManager/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import AllocationManager from './AllocationManager.jsx';
|
||||
|
||||
export default AllocationManager;
|
||||
@@ -3,7 +3,7 @@ import { Table } from '@mui/material';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function TblContainer({ children, backgroundColor, color }) {
|
||||
export default function TblContainer({ children, backgroundColor, color, id }) {
|
||||
const useStyles = makeStyles({
|
||||
headDisplay: {
|
||||
display: 'revert'
|
||||
@@ -31,7 +31,7 @@ export default function TblContainer({ children, backgroundColor, color }) {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Table className={classes.table}>{children}</Table>
|
||||
<Table className={classes.table} id={id}>{children}</Table>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -39,5 +39,6 @@ export default function TblContainer({ children, backgroundColor, color }) {
|
||||
TblContainer.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
backgroundColor: PropTypes.string.isRequired,
|
||||
color: PropTypes.string.isRequired
|
||||
color: PropTypes.string.isRequired,
|
||||
id: PropTypes.string
|
||||
};
|
||||
|
||||
@@ -10,11 +10,11 @@ const useStyles = makeStyles(() => ({
|
||||
}
|
||||
}));
|
||||
|
||||
export default function BasicTable({ children, headCells, backgroundColor, color }) {
|
||||
export default function BasicTable({ children, headCells, id, backgroundColor, color }) {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<TblContainer backgroundColor={backgroundColor} color={color}>
|
||||
<TblContainer id={id} backgroundColor={backgroundColor} color={color}>
|
||||
<TableHead className={classes.headDisplay}>
|
||||
<TableRow>
|
||||
{headCells.map((headCell) => (
|
||||
@@ -36,5 +36,6 @@ BasicTable.propTypes = {
|
||||
})
|
||||
).isRequired,
|
||||
backgroundColor: PropTypes.string,
|
||||
color: PropTypes.string
|
||||
color: PropTypes.string,
|
||||
id: PropTypes.string
|
||||
};
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import AdapterDateFns from '@mui/lab/AdapterDateFns';
|
||||
import LocalizationProvider from '@mui/lab/LocalizationProvider';
|
||||
import DateTimePicker from '@mui/lab/DateTimePicker';
|
||||
|
||||
export default function DateTimeInput() {
|
||||
export default function DateTimeInput({ disabled }) {
|
||||
const [value, setValue] = React.useState(new Date());
|
||||
|
||||
const handleChange = (newValue) => {
|
||||
@@ -16,6 +17,7 @@ export default function DateTimeInput() {
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||
<Stack spacing={3}>
|
||||
<DateTimePicker
|
||||
disabled={disabled}
|
||||
label=""
|
||||
value={value}
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
@@ -25,3 +27,7 @@ export default function DateTimeInput() {
|
||||
</LocalizationProvider>
|
||||
);
|
||||
}
|
||||
|
||||
DateTimeInput.propTypes = {
|
||||
disabled: PropTypes.bool
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ export default styled(Button)(({ theme, ownerState }) => {
|
||||
const { borderRadius } = borders;
|
||||
const { colored } = boxShadows;
|
||||
|
||||
// styles for the button with variant="contained"
|
||||
// styles for the button with variant='contained'
|
||||
const containedStyles = () => {
|
||||
// background color value
|
||||
const backgroundValue = palette[color] ? palette[color].main : white.main;
|
||||
@@ -97,7 +97,7 @@ export default styled(Button)(({ theme, ownerState }) => {
|
||||
};
|
||||
};
|
||||
|
||||
// styles for the button with variant="outlined"
|
||||
// styles for the button with variant='outlined'
|
||||
const outliedStyles = () => {
|
||||
// background color value
|
||||
const backgroundValue = color === 'white' ? rgba(white.main, 0.1) : transparent.main;
|
||||
@@ -145,7 +145,7 @@ export default styled(Button)(({ theme, ownerState }) => {
|
||||
};
|
||||
};
|
||||
|
||||
// styles for the button with variant="gradient"
|
||||
// styles for the button with variant='gradient'
|
||||
const gradientStyles = () => {
|
||||
// background value
|
||||
const backgroundValue =
|
||||
@@ -202,7 +202,7 @@ export default styled(Button)(({ theme, ownerState }) => {
|
||||
};
|
||||
};
|
||||
|
||||
// styles for the button with variant="text"
|
||||
// styles for the button with variant='text'
|
||||
const textStyles = () => {
|
||||
// color value
|
||||
const colorValue = palette[color] ? palette[color].main : white.main;
|
||||
|
||||
@@ -18,7 +18,7 @@ const MDButton = forwardRef(
|
||||
<MDButtonRoot
|
||||
{...rest}
|
||||
ref={ref}
|
||||
color="primary"
|
||||
color='primary'
|
||||
variant={variant === 'gradient' ? 'contained' : variant}
|
||||
size={size}
|
||||
ownerState={{ color, variant, size, circular, iconOnly, darkMode }}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
@@ -45,11 +46,11 @@ function intersection(a, b) {
|
||||
return a.filter((value) => b.indexOf(value) !== -1);
|
||||
}
|
||||
|
||||
export default function TransferList() {
|
||||
export default function TransferList({list}) {
|
||||
const classes = useStyles();
|
||||
const [checked, setChecked] = React.useState([]);
|
||||
const [left, setLeft] = React.useState([0, 1, 2, 3]);
|
||||
const [right, setRight] = React.useState([4, 5, 6, 7]);
|
||||
const [left, setLeft] = React.useState(list || []);
|
||||
const [right, setRight] = React.useState([]);
|
||||
|
||||
const leftChecked = intersection(checked, left);
|
||||
const rightChecked = intersection(checked, right);
|
||||
@@ -89,17 +90,18 @@ export default function TransferList() {
|
||||
setRight([]);
|
||||
};
|
||||
|
||||
const customList = (items) => (
|
||||
const customList = items => (
|
||||
<List component="div" role="list">
|
||||
{items.map((value) => {
|
||||
{items.map((item, key) => {
|
||||
const value = item.name;
|
||||
const labelId = `transfer-list-item-${value}-label`;
|
||||
|
||||
return (
|
||||
<ListItem button key={value} role="listitem" onClick={handleToggle(value)}>
|
||||
<ListItem button key={value + '-' + key} role="listitem" onClick={handleToggle(item)}>
|
||||
<ListItemIcon className={classes.unsetwidth}>
|
||||
<Checkbox
|
||||
disableRipple
|
||||
checked={checked.indexOf(value) !== -1}
|
||||
checked={checked.indexOf(item) !== -1}
|
||||
tabIndex={-1}
|
||||
inputProps={{
|
||||
'aria-labelledby': labelId
|
||||
@@ -110,7 +112,7 @@ export default function TransferList() {
|
||||
<ListItemText
|
||||
id={labelId}
|
||||
className={classes.label}
|
||||
primary={`Warehouse ${value + 1}`}
|
||||
primary={`${value}`}
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
@@ -126,7 +128,7 @@ export default function TransferList() {
|
||||
Unassigned
|
||||
</Typography>
|
||||
<Divider className={classes.line} />
|
||||
{customList(left)}
|
||||
{left && customList(left) }
|
||||
</Grid>
|
||||
<Grid item md={2}>
|
||||
<Grid container direction="column" alignItems="center">
|
||||
@@ -177,8 +179,12 @@ export default function TransferList() {
|
||||
Assigned
|
||||
</Typography>
|
||||
<Divider className={classes.line} />
|
||||
{customList(right)}
|
||||
{right && customList(right)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
TransferList.propTypes = {
|
||||
list: PropTypes.array
|
||||
};
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
import { TextField, InputAdornment, SvgIcon } from '@mui/material';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import Search from 'assets/images/SearchIcon';
|
||||
|
||||
function SearchBar() {
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
textField: {
|
||||
'& legend': {
|
||||
width: 0
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextField
|
||||
fullWidth
|
||||
className={classes.textField}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function TabPanel({ children, value, index }) {
|
||||
return <div>{value === index && <h1>{children}</h1>}</div>;
|
||||
export default function TabPanel({ children, className, value, index }) {
|
||||
return <div className={className ? className : ''}>{value === index && <h1>{children}</h1>}</div>;
|
||||
}
|
||||
|
||||
TabPanel.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.number,
|
||||
index: PropTypes.number
|
||||
};
|
||||
|
||||
3
src/components/Toggles/Toggles.component.scss
Executable file
3
src/components/Toggles/Toggles.component.scss
Executable file
@@ -0,0 +1,3 @@
|
||||
.c-Toggles {
|
||||
|
||||
}
|
||||
57
src/components/Toggles/Toggles.jsx
Executable file
57
src/components/Toggles/Toggles.jsx
Executable file
@@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import { Box, Grid } from '@mui/material';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import MDBox from 'components/MDBox';
|
||||
import Switch from 'components/Switch';
|
||||
import MDTypography from 'components/MDTypography';
|
||||
import './Toggles.component.scss';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
switchSpacer: {
|
||||
margin: '0',
|
||||
'& .MuiFormControlLabel-root': {
|
||||
margin: '0'
|
||||
},
|
||||
'& .MuiSwitch-root': {
|
||||
margin: '0'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const Toggles = props => {
|
||||
const {boxSx, md, title, toggles, typoComponent, typoSx, typoVariant, xs} = props;
|
||||
const classes = useStyles();
|
||||
|
||||
const switchRenders = toggles => toggles && toggles.map((toggle, key) => {
|
||||
return <MDBox key={key} display='flex' justifyContent='space-between' alignItems='center' lineHeight={1} className={classes.switchSpacer}
|
||||
sx={{ marginBottom: '20px !important' }}>
|
||||
<MDTypography variant='body2'>{toggle}</MDTypography>
|
||||
<Switch checked />
|
||||
</MDBox>;
|
||||
});
|
||||
|
||||
return <Grid item id='c-Toggles' xs={xs || 12} md={md || 3} >
|
||||
<MDBox sx={boxSx || {backgroundColor: '#fff', border: '1px solid #c2c2c2', borderTop: '7px solid #007aff', borderRadius: '4px'}}>
|
||||
<Typography gutterBottom variant={typoVariant || 'h6'} component={typoComponent || 'div'}
|
||||
sx={typoSx || {borderBottom: '1px solid #c2c2c2', padding: '10px 20px', marginBottom: '20px'}}>
|
||||
{title || "Title"}
|
||||
</Typography>
|
||||
<Box sx={{ padding: ' 0px 20px' }}>{toggles && switchRenders(toggles)}</Box>
|
||||
</MDBox>
|
||||
</Grid>;
|
||||
};
|
||||
|
||||
Toggles.propTypes = {
|
||||
boxSx: PropTypes.object,
|
||||
md: PropTypes.number,
|
||||
title: PropTypes.string,
|
||||
toggles: PropTypes.array,
|
||||
typoComponent: PropTypes.string,
|
||||
typoSx: PropTypes.object,
|
||||
typoVariant: PropTypes.string,
|
||||
xs: PropTypes.number
|
||||
};
|
||||
|
||||
export default Toggles;
|
||||
8
src/components/Toggles/Toggles.test.js
Executable file
8
src/components/Toggles/Toggles.test.js
Executable file
@@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
import Toggles from "./Toggles";
|
||||
|
||||
describe("Toggles", () => {
|
||||
it("renders without error", () => {
|
||||
|
||||
});
|
||||
});
|
||||
3
src/components/Toggles/index.js
Executable file
3
src/components/Toggles/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import Toggles from './Toggles.jsx';
|
||||
|
||||
export default Toggles;
|
||||
9
src/components/index.js
Executable file
9
src/components/index.js
Executable file
@@ -0,0 +1,9 @@
|
||||
/* PLOP_INJECT_IMPORT */
|
||||
import Toggles from './Toggles';
|
||||
import AllocationManager from './AllocationManager';
|
||||
|
||||
export {
|
||||
/* PLOP_INJECT_EXPORT */
|
||||
Toggles,
|
||||
AllocationManager
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
export default {
|
||||
LOGIN_USER: '/user/login',
|
||||
GET_WAREHOUSE_DATA: '/warehouse/all?page=0&perPage=50',
|
||||
CREATE_WAREHOUSE: '/warehouse/',
|
||||
GET_USERS_DATA: '/user/all?page=0&perPage=10',
|
||||
CREATE_USER: '/user/create',
|
||||
GET_USERS_DATA: '/user/all?page=0&perPage=20',
|
||||
GET_ROLES_DATA: '/user-role/all?page=0&perPage=10',
|
||||
CREATE_WAREHOUSE: '/warehouse/',
|
||||
GET_WAREHOUSE_DATA: '/warehouse/all?page=0&perPage=50',
|
||||
LOGIN_USER: '/user/login',
|
||||
GET_CHILDREN_FROM_PARENT: '/dashboard/get-children-from-parent',
|
||||
LOCATION_DELETE: '/dashboard/delete-location',
|
||||
ADD_NEW_ZONE: '/zone',
|
||||
ADD_NEW_AREA: '/area',
|
||||
ADD_NEW_ROW: '/row',
|
||||
|
||||
@@ -16,6 +16,7 @@ Coded by www.creative-tim.com
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import App from 'App';
|
||||
|
||||
// Soft UI Context Provider
|
||||
|
||||
@@ -27,7 +27,7 @@ import MDBox from 'components/MDBox';
|
||||
// Material Dashboard 2 PRO React context
|
||||
import { useMaterialUIController, setLayout } from 'context';
|
||||
|
||||
function DashboardLayout({ children }) {
|
||||
function DashboardLayout({ children, className }) {
|
||||
const [controller, dispatch] = useMaterialUIController();
|
||||
const { miniSidenav } = controller;
|
||||
const { pathname } = useLocation();
|
||||
@@ -38,6 +38,8 @@ function DashboardLayout({ children }) {
|
||||
|
||||
return (
|
||||
<MDBox
|
||||
id="dashboard-layout"
|
||||
className={className ? className : ''}
|
||||
sx={({ breakpoints, transitions, functions: { pxToRem } }) => ({
|
||||
p: 0,
|
||||
position: 'relative',
|
||||
@@ -58,7 +60,8 @@ function DashboardLayout({ children }) {
|
||||
|
||||
// Typechecking props for the DashboardLayout
|
||||
DashboardLayout.propTypes = {
|
||||
children: PropTypes.node.isRequired
|
||||
children: PropTypes.node.isRequired,
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
||||
export default DashboardLayout;
|
||||
|
||||
308
src/pages/createEditUser/index.js
Normal file
308
src/pages/createEditUser/index.js
Normal file
@@ -0,0 +1,308 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useFormik } from 'formik';
|
||||
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import { Box, Grid } from '@mui/material';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import Select from '@mui/material/Select';
|
||||
|
||||
import WarehouseActions, { WarehouseSelectors } from 'redux/WarehouseRedux';
|
||||
import InventoryActions, { InventorySelectors } from 'redux/InventoryRedux';
|
||||
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
|
||||
import { AuthSelectors } from 'redux/AuthRedux';
|
||||
import UsersActions from 'redux/UsersRedux';
|
||||
|
||||
import schema from 'services/ValidationServices';
|
||||
|
||||
import MDBox from 'components/MDBox';
|
||||
import Switch from 'components/Switch';
|
||||
import DashboardNavbar from 'components/DashboardNavbar';
|
||||
import { AllocationManager, Toggles } from 'components';
|
||||
import DashboardLayout from 'layouts/DashboardLayout';
|
||||
import MDButton from 'components/Button';
|
||||
import DateTimeInput from 'components/DateTimePicker';
|
||||
import MDInput from 'components/MDInput';
|
||||
|
||||
import { API } from 'constant';
|
||||
import UserIcon from 'assets/images/userIcon.png';
|
||||
import EditIcon from 'assets/images/edit-icon.png';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
labelSize: {
|
||||
fontSize: '16px',
|
||||
letterSpacing: '0.01em',
|
||||
color: '#000',
|
||||
marginBottom: '4px'
|
||||
},
|
||||
boxWrap: {
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid #c2c2c2',
|
||||
borderTop: '3px solid #007aff',
|
||||
display: 'inline-block',
|
||||
padding: '12px',
|
||||
borderRadius: '4px'
|
||||
},
|
||||
noLegend: {
|
||||
display: 'none'
|
||||
},
|
||||
fullWidth: {
|
||||
width: '100%',
|
||||
borderColor: '#d2d6da',
|
||||
borderRadius: '0.375rem'
|
||||
},
|
||||
createEditUserGlobal: {
|
||||
'& legend': {
|
||||
width: 0
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
/* eslint-disable complexity */
|
||||
function CreateEditUser(props) {
|
||||
const { context } = props;
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const roles = useSelector(RolesSelectors.getRolesDetail);
|
||||
const warehouses = useSelector(WarehouseSelectors.getWarehouseDetail);
|
||||
const inventories = useSelector(InventorySelectors.getInventoryDetail);
|
||||
const currentUser = useSelector(AuthSelectors.getUser);
|
||||
const location = useLocation();
|
||||
const [editedUser, setEditedUser] = useState();
|
||||
const [userRoles, setUserRoles] = useState([]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
fullName: editedUser ? editedUser.fullName : '',
|
||||
phoneNumber: editedUser ? editedUser.phoneNumber : '',
|
||||
roles: userRoles,
|
||||
permissions: {},
|
||||
isActive: editedUser && editedUser.isActive !== undefined ? editedUser.isActive : true,
|
||||
createdBy: context === 'new' ? currentUser ? currentUser.fullName : '' : editedUser ? editedUser.createdBy?.fullName : '',
|
||||
createdOn: new Date(),
|
||||
updatedBy: context === 'new' ? currentUser ? currentUser.fullName : '' : editedUser ? editedUser.updatedBy?.fullName : '',
|
||||
updatedOn: new Date()
|
||||
},
|
||||
validationSchema: schema.createUser,
|
||||
onSubmit: (values, { setSubmitting }) =>
|
||||
{
|
||||
const onValidationFailed = () => {
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
// const onSuccessfulSubmission = data => {
|
||||
const onSuccessfulSubmission = () => {
|
||||
navigate('/setup/users-access');
|
||||
// TODO
|
||||
// dispatchAlert
|
||||
};
|
||||
values.roles = values.roles && values.roles.length > 0 ? values.roles.map(role => role._id) : [];
|
||||
dispatch(
|
||||
UsersActions.createUserAction({
|
||||
loader: 'loading-request',
|
||||
slug: API.CREATE_USER,
|
||||
method: 'post',
|
||||
data: values,
|
||||
onValidationFailed,
|
||||
onSuccessfulSubmission
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (context === 'edit') {
|
||||
const editedUser = location?.state?.user;
|
||||
if (!editedUser) {
|
||||
navigate('/setup/users-access');
|
||||
} else {
|
||||
setEditedUser(editedUser);
|
||||
setUserRoles(editedUser.role_name ? editedUser.role_name.split(',') : []);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(WarehouseActions.warehouseDataAction({loader: 'loading-request', slug: API.GET_WAREHOUSE_DATA,method: 'get'}));
|
||||
dispatch(InventoryActions.getInventoryAction({loader: 'loading-request', slug: API.GET_INVENTORY,method: 'get'}));
|
||||
!roles || roles.length === 0 && dispatch(RolesActions.getRolesAction({loader: 'loading-request', slug: API.GET_ROLES_DATA, method: 'get'}));
|
||||
dispatch(RolesActions.getRolesAction({loader: 'loading-request', slug: API.GET_ROLES_DATA, method: 'get'}));
|
||||
dispatch(PermissionActions.getRolesAction({loader: 'loading-request', slug: API.GET_ROLES_DATA, method: 'get'}));
|
||||
fetchPermissions();
|
||||
fetchActions();
|
||||
}, []);
|
||||
|
||||
|
||||
const handleChange = event => {
|
||||
const value = typeof event.target.value === 'string' ? event.target.value?.split(',') : event.target.value;
|
||||
setUserRoles(value);
|
||||
formik.handleChange(event);
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardLayout className={classes.createEditUserGlobal}>
|
||||
<DashboardNavbar />
|
||||
<MDBox component='form' role='form' px={2} sx={{ backgroundColor: '#fff' }} onSubmit={formik.handleSubmit}>
|
||||
<MDBox mx={4} sx={{ border: '1px solid #C4C4C4', borderRadius: '4px', padding: '30px' }}>
|
||||
<MDBox sx={{ width: '50%', margin: 'auto' }}>
|
||||
<MDBox sx={{ width: '120px', margin: 'auto', position: 'relative' }}>
|
||||
<img src={UserIcon} alt="img" />
|
||||
<MDBox sx={{ position: 'absolute', bottom: '0', right: '0', cursor: 'pointer' }}>
|
||||
<img src={EditIcon} alt="img" />
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
<MDBox sx={{ marginBottom: '24px' }}>
|
||||
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||
User Name
|
||||
</Box>
|
||||
<MDInput fullWidth disabled={context === 'edit'} value={formik.values.fullName} name="fullName" type="text"
|
||||
variant="outlined" error={formik.touched.fullName && Boolean(formik.errors.fullName)}
|
||||
helperText={formik.touched.fullName && formik.errors.fullName} onChange={formik.handleChange} />
|
||||
</MDBox>
|
||||
<MDBox sx={{ marginBottom: '24px' }}>
|
||||
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||
Phone Number
|
||||
</Box>
|
||||
<MDInput fullWidth value={formik.values.phoneNumber} name="phoneNumber" type="text"
|
||||
variant="outlined" error={formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber)}
|
||||
helperText={formik.touched.phoneNumber && formik.errors.phoneNumber} onChange={formik.handleChange} />
|
||||
</MDBox>
|
||||
<MDBox sx={{ marginBottom: '24px' }}>
|
||||
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||
Role
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', columnGap: '20px' }}>
|
||||
<Box sx={{ width: '70%' }}>
|
||||
<Select
|
||||
multiple
|
||||
displayEmpty
|
||||
name='roles'
|
||||
value={userRoles}
|
||||
input={<OutlinedInput />}
|
||||
error={formik.touched.roles && Boolean(formik.errors.roles)}
|
||||
renderValue={() => {
|
||||
if (userRoles.length === 0) {
|
||||
return 'Please select a role';
|
||||
}
|
||||
|
||||
return userRoles.map(role => role.name).join(',');
|
||||
}}
|
||||
inputProps={{ 'aria-label': 'Without label' }}
|
||||
sx={{
|
||||
width: '100%'
|
||||
}}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{roles && roles.map((role, key) => <MenuItem key={key} value={role}>{role.name}</MenuItem>)}
|
||||
</Select>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '30%',
|
||||
border: '1px solid #C4C4C4',
|
||||
borderRadius: '4px'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component="div"
|
||||
sx={{
|
||||
fontSize: '16px',
|
||||
lineHeight: '20px',
|
||||
letterSpacing: '0.01em',
|
||||
textTransform: 'capitalize',
|
||||
color: '#000',
|
||||
marginLeft: '10px'
|
||||
}}
|
||||
>
|
||||
Access
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
left: '20px'
|
||||
}}
|
||||
>
|
||||
<Switch checked={formik.values.isActive} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</MDBox>
|
||||
<Grid container spacing={2} className={classes.margin}>
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2} className={classes.margin}>
|
||||
<Grid item xs={6}>
|
||||
<Box component="div" className={classes.labelSize}>
|
||||
Created By
|
||||
</Box>
|
||||
<MDInput fullWidth disabled name="warehousename" type="text" value={currentUser ? currentUser.fullName : ''} variant="outlined" />
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Box component="div" className={classes.labelSize}>
|
||||
Date & Time
|
||||
</Box>
|
||||
<DateTimeInput disabled />
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Box component="div" className={classes.labelSize}>
|
||||
Last Updated by
|
||||
</Box>
|
||||
<MDInput fullWidth disabled name="warehousename" type="text" value={currentUser ? currentUser.fullName : ''} variant="outlined" />
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Box component="div" className={classes.labelSize}>
|
||||
Date & Time
|
||||
</Box>
|
||||
<DateTimeInput disabled />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
<Grid container spacing={4} sx={{ marginTop: '-6px' }}>
|
||||
<AllocationManager gridStyleOverride={{ paddingLeft: '4rem !important' }} list={warehouses} title='Warehouse' />
|
||||
<AllocationManager gridStyleOverride={{ paddingRight: '2rem' }} list={inventories} title='Inventory' />
|
||||
</Grid>
|
||||
<Grid container spacing={2} sx={{ marginTop: '12px', paddingLeft: '2rem' }}>
|
||||
<Toggles title='Actions' />
|
||||
<Toggles title='Application' />
|
||||
</Grid>
|
||||
<MDBox
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
lineHeight={1}
|
||||
sx={{ marginBottom: '15px', marginTop: '45px', paddingBottom: '30px' }}
|
||||
>
|
||||
<MDButton
|
||||
size="medium"
|
||||
color="error"
|
||||
variant="outlined"
|
||||
type="button"
|
||||
sx={{ marginRight: '15px' }}
|
||||
>
|
||||
Cancel
|
||||
</MDButton>
|
||||
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
||||
{context === 'new' ? 'Create' : 'Save'}
|
||||
</MDButton>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
</DashboardLayout>
|
||||
);
|
||||
}
|
||||
|
||||
CreateEditUser.propTypes = {
|
||||
context: PropTypes.string
|
||||
};
|
||||
|
||||
export default CreateEditUser;
|
||||
@@ -28,8 +28,16 @@ const useStyles = makeStyles((theme) => ({
|
||||
color: theme.palette.primary.light,
|
||||
marginRight: '8px'
|
||||
},
|
||||
statusActive: {
|
||||
color: 'green'
|
||||
},
|
||||
statusInactive: {
|
||||
color: 'red'
|
||||
},
|
||||
margin: {
|
||||
marginBottom: '20px'
|
||||
marginBottom: '20px',
|
||||
borderTop: '1px solid #ddd',
|
||||
borderBottom: '1px solid #ddd'
|
||||
},
|
||||
wrap: {
|
||||
display: 'flex'
|
||||
@@ -41,30 +49,25 @@ const useStyles = makeStyles((theme) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
radialBorder: {
|
||||
overflow: 'hidden',
|
||||
borderRadius: '0.5rem'
|
||||
},
|
||||
tabs: {
|
||||
borderRadius: 0,
|
||||
'& .MuiButtonBase-root.MuiTab-root': {
|
||||
padding: '12px 0px',
|
||||
borderRadius: '0px'
|
||||
borderRadius: '0px',
|
||||
fontWeight: 'bold',
|
||||
backgroundColor: '#eee',
|
||||
border: '1px solid #ddd'
|
||||
},
|
||||
'& .Mui-selected': {
|
||||
'& .MuiButtonBase-root.MuiTab-root.Mui-selected': {
|
||||
backgroundColor: '#017AFF',
|
||||
color: 'white'
|
||||
color: 'white !important'
|
||||
}
|
||||
}
|
||||
}));
|
||||
const userHeadCells = [
|
||||
{ id: 'fullName', label: 'Name' },
|
||||
{ id: 'role_name', label: 'Roles' },
|
||||
{ id: 'updated_at', label: 'Updated at' },
|
||||
{ id: 'created_at', label: 'Created by and at' }
|
||||
];
|
||||
|
||||
const rolesHeadCells = [
|
||||
{ id: 'role', label: 'Role' },
|
||||
{ id: 'permissions', label: 'Permissions' },
|
||||
{ id: 'status', label: 'Status' }
|
||||
];
|
||||
|
||||
// const permissionsHeadCells = [
|
||||
// { id: 'permission', label: 'Permission' },
|
||||
// { id: 'warehouse', label: 'Warehouse' },
|
||||
@@ -84,6 +87,26 @@ function UserAccessScreen() {
|
||||
const [rolesRecords, setRoleRecords] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const userHeadCells = [
|
||||
{ id: 'full_name', label: 'User Name', isEditAnchor: true, value: record => record.fullName },
|
||||
{ id: 'phone_number', label: 'Phone Number', value: record => record.phoneNumber },
|
||||
{ id: 'role_name', label: 'Roles', value: record => record.role_name },
|
||||
{ id: 'updated_by_at', label: 'Last Updated By & Date', value: record => `${record.updatedBy?.fullName} | ${moment(record.updatedAt).format('D/M/YYYY h:m:s A')}` },
|
||||
{ id: 'created_by_at', label: 'Created By & Date', value: record => `${record.createdBy?.fullName} | ${moment(record.createdAt).format('D/M/YYYY h:m:s A')}` },
|
||||
{ id: 'last_login', label: 'Last Login', value: record => record.lastLogin },
|
||||
{
|
||||
id: 'is_active', label: 'Access', value: record => record.isActive ? <span className={classes.statusActive}>Active</span>
|
||||
: <span className={status.Inactive}>Inactive</span>
|
||||
}
|
||||
];
|
||||
|
||||
const rolesHeadCells = [
|
||||
{ id: 'role', label: 'Role' },
|
||||
{ id: 'permissions', label: 'Permissions' },
|
||||
{ id: 'status', label: 'Status' }
|
||||
];
|
||||
|
||||
|
||||
const usersHandler = () => {
|
||||
dispatch(
|
||||
UsersActions.getUsersAction({
|
||||
@@ -120,14 +143,11 @@ function UserAccessScreen() {
|
||||
let roles = JSON.parse(JSON.stringify(rolesData));
|
||||
roles = roles.map((item) => {
|
||||
item.name = item.name.split('-').join(' ').toUpperCase();
|
||||
item.permissions = item.permissions.map((permission) => permission.name).join(',');
|
||||
item.permissions = item.permissions?.allowedUIModules?.join(',');
|
||||
if (!item.permissions) {
|
||||
item.permissions = 'NA';
|
||||
}
|
||||
item.status = 'INACTIVE';
|
||||
if (item.status) {
|
||||
item.status = 'ACTIVE';
|
||||
}
|
||||
item.status = item.status ? 'ACTIVE' : 'INACTIVE';
|
||||
return item;
|
||||
});
|
||||
setRoleRecords(roles);
|
||||
@@ -144,6 +164,17 @@ function UserAccessScreen() {
|
||||
}
|
||||
}));
|
||||
|
||||
const columnRenders = userRecords && userRecords.map(record => {
|
||||
return <StyledTableRow key={record.id}>
|
||||
{userHeadCells.map((columnConfig, key) => <TableCell key={key} onClick={() => columnConfig.isEditAnchor && navigate('/setup/users-access/edit-user', {state: {user: record}})}>
|
||||
{columnConfig.isEditAnchor && <span className={classes.iconwrap}>
|
||||
<EditIcon className={classes.iconSize}/>
|
||||
</span>}
|
||||
{columnConfig.value(record)}
|
||||
</TableCell>)}
|
||||
</StyledTableRow>;
|
||||
});
|
||||
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<DashboardNavbar />
|
||||
@@ -154,79 +185,67 @@ function UserAccessScreen() {
|
||||
{ name: 'Users and Access', path: '/setup/users-access' }
|
||||
]}
|
||||
/>
|
||||
<MDBox px={2} py={3}>
|
||||
<Grid container spacing={2} className={classes.margin}>
|
||||
<Grid item xs={12} sm={4} md={4}>
|
||||
<Tabs value={value} className={classes.tabs} onChange={handleTabs}>
|
||||
<MDBox px={0} py={3}>
|
||||
<Grid container spacing={1} className={classes.margin}>
|
||||
<Grid item xs={12} sm={4} md={4} className='ps-2 pt-0'>
|
||||
<Tabs value={value} className={`p-0 h-100 ${classes.tabs}`} onChange={handleTabs}>
|
||||
<Tab label="Roles" onClick={() => rolesHandler()} />
|
||||
<Tab label="Users" onClick={() => usersHandler()} />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4} md={6}>
|
||||
<Grid item xs={12} sm={4} md={6} className='py-2' style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<SearchBar />
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4} md={2}>
|
||||
<Grid item xs={12} sm={4} md={2} className='py-2' style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<MDButton
|
||||
color="primary"
|
||||
size="medium"
|
||||
onClick={() => navigate('/setup/users-access/create-role')}
|
||||
onClick={() => navigate(`/setup/users-access/${value === 0 ? 'create-role' : 'create-user'}`)}
|
||||
>
|
||||
{'+ CREATE USER'}
|
||||
{value === 0 ? '+ CREATE ROLE' : '+ CREATE USER'}
|
||||
</MDButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<TabPanel value={value} index={0}>
|
||||
<BasicTable
|
||||
headCells={rolesHeadCells}
|
||||
records={rolesRecords}
|
||||
backgroundColor="#007AFF"
|
||||
color="#fff"
|
||||
>
|
||||
<TableBody>
|
||||
{rolesRecords &&
|
||||
rolesRecords.map((item) => (
|
||||
<StyledTableRow key={item.id}>
|
||||
<TableCell>
|
||||
<div className={classes.iconwrap}>
|
||||
<EditIcon className={classes.iconSize} />
|
||||
{item.name}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{item.permissions}</TableCell>
|
||||
<TableCell>{item.status}</TableCell>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</BasicTable>
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1}>
|
||||
<BasicTable
|
||||
headCells={userHeadCells}
|
||||
records={userRecords}
|
||||
backgroundColor="#007AFF"
|
||||
color="#fff"
|
||||
>
|
||||
<TableBody>
|
||||
{userRecords &&
|
||||
userRecords.map((item) => (
|
||||
<StyledTableRow key={item.id}>
|
||||
<TableCell>
|
||||
<div className={classes.iconwrap}>
|
||||
<EditIcon className={classes.iconSize} />
|
||||
{item.fullName}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{item.role_name}</TableCell>
|
||||
<TableCell>{moment(item.updatedAt).format('D/M/YYYY h:m:s A')}</TableCell>
|
||||
<TableCell>
|
||||
{item.createdBy ? item.createdBy?.fullName + ' | ' : null}
|
||||
{moment(item.createdAt).format('D/M/YYYY h:m:s A')}
|
||||
</TableCell>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</BasicTable>
|
||||
</TabPanel>
|
||||
<Grid px={2}>
|
||||
<TabPanel value={value} index={0} className={classes.radialBorder}>
|
||||
<BasicTable
|
||||
headCells={rolesHeadCells}
|
||||
records={rolesRecords}
|
||||
backgroundColor="#007AFF"
|
||||
color="#fff"
|
||||
>
|
||||
<TableBody>
|
||||
{rolesRecords &&
|
||||
rolesRecords.map((item) => (
|
||||
<StyledTableRow key={item.id}>
|
||||
<TableCell>
|
||||
<div className={classes.iconwrap}>
|
||||
<EditIcon className={classes.iconSize} />
|
||||
{item.name}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{item.permissions}</TableCell>
|
||||
<TableCell>{item.status}</TableCell>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</BasicTable>
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1} className={classes.radialBorder}>
|
||||
<BasicTable
|
||||
id="user-list"
|
||||
headCells={userHeadCells}
|
||||
records={userRecords}
|
||||
backgroundColor="#007AFF"
|
||||
color="#fff"
|
||||
>
|
||||
{userRecords && userRecords.length > 0
|
||||
? <TableBody>
|
||||
{columnRenders}
|
||||
</TableBody> : 'No Records to Display'}
|
||||
</BasicTable>
|
||||
</TabPanel>
|
||||
</Grid>
|
||||
</MDBox>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,10 @@ import { getFetchingValue, getErrorValue } from '../services/Utils';
|
||||
const { Types, Creators } = createActions({
|
||||
getUsersAction: ['payload'],
|
||||
getUsersSuccess: ['data'],
|
||||
getUsersFailure: ['error']
|
||||
getUsersFailure: ['error'],
|
||||
createUserAction: ['payload'],
|
||||
createUserSuccess: ['data'],
|
||||
createUserFailure: ['error']
|
||||
});
|
||||
|
||||
export const UsersTypes = Types;
|
||||
@@ -45,10 +48,30 @@ export const onGetUsersFailure = (state, { error }) =>
|
||||
fetching: _.without(state.fetching, error?.loader),
|
||||
error: { ...state.error, [error?.loader]: error?.error }
|
||||
});
|
||||
export const onCreateUserAction = (state, { payload }) =>
|
||||
state.merge({
|
||||
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||
error: getErrorValue(state?.error, payload?.loader)
|
||||
});
|
||||
|
||||
export const onCreateUserSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader)
|
||||
});
|
||||
|
||||
export const onCreateUserFailure = (state, { error }) =>
|
||||
state.merge({
|
||||
fetching: _.without(state.fetching, error?.loader),
|
||||
error: { ...state.error, [error?.loader]: error?.error }
|
||||
});
|
||||
|
||||
/* ------------- Hookup Reducers To Types ------------- */
|
||||
export const usersReducer = createReducer(INITIAL_STATE, {
|
||||
[Types.GET_USERS_ACTION]: onGetUsersAction,
|
||||
[Types.GET_USERS_SUCCESS]: onGetUsersSuccess,
|
||||
[Types.GET_USERS_FAILURE]: onGetUsersFailure
|
||||
[Types.GET_USERS_FAILURE]: onGetUsersFailure,
|
||||
[Types.CREATE_USER_ACTION]: onCreateUserAction,
|
||||
[Types.CREATE_USER_SUCCESS]: onCreateUserSuccess,
|
||||
[Types.CREATE_USER_FAILURE]: onCreateUserFailure
|
||||
});
|
||||
|
||||
@@ -1,65 +1,24 @@
|
||||
/**
|
||||
=========================================================
|
||||
* Material Dashboard 2 PRO React - v2.0.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/material-dashboard-pro-react
|
||||
* Copyright 2021 Creative Tim (https://www.creative-tim.com)
|
||||
|
||||
Coded by www.creative-tim.com
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
/**
|
||||
All of the routes for the Material Dashboard 2 PRO React are added here,
|
||||
You can add a new route, customize the routes and delete the routes here.
|
||||
|
||||
Once you add a new route on this file it will be visible automatically on
|
||||
the Sidenav.
|
||||
|
||||
For adding a new route you can follow the existing routes in the routes array.
|
||||
1. The `type` key with the `collapse` value is used for a route.
|
||||
2. The `type` key with the `title` value is used for a title inside the Sidenav.
|
||||
3. The `type` key with the `divider` value is used for a divider between Sidenav items.
|
||||
4. The `name` key is used for the name of the route on the Sidenav.
|
||||
5. The `key` key is used for the key of the route (It will help you with the key prop inside a loop).
|
||||
6. The `icon` key is used for the icon of the route on the Sidenav, you have to add a node.
|
||||
7. The `collapse` key is used for making a collapsible item on the Sidenav that contains other routes
|
||||
inside (nested routes), you need to pass the nested routes inside an array as a value for the `collapse` key.
|
||||
8. The `route` key is used to store the route location which is used for the react router.
|
||||
9. The `href` key is used to store the external links location.
|
||||
10. The `title` key is only for the item with the type of `title` and its used for the title text on the Sidenav.
|
||||
10. The `component` key is used to store the component of its route.
|
||||
*/
|
||||
|
||||
// Material Dashboard 2 PRO React layouts
|
||||
import DashboardScreen from 'pages/dashboard';
|
||||
import LoginScreen from 'pages/authentication';
|
||||
|
||||
// Material Dashboard 2 PRO React components
|
||||
// import MDAvatar from 'components/MDAvatar';
|
||||
|
||||
// @mui icons
|
||||
import Icon from '@mui/material/Icon';
|
||||
import InventoryScreen from 'pages/inventory';
|
||||
import WarehouseScreen from 'pages/warehouse';
|
||||
import HomepageScreen from 'pages/homepage';
|
||||
import DashboardScreen from 'pages/dashboard';
|
||||
import LoginScreen from 'pages/authentication';
|
||||
import LocationLabelingScreen from 'pages/labeling';
|
||||
import UserAccessScreen from 'pages/useraccess';
|
||||
import NewWarehouseDetails from 'pages/newWarehouseDetails';
|
||||
|
||||
import SetupHome from 'pages/setup';
|
||||
import NewWarehouseDetails from 'pages/newWarehouseDetails';
|
||||
import EditWarehouseDetails from 'pages/editWarehouseDetails';
|
||||
import LabelingHome from 'pages/labellingHome';
|
||||
import SetupInventory from 'pages/setupInventory';
|
||||
import CreateUserRole from 'pages/createUserRole';
|
||||
import CreateEditUser from 'pages/createEditUser';
|
||||
import WidgetLabel from 'pages/widgetLabel';
|
||||
import ItemListing from 'pages/itemListing';
|
||||
import HomeIcon from 'assets/images/HomeIcon';
|
||||
import SetupIcon from 'assets/images/SetupIcon';
|
||||
import AddNewItem from '../pages/addNewProduct';
|
||||
import CreateUserRole from 'pages/createUserRole';
|
||||
import WidgetLabel from 'pages/widgetLabel';
|
||||
import ItemListing from 'pages/itemListing';
|
||||
|
||||
// Images
|
||||
// import profilePicture from 'assets/images/team-3.jpg';
|
||||
@@ -211,6 +170,20 @@ const protectedRoutes = [
|
||||
route: '/setup/users-access/create-role',
|
||||
hide: true,
|
||||
component: <CreateUserRole />
|
||||
},
|
||||
{
|
||||
name: 'Create User',
|
||||
key: 'create-user',
|
||||
route: '/setup/users-access/create-user',
|
||||
hide: true,
|
||||
component: <CreateEditUser context='new' />
|
||||
},
|
||||
{
|
||||
name: 'Edot User',
|
||||
key: 'edit-user',
|
||||
route: '/setup/users-access/edit-user',
|
||||
hide: true,
|
||||
component: <CreateEditUser context='edit' />
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,4 +27,33 @@ export function* onRequestUsersData({ payload }) {
|
||||
);
|
||||
}
|
||||
}
|
||||
export default [takeLatest(UsersTypes.GET_USERS_ACTION, onRequestUsersData)];
|
||||
|
||||
export function* onCreateUserData({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
payload?.data
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
payload.onSuccessfulSubmission(response.data?.data);
|
||||
yield put(
|
||||
UsersActions.createUserSuccess({
|
||||
loader: payload?.loader,
|
||||
usersDetail: response?.data?.data
|
||||
})
|
||||
);
|
||||
} else {
|
||||
payload.onValidationFailed(response.data?.error);
|
||||
yield put(
|
||||
UsersActions.createUserFailure({
|
||||
loader: payload?.loader,
|
||||
error: response?.data
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
export default [
|
||||
takeLatest(UsersTypes.GET_USERS_ACTION, onRequestUsersData),
|
||||
takeLatest(UsersTypes.CREATE_USER_ACTION, onCreateUserData)
|
||||
];
|
||||
|
||||
@@ -63,6 +63,12 @@ const schema = {
|
||||
inventory_process: Yup.string()
|
||||
}),
|
||||
image: Yup.array()
|
||||
}),
|
||||
|
||||
createUser: Yup.object({
|
||||
fullName: Yup.string('Enter Full Name').required('User Name is required'),
|
||||
phoneNumber: Yup.string('Enter Phone Numbe').required('Phone Number is required'),
|
||||
roles: Yup.string('Select a role').required('At least one role is required'),
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user