Compare commits
44 Commits
develop
...
feature/wm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55d8526808 | ||
|
|
c4d3190d5e | ||
|
|
ceb9256f1b | ||
|
|
8abe5ba900 | ||
|
|
4d3b6ec9df | ||
|
|
b2c0c3f958 | ||
|
|
7561006ce0 | ||
|
|
7131e86792 | ||
|
|
cb71fe1a42 | ||
|
|
787c91fe7a | ||
|
|
c62453e318 | ||
| e17f4fb0b6 | |||
|
|
728406b452 | ||
|
|
30b4b5d7c2 | ||
|
|
51dc7c33c3 | ||
|
|
e75e270cdf | ||
|
|
913c1dbcf2 | ||
|
|
940c1e704e | ||
|
|
0fb3f3bf55 | ||
|
|
70cda3d3f2 | ||
|
|
75b6f2a88b | ||
|
|
be258aea34 | ||
|
|
ef4e3a2d9f | ||
|
|
320ec7061c | ||
|
|
ae7e8547c3 | ||
|
|
74199f6752 | ||
|
|
54369ae9b7 | ||
| 87a890cd23 | |||
|
|
95e05cb51c | ||
| e87dbdeee6 | |||
|
|
eb0e34fef5 | ||
| 61bfd87029 | |||
|
|
1469e4ff5a | ||
|
|
2f8d60049c | ||
|
|
85947c18c2 | ||
|
|
a22c3fcf42 | ||
|
|
8cccf1f034 | ||
|
|
5d2e29fc41 | ||
|
|
5381f7d727 | ||
|
|
e2d3ccfb7e | ||
|
|
fd8d0b1167 | ||
|
|
a883212126 | ||
|
|
7c9bc373d4 | ||
|
|
f1a2210e16 |
@@ -8,6 +8,10 @@ module.exports = {
|
|||||||
extends: ['eslint:recommended', 'plugin:react/recommended'],
|
extends: ['eslint:recommended', 'plugin:react/recommended'],
|
||||||
parser: '@babel/eslint-parser',
|
parser: '@babel/eslint-parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
requireConfigFile: false,
|
||||||
|
babelOptions: {
|
||||||
|
presets: ['@babel/preset-react']
|
||||||
|
},
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
jsx: true,
|
jsx: true,
|
||||||
modules: true,
|
modules: true,
|
||||||
@@ -23,7 +27,7 @@ module.exports = {
|
|||||||
'linebreak-style': ['error', 'unix'],
|
'linebreak-style': ['error', 'unix'],
|
||||||
quotes: ['warn', 'single'],
|
quotes: ['warn', 'single'],
|
||||||
semi: ['warn', 'always'],
|
semi: ['warn', 'always'],
|
||||||
'no-unused-vars' : 'warn',
|
'no-unused-vars': 'warn',
|
||||||
'comma-dangle': [
|
'comma-dangle': [
|
||||||
'warn',
|
'warn',
|
||||||
{
|
{
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,7 +1,7 @@
|
|||||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
|
|||||||
7144
package-lock.json
generated
7144
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@asseinfo/react-kanban": "2.2.0",
|
"@asseinfo/react-kanban": "2.2.0",
|
||||||
"@emotion/cache": "11.4.0",
|
"@emotion/cache": "11.4.0",
|
||||||
"@emotion/react": "11.4.1",
|
"@emotion/react": "^11.4.1",
|
||||||
"@emotion/styled": "11.3.0",
|
"@emotion/styled": "11.3.0",
|
||||||
"@fullcalendar/daygrid": "5.9.0",
|
"@fullcalendar/daygrid": "5.9.0",
|
||||||
"@fullcalendar/interaction": "5.9.0",
|
"@fullcalendar/interaction": "5.9.0",
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
"@zxing/library": "^0.18.5",
|
"@zxing/library": "^0.18.5",
|
||||||
"apisauce": "^2.1.5",
|
"apisauce": "^2.1.5",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"chart.js": "3.4.1",
|
"chart.js": "3.4.1",
|
||||||
"chroma-js": "2.1.2",
|
"chroma-js": "2.1.2",
|
||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
@@ -41,7 +40,6 @@
|
|||||||
"jsbarcode": "^3.11.5",
|
"jsbarcode": "^3.11.5",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"process": "^0.11.10",
|
|
||||||
"prop-types": "15.7.2",
|
"prop-types": "15.7.2",
|
||||||
"ramda": "^0.27.2",
|
"ramda": "^0.27.2",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
@@ -59,11 +57,9 @@
|
|||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
"reduxsauce": "^1.2.1",
|
"reduxsauce": "^1.2.1",
|
||||||
"seamless-immutable": "^7.1.4",
|
"seamless-immutable": "^7.1.4",
|
||||||
"stream": "^0.0.2",
|
|
||||||
"stylis": "4.0.10",
|
"stylis": "4.0.10",
|
||||||
"stylis-plugin-rtl": "2.1.0",
|
"stylis-plugin-rtl": "2.1.0",
|
||||||
"underscore": "^1.13.2",
|
"underscore": "^1.13.2",
|
||||||
"util": "^0.12.4",
|
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
"web-vitals": "1.0.1",
|
"web-vitals": "1.0.1",
|
||||||
"yup": "^0.32.11"
|
"yup": "^0.32.11"
|
||||||
@@ -104,7 +100,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.17.5",
|
||||||
"@babel/eslint-parser": "^7.17.0",
|
"@babel/eslint-parser": "^7.17.0",
|
||||||
|
"@babel/preset-react": "^7.16.7",
|
||||||
"eslint": "^8.2.0",
|
"eslint": "^8.2.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-prettier": "8.3.0",
|
"eslint-config-prettier": "8.3.0",
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ import PublicRoutes from 'routes/PublicRoutes';
|
|||||||
import reduxStore from './redux/Store';
|
import reduxStore from './redux/Store';
|
||||||
import { protectedRoutes as routes } from './routes/index';
|
import { protectedRoutes as routes } from './routes/index';
|
||||||
import PrivateRoute from './routes/PrivateRoute';
|
import PrivateRoute from './routes/PrivateRoute';
|
||||||
import MDAlert from 'components/MDAlert';
|
// import MDAlert from 'components/MDAlert';
|
||||||
|
|
||||||
import { ToastContainer } from 'react-toastify';
|
import { ToastContainer } from 'react-toastify';
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.css';
|
||||||
@@ -171,7 +171,7 @@ export default function App() {
|
|||||||
</Routes>
|
</Routes>
|
||||||
{/* <MDAlert dismissible><span>Submitted Successfully!</span></MDAlert> */}
|
{/* <MDAlert dismissible><span>Submitted Successfully!</span></MDAlert> */}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
<ToastContainer />
|
<ToastContainer position="bottom-right" />
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,12 +1,38 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const InventoryIcon = ({ width = 25, height = 24, ...props }) => (
|
const InventoryIcon = ({ width = '25', height = '25', ...props }) => (
|
||||||
<svg width={width} height={height} {...props} viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg
|
||||||
<path d="M37.24 58.7998L43.24 64.7998L59.24 48.7998" stroke="#007AFF" strokeWidth="5" strokeLinecap="round" strokeLinejoin="round"/>
|
width={width}
|
||||||
<path d="M40 24H56C64 24 64 20 64 16C64 8 60 8 56 8H40C36 8 32 8 32 16C32 24 36 24 40 24Z" stroke="#007AFF" strokeWidth="5" strokeMiterlimit="10" strokeLinecap="round" strokeLinejoin="round"/>
|
height={height}
|
||||||
<path d="M64 16.0801C77.32 16.8001 84 21.7201 84 40.0001V64.0001C84 80.0001 80 88.0001 60 88.0001H36C16 88.0001 12 80.0001 12 64.0001V40.0001C12 21.7601 18.68 16.8001 32 16.0801" stroke="#007AFF" strokeWidth="5" strokeMiterlimit="10" strokeLinecap="round" strokeLinejoin="round"/>
|
{...props}
|
||||||
|
viewBox="0 0 96 96"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M37.24 58.7998L43.24 64.7998L59.24 48.7998"
|
||||||
|
stroke="#007AFF"
|
||||||
|
strokeWidth="5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M40 24H56C64 24 64 20 64 16C64 8 60 8 56 8H40C36 8 32 8 32 16C32 24 36 24 40 24Z"
|
||||||
|
stroke="#007AFF"
|
||||||
|
strokeWidth="5"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M64 16.0801C77.32 16.8001 84 21.7201 84 40.0001V64.0001C84 80.0001 80 88.0001 60 88.0001H36C16 88.0001 12 80.0001 12 64.0001V40.0001C12 21.7601 18.68 16.8001 32 16.0801"
|
||||||
|
stroke="#007AFF"
|
||||||
|
strokeWidth="5"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
);
|
);
|
||||||
export default InventoryIcon;
|
export default InventoryIcon;
|
||||||
|
|
||||||
|
|||||||
BIN
src/assets/images/blank-profile-picture.webp
Normal file
BIN
src/assets/images/blank-profile-picture.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/images/fsr-logo.png
Normal file
BIN
src/assets/images/fsr-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/images/roofing-company-houston.jpg
Normal file
BIN
src/assets/images/roofing-company-houston.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
@@ -6,13 +6,13 @@ import TransferList from 'components/MDTransferList';
|
|||||||
import './AllocationManager.component.scss';
|
import './AllocationManager.component.scss';
|
||||||
|
|
||||||
const AllocationManager = props => {
|
const AllocationManager = props => {
|
||||||
const {boxStyleOverride, component, gridStyleOverride, initlist, list, matchProp, md, onChange, title, variant, xs} = props;
|
const {allDisabled, boxStyleOverride, component, gridStyleOverride, allocatedList, list, matchProp, md, onChange, title, variant, xs} = props;
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const [allocationStatus, setAllocationStatus] = useState();
|
const [allocationStatus, setAllocationStatus] = useState();
|
||||||
|
|
||||||
const handleAllocationChange = state => {
|
const handleAllocationChange = state => {
|
||||||
setAllocationStatus(state);
|
setAllocationStatus(state);
|
||||||
onChange && onChange(state.assigned?.map(obj => obj._id).join(','));
|
onChange && onChange(state.assigned);
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Grid item className='c-AllocationManager' xs={xs || 12} md={md || 6} sx={gridStyleOverride}>
|
return <Grid item className='c-AllocationManager' xs={xs || 12} md={md || 6} sx={gridStyleOverride}>
|
||||||
@@ -24,20 +24,22 @@ const AllocationManager = props => {
|
|||||||
padding: '12px',
|
padding: '12px',
|
||||||
borderRadius: '4px'
|
borderRadius: '4px'
|
||||||
})}
|
})}
|
||||||
|
className="h-100 d-flex flex-column"
|
||||||
>
|
>
|
||||||
<Typography gutterBottom variant={variant || 'h6'} component={component || 'div'}>
|
<Typography gutterBottom variant={variant || 'h6'} component={component || 'div'}>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<TransferList list={list || []} initlist={initlist} matchProp={matchProp} onChange={handleAllocationChange} />
|
<TransferList allDisabled={allDisabled} list={list || []} allocatedList={allocatedList} matchProp={matchProp} onChange={handleAllocationChange} />
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Grid>;
|
</Grid>;
|
||||||
};
|
};
|
||||||
|
|
||||||
AllocationManager.propTypes = {
|
AllocationManager.propTypes = {
|
||||||
|
allDisabled: PropTypes.bool,
|
||||||
boxStyleOverride: PropTypes.object,
|
boxStyleOverride: PropTypes.object,
|
||||||
component: PropTypes.string,
|
component: PropTypes.string,
|
||||||
gridStyleOverride: PropTypes.object,
|
gridStyleOverride: PropTypes.object,
|
||||||
initlist: PropTypes.oneOfType([
|
allocatedList: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.array
|
PropTypes.array
|
||||||
]),
|
]),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
// @mui material components
|
// @mui material components
|
||||||
import { Breadcrumbs as MuiBreadcrumbs, Grid, Toolbar } from '@mui/material';
|
import { Box, Breadcrumbs as MuiBreadcrumbs, Grid, Toolbar } from '@mui/material';
|
||||||
import ArrowRight from 'assets/images/CarretArrowRightIcon';
|
import ArrowRight from 'assets/images/CarretArrowRightIcon';
|
||||||
|
|
||||||
// Material Dashboard 2 PRO React components
|
// Material Dashboard 2 PRO React components
|
||||||
@@ -53,7 +53,8 @@ const buildBreadcrumbs = (route, light) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function Breadcrumbs({ route, light, children }) {
|
function Breadcrumbs({ title, route, children }) {
|
||||||
|
const light = false;
|
||||||
return (
|
return (
|
||||||
<Toolbar variant="dense">
|
<Toolbar variant="dense">
|
||||||
<MDBox
|
<MDBox
|
||||||
@@ -63,6 +64,19 @@ function Breadcrumbs({ route, light, children }) {
|
|||||||
// backgroundColor: '#fff'
|
// backgroundColor: '#fff'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{title && (
|
||||||
|
<Box
|
||||||
|
component="div"
|
||||||
|
sx={{
|
||||||
|
fontSize: '22px',
|
||||||
|
letterSpacing: '0.01em',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: '15px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
<Grid container spacing={2} alignItems="center">
|
<Grid container spacing={2} alignItems="center">
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<MuiBreadcrumbs
|
<MuiBreadcrumbs
|
||||||
@@ -86,15 +100,15 @@ function Breadcrumbs({ route, light, children }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting default values for the props of Breadcrumbs
|
// // Setting default values for the props of Breadcrumbs
|
||||||
Breadcrumbs.defaultProps = {
|
// Breadcrumbs.defaultProps = {
|
||||||
light: false
|
// light: false
|
||||||
};
|
// };
|
||||||
|
|
||||||
// Typechecking props for the Breadcrumbs
|
// Typechecking props for the Breadcrumbs
|
||||||
Breadcrumbs.propTypes = {
|
Breadcrumbs.propTypes = {
|
||||||
route: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired,
|
route: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired,
|
||||||
light: PropTypes.bool,
|
title: PropTypes.string,
|
||||||
children: PropTypes.node
|
children: PropTypes.node
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as React from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
@@ -6,11 +6,15 @@ import AdapterDateFns from '@mui/lab/AdapterDateFns';
|
|||||||
import LocalizationProvider from '@mui/lab/LocalizationProvider';
|
import LocalizationProvider from '@mui/lab/LocalizationProvider';
|
||||||
import DateTimePicker from '@mui/lab/DateTimePicker';
|
import DateTimePicker from '@mui/lab/DateTimePicker';
|
||||||
|
|
||||||
export default function DateTimeInput({ disabled }) {
|
export default function DateTimeInput({ disabled, value }) {
|
||||||
const [value, setValue] = React.useState(new Date());
|
const [date, setDate] = useState(value || new Date());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDate(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
const handleChange = (newValue) => {
|
const handleChange = (newValue) => {
|
||||||
setValue(newValue);
|
setDate(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -19,7 +23,7 @@ export default function DateTimeInput({ disabled }) {
|
|||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label=""
|
label=""
|
||||||
value={value}
|
value={date}
|
||||||
renderInput={(params) => <TextField {...params} />}
|
renderInput={(params) => <TextField {...params} />}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
@@ -29,5 +33,6 @@ export default function DateTimeInput({ disabled }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DateTimeInput.propTypes = {
|
DateTimeInput.propTypes = {
|
||||||
disabled: PropTypes.bool
|
disabled: PropTypes.bool,
|
||||||
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object])
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
// import InputLabel from '@mui/material/InputLabel'
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import FormControl from '@mui/material/FormControl';
|
import FormControl from '@mui/material/FormControl';
|
||||||
import Select from '@mui/material/Select';
|
import Select from '@mui/material/Select';
|
||||||
@@ -15,53 +13,32 @@ const useStyles = makeStyles({
|
|||||||
color: 'black'
|
color: 'black'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export default function Dropdown({ items, dropdownData }) {
|
|
||||||
|
export default function Dropdown({ dropdownData, label, onChange, value }) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const [age, setAge] = useState('');
|
|
||||||
const [dropDownValue, setDropDownValue] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setDropDownValue(items);
|
|
||||||
}, [items]);
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
const {
|
|
||||||
target: { value }
|
|
||||||
} = event;
|
|
||||||
setAge(
|
|
||||||
// On autofill we get a stringified value.
|
|
||||||
typeof value === 'string' ? value.split(',') : value
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
<InputLabel className={classes.font} id="demo-simple-select-label" sx={{ pb: 2, pt: 3 }}>
|
<InputLabel className={classes.font} id="demo-simple-select-label" sx={{ pb: 2, pt: 3 }}>
|
||||||
{dropDownValue?.label}
|
{label}
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<FormControl sx={{ width: '100%' }}>
|
<FormControl sx={{ width: '100%' }}>
|
||||||
<Select
|
<Select
|
||||||
displayEmpty
|
displayEmpty
|
||||||
input={<OutlinedInput />}
|
value={value}
|
||||||
value={age}
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (selected.length === 0) {
|
|
||||||
return <span>{dropDownValue?.placeholder}</span>;
|
|
||||||
}
|
|
||||||
return selected;
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
inputProps={{ 'aria-label': 'Without label' }}
|
||||||
onChange={handleChange}
|
onChange={onChange}
|
||||||
>
|
>
|
||||||
<MenuItem disabled value="">
|
<MenuItem disabled value="">
|
||||||
<span>{dropDownValue?.label}</span>
|
None selected
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{dropdownData && dropdownData.map((data) => (
|
{dropdownData &&
|
||||||
<MenuItem value={data.displayname} key={data.ID}>{data.displayname}</MenuItem>
|
dropdownData.map((data) => (
|
||||||
))}
|
<MenuItem value={data._id} key={data._id}>
|
||||||
|
{data.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -69,7 +46,8 @@ export default function Dropdown({ items, dropdownData }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Dropdown.propTypes = {
|
Dropdown.propTypes = {
|
||||||
items: PropTypes.object.isRequired,
|
dropdownData: PropTypes.array,
|
||||||
dropdownData: PropTypes.object.isRequired
|
onChange: PropTypes.any,
|
||||||
|
label: PropTypes.string,
|
||||||
|
value: PropTypes.any
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import TableHead from '@mui/material/TableHead';
|
|||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
import TablePagination from 'components/TablePagination';
|
import TablePagination from 'components/TablePagination';
|
||||||
import { Dialog, DialogActions, MenuItem, Select } from '@mui/material';
|
import { Grid, MenuItem, Select } from '@mui/material';
|
||||||
|
|
||||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
[`&.${tableCellClasses.head}`]: {
|
[`&.${tableCellClasses.head}`]: {
|
||||||
@@ -41,10 +41,11 @@ const StyledTableRow = styled(TableRow)(({ theme }) => ({
|
|||||||
Row.propTypes = {
|
Row.propTypes = {
|
||||||
rowData: PropTypes.array,
|
rowData: PropTypes.array,
|
||||||
tHeads: PropTypes.array,
|
tHeads: PropTypes.array,
|
||||||
editHandler: PropTypes.any
|
editHandler: PropTypes.any,
|
||||||
|
deleteHandler: PropTypes.any
|
||||||
};
|
};
|
||||||
|
|
||||||
function Row({ tHeads, rowData, editHandler }) {
|
function Row({ tHeads, rowData, editHandler, deleteHandler }) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<StyledTableRow sx={{ '&odd > *': { borderBottom: 'unset' } }}>
|
<StyledTableRow sx={{ '&odd > *': { borderBottom: 'unset' } }}>
|
||||||
@@ -68,6 +69,25 @@ function Row({ tHeads, rowData, editHandler }) {
|
|||||||
>
|
>
|
||||||
EDIT
|
EDIT
|
||||||
</MDButton>
|
</MDButton>
|
||||||
|
<MDButton
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
sx={{
|
||||||
|
textTransform: 'capitalize',
|
||||||
|
minWidth: '45px',
|
||||||
|
minHeight: '28px',
|
||||||
|
marginLeft: '10px',
|
||||||
|
boxShadow: 'none',
|
||||||
|
fontWeight: '500',
|
||||||
|
padding: '0'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
deleteHandler(rowData._id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
DELETE
|
||||||
|
</MDButton>
|
||||||
</StyledTableCell>
|
</StyledTableCell>
|
||||||
{tHeads &&
|
{tHeads &&
|
||||||
tHeads
|
tHeads
|
||||||
@@ -87,15 +107,10 @@ function EnhancedTable({
|
|||||||
data,
|
data,
|
||||||
tHeads,
|
tHeads,
|
||||||
editHandler,
|
editHandler,
|
||||||
|
deleteHandler,
|
||||||
filtersControl,
|
filtersControl,
|
||||||
resetFilters
|
resetFilters
|
||||||
}) {
|
}) {
|
||||||
const [filtersOpen, setFiltersOpen] = React.useState(false);
|
|
||||||
|
|
||||||
const handleFiltersClose = () => {
|
|
||||||
setFiltersOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@@ -106,7 +121,9 @@ function EnhancedTable({
|
|||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Grid
|
||||||
|
container
|
||||||
|
fullWidth
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -114,41 +131,15 @@ function EnhancedTable({
|
|||||||
padding: '16px'
|
padding: '16px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box>{/* <SearchBar /> */}</Box>
|
{/* <Box><SearchBar /></Box> */}
|
||||||
<Box sx={{ display: 'flex', columnGap: '15px' }}>
|
<Grid container item xs={12} spacing={5}>
|
||||||
<MDButton
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
sx={{
|
|
||||||
textTransform: 'capitalize',
|
|
||||||
minWidth: '60px',
|
|
||||||
minHeight: '44px',
|
|
||||||
fontWeight: '500'
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setFiltersOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Filter
|
|
||||||
</MDButton>
|
|
||||||
{filtersControl ? (
|
{filtersControl ? (
|
||||||
<Dialog open={filtersOpen} onClose={handleFiltersClose}>
|
<>
|
||||||
{filtersControl}
|
{filtersControl}
|
||||||
<DialogActions>
|
<Grid item sx={4}>
|
||||||
<MDButton onClick={resetFilters}>Reset Filters</MDButton>
|
<MDButton onClick={resetFilters}>Reset Filters</MDButton>
|
||||||
<MDButton
|
</Grid>
|
||||||
size="small"
|
</>
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setFiltersOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</MDButton>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
) : null}
|
) : null}
|
||||||
{/* <MDButton
|
{/* <MDButton
|
||||||
id="fade-button"
|
id="fade-button"
|
||||||
@@ -183,8 +174,8 @@ function EnhancedTable({
|
|||||||
<MenuItem>My account</MenuItem>
|
<MenuItem>My account</MenuItem>
|
||||||
<MenuItem>Logout</MenuItem>
|
<MenuItem>Logout</MenuItem>
|
||||||
</Menu> */}
|
</Menu> */}
|
||||||
</Box>
|
</Grid>
|
||||||
</Box>
|
</Grid>
|
||||||
{/* Table-row- */}
|
{/* Table-row- */}
|
||||||
<TableContainer component={Paper} sx={{ borderRadius: '0 !important', boxShadow: 'none' }}>
|
<TableContainer component={Paper} sx={{ borderRadius: '0 !important', boxShadow: 'none' }}>
|
||||||
<Table aria-label="collapsible table" sx={{ minWidth: 700 }}>
|
<Table aria-label="collapsible table" sx={{ minWidth: 700 }}>
|
||||||
@@ -202,6 +193,7 @@ function EnhancedTable({
|
|||||||
<Row
|
<Row
|
||||||
key={rowData._id}
|
key={rowData._id}
|
||||||
editHandler={editHandler}
|
editHandler={editHandler}
|
||||||
|
deleteHandler={deleteHandler}
|
||||||
rowData={rowData}
|
rowData={rowData}
|
||||||
tHeads={tHeads}
|
tHeads={tHeads}
|
||||||
/>
|
/>
|
||||||
@@ -334,6 +326,7 @@ EnhancedTable.propTypes = {
|
|||||||
data: PropTypes.array,
|
data: PropTypes.array,
|
||||||
tHeads: PropTypes.array,
|
tHeads: PropTypes.array,
|
||||||
editHandler: PropTypes.any,
|
editHandler: PropTypes.any,
|
||||||
|
deleteHandler: PropTypes.any,
|
||||||
filtersControl: PropTypes.any,
|
filtersControl: PropTypes.any,
|
||||||
resetFilters: PropTypes.any
|
resetFilters: PropTypes.any
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function ImageUploadSingle({ heading, accept, multiple, images, setImages }) {
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
minHeight: pxToRem(200),
|
height: pxToRem(250),
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@@ -72,14 +72,14 @@ function ImageUploadSingle({ heading, accept, multiple, images, setImages }) {
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
minHeight: pxToRem(200),
|
height: pxToRem(250),
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
marginBottom: '16px'
|
marginBottom: '16px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={images[0].src} alt="" width="100%" height="100%" />
|
<img src={images[0].src} alt="" height="100%" />
|
||||||
<Button
|
<Button
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: '#fff !important',
|
backgroundColor: '#fff !important',
|
||||||
|
|||||||
@@ -36,10 +36,14 @@ const useStyles = makeStyles({
|
|||||||
'& .MuiCheckbox-root': {
|
'& .MuiCheckbox-root': {
|
||||||
paddingLeft: '0px'
|
paddingLeft: '0px'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
maxHeight: '20rem',
|
||||||
|
overflow: 'auto'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function TransferList({list, initlist, matchProp, onChange}) {
|
export default function TransferList({allDisabled, list, allocatedList, matchProp, onChange}) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [checked, setChecked] = useState([]);
|
const [checked, setChecked] = useState([]);
|
||||||
const [left, setLeft] = useState(list || []);
|
const [left, setLeft] = useState(list || []);
|
||||||
@@ -49,14 +53,14 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
|
|||||||
const rightChecked = intersection(checked, right);
|
const rightChecked = intersection(checked, right);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initlist) {
|
if (typeof allocatedList === 'string') {
|
||||||
const initlistClone = typeof initlist === 'object' ? initlist : initlist.split(',');
|
const allocatedListClone = typeof allocatedList === 'object' ? allocatedList : allocatedList.split(',');
|
||||||
const left = notBy(matchProp, list, initlistClone);
|
const left = notBy(matchProp, list, allocatedListClone);
|
||||||
const right = intersectionBy(matchProp, list, initlistClone);
|
const right = intersectionBy(matchProp, list, allocatedListClone);
|
||||||
setLeft(left);
|
setLeft(left);
|
||||||
setRight(right);
|
setRight(right);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [allocatedList]);
|
||||||
|
|
||||||
const handleToggle = (value) => () => {
|
const handleToggle = (value) => () => {
|
||||||
const currentIndex = checked.indexOf(value);
|
const currentIndex = checked.indexOf(value);
|
||||||
@@ -106,13 +110,13 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const customList = items => (
|
const customList = items => (
|
||||||
<List component="div" role="list">
|
<List component="div" role="list" className={classes.maxHeight}>
|
||||||
{items.map((item, key) => {
|
{items.map((item, key) => {
|
||||||
const value = item.name;
|
const value = item.name;
|
||||||
const labelId = `transfer-list-item-${value}-label`;
|
const labelId = `transfer-list-item-${value}-label`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem button key={value + '-' + key} role="listitem" onClick={handleToggle(item)}>
|
<ListItem button disabled={allDisabled} key={value + '-' + key} role="listitem" onClick={handleToggle(item)}>
|
||||||
<ListItemIcon className={classes.unsetwidth}>
|
<ListItemIcon className={classes.unsetwidth}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
disableRipple
|
disableRipple
|
||||||
@@ -137,7 +141,7 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container className="flex-fill">
|
||||||
<Grid item md={5} className={classes.boxStyling}>
|
<Grid item md={5} className={classes.boxStyling}>
|
||||||
<Typography gutterBottom variant="caption" component="div">
|
<Typography gutterBottom variant="caption" component="div">
|
||||||
Unassigned
|
Unassigned
|
||||||
@@ -201,7 +205,8 @@ export default function TransferList({list, initlist, matchProp, onChange}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransferList.propTypes = {
|
TransferList.propTypes = {
|
||||||
initlist: PropTypes.oneOfType([
|
allDisabled: PropTypes.bool,
|
||||||
|
allocatedList: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.array
|
PropTypes.array
|
||||||
]),
|
]),
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
// Chip,
|
// Chip,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Grid,
|
Grid,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
@@ -64,6 +66,14 @@ function NestedDataTable({ data, selected, setSelected, populateChildren }) {
|
|||||||
populateChildren(data.id, data.location);
|
populateChildren(data.id, data.location);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
|
||||||
|
const handleDeleteAlertClose = () => {
|
||||||
|
setDeleteAlertOpen(false);
|
||||||
|
};
|
||||||
|
const handleDeleteAlertOpen = () => {
|
||||||
|
setDeleteAlertOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@@ -80,7 +90,7 @@ function NestedDataTable({ data, selected, setSelected, populateChildren }) {
|
|||||||
selected?.id === data.id
|
selected?.id === data.id
|
||||||
? 'linear-gradient(135deg, ' +
|
? 'linear-gradient(135deg, ' +
|
||||||
getColorOfLocationType(data.location) +
|
getColorOfLocationType(data.location) +
|
||||||
' 0%, #f9f9f9 20%)'
|
' 0%, #f9f9f9 100%)'
|
||||||
: '#f9f9f9'
|
: '#f9f9f9'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -154,18 +164,44 @@ function NestedDataTable({ data, selected, setSelected, populateChildren }) {
|
|||||||
padding: '0 6'
|
padding: '0 6'
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dispatch(
|
handleDeleteAlertOpen();
|
||||||
WarehouseLocationsActions.deleteLocationRequest({
|
|
||||||
loader: 'location-request',
|
|
||||||
slug: API.LOCATION_DELETE,
|
|
||||||
method: 'post',
|
|
||||||
data: { type: data.location, id: data.id }
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
DELETE
|
DELETE
|
||||||
</MDButton>
|
</MDButton>
|
||||||
|
<Dialog
|
||||||
|
open={deleteAlertOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleDeleteAlertClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Confirm Delete</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Are you sure you want to delete this?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleDeleteAlertClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(
|
||||||
|
WarehouseLocationsActions.deleteLocationRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: API.LOCATION_DELETE,
|
||||||
|
method: 'post',
|
||||||
|
data: { type: data.location, id: data.id }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
handleDeleteAlertClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
3
src/components/PwTablePanel/PwTablePanel.component.scss
Executable file
3
src/components/PwTablePanel/PwTablePanel.component.scss
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
.c-PwTablePanel {
|
||||||
|
|
||||||
|
}
|
||||||
79
src/components/PwTablePanel/PwTablePanel.jsx
Executable file
79
src/components/PwTablePanel/PwTablePanel.jsx
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import { TableBody, TableCell, TableRow } from '@mui/material';
|
||||||
|
import BasicTable from 'components/BasicTable';
|
||||||
|
import TabPanel from 'components/Tabs';
|
||||||
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
|
import './PwTablePanel.component.scss';
|
||||||
|
|
||||||
|
const PwTablePanel = props => {
|
||||||
|
const { backgroundColor, classes, color, dataFetched, headCells, id, loader, index, navUrl, records, table, value } = props;
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const StyledTableRow = styled(TableRow)(({ theme }) => ({
|
||||||
|
'&:nth-of-type(even)': {
|
||||||
|
backgroundColor: theme.palette.action.hover
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const rowRenders = ({ records, headers, navUrl, table }) => {
|
||||||
|
return records && records.map((record, keyouter) => {
|
||||||
|
return <StyledTableRow key={record.id + '-' + keyouter}>
|
||||||
|
{headers.map((columnConfig, key) => {
|
||||||
|
const canEdit = columnConfig.isEditAnchor;
|
||||||
|
const isAfter = columnConfig.placement && columnConfig.placement === 'after';
|
||||||
|
const limitWidth = columnConfig.limitWidth;
|
||||||
|
return <TableCell key={key} className={`${isAfter ? 'position-relative pe-5' : ''}${limitWidth ? ' overflow-auto ' + classes.limitWidth : ''}`}
|
||||||
|
onClick={() => canEdit && navigate(navUrl, { state: { [table]: record } })}>
|
||||||
|
{canEdit
|
||||||
|
? isAfter
|
||||||
|
? <span className={classes.iconwrap}>
|
||||||
|
{columnConfig.value(record)}
|
||||||
|
<EditIcon className={classes.iconSize + ' ' + classes.rightPlaced} />
|
||||||
|
</span>
|
||||||
|
: <span className={classes.iconwrap}>
|
||||||
|
<EditIcon className={classes.iconSize} />
|
||||||
|
{columnConfig.value(record)}
|
||||||
|
</span>
|
||||||
|
: <span>{columnConfig.value(record)}</span>}
|
||||||
|
</TableCell>;
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</StyledTableRow>;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return <TabPanel id={`c-PwTablePanel-${index}`} value={value} index={index} className={classes.radialBorder}>
|
||||||
|
<BasicTable
|
||||||
|
id={id}
|
||||||
|
headCells={headCells}
|
||||||
|
backgroundColor={backgroundColor || '#007AFF'}
|
||||||
|
color={color || '#fff'}
|
||||||
|
>
|
||||||
|
{records && records.length > 0 && <TableBody className={loader ? 'loader' : ''}>
|
||||||
|
{rowRenders({ records, headers: headCells, navUrl, table })}
|
||||||
|
</TableBody>}
|
||||||
|
</BasicTable>
|
||||||
|
{(dataFetched && (!records || records.length === 0))
|
||||||
|
&& <p className='mx-3 my-5 d-flex justify-content-center align-items-center h4'>No Records to Display</p>}
|
||||||
|
</TabPanel>;
|
||||||
|
};
|
||||||
|
|
||||||
|
PwTablePanel.propTypes = {
|
||||||
|
backgroundColor: PropTypes.string,
|
||||||
|
classes: PropTypes.string,
|
||||||
|
color: PropTypes.string,
|
||||||
|
dataFetched: PropTypes.bool,
|
||||||
|
headCells: PropTypes.array,
|
||||||
|
id: PropTypes.string,
|
||||||
|
index: PropTypes.number,
|
||||||
|
loader: PropTypes.bool,
|
||||||
|
navUrl: PropTypes.string,
|
||||||
|
records: PropTypes.array,
|
||||||
|
table: PropTypes.string,
|
||||||
|
value: PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PwTablePanel;
|
||||||
8
src/components/PwTablePanel/PwTablePanel.test.js
Executable file
8
src/components/PwTablePanel/PwTablePanel.test.js
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
import React from "react";
|
||||||
|
import PwTablePanel from "./PwTablePanel";
|
||||||
|
|
||||||
|
describe("PwTablePanel", () => {
|
||||||
|
it("renders without error", () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
3
src/components/PwTablePanel/index.js
Executable file
3
src/components/PwTablePanel/index.js
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
import PwTablePanel from "./PwTablePanel.jsx";
|
||||||
|
|
||||||
|
export default PwTablePanel;
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import { TextField, InputAdornment, SvgIcon } from '@mui/material';
|
import { TextField, InputAdornment, SvgIcon } from '@mui/material';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { makeStyles } from '@mui/styles';
|
import { makeStyles } from '@mui/styles';
|
||||||
import Search from 'assets/images/SearchIcon';
|
import Search from 'assets/images/SearchIcon';
|
||||||
|
|
||||||
function SearchBar() {
|
function SearchBar(props) {
|
||||||
|
const { onChange } = props;
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
textField: {
|
textField: {
|
||||||
@@ -30,8 +32,13 @@ function SearchBar() {
|
|||||||
}}
|
}}
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchBar.propTypes = {
|
||||||
|
onChange: PropTypes.func
|
||||||
|
};
|
||||||
export default SearchBar;
|
export default SearchBar;
|
||||||
|
|||||||
@@ -56,12 +56,13 @@ const IOSSwitch = styled((props) => (
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default function Switch({ checked, onChange, name }) {
|
export default function Switch({ disabled, checked, onChange, name }) {
|
||||||
return <IOSSwitch checked={checked} sx={{ m: 1 }} name={name} onChange={onChange} />;
|
return <IOSSwitch disabled={disabled} checked={checked} sx={{ m: 1 }} name={name} onChange={onChange} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
Switch.propTypes = {
|
Switch.propTypes = {
|
||||||
checked: PropTypes.any,
|
checked: PropTypes.any,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
name: PropTypes.any,
|
name: PropTypes.any,
|
||||||
onChange: PropTypes.any
|
onChange: PropTypes.any
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default function TileBasic({ tiles }) {
|
|||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{tiles &&
|
{tiles &&
|
||||||
tiles.map((item) => (
|
tiles.map((item) => (
|
||||||
<Grid item key={item.name} xs={12} sm={6} md={tiles.length > 4 ? 4 : 6}>
|
<Grid item key={item._id} xs={12} sm={6} md={tiles.length > 4 ? 4 : 6}>
|
||||||
{item.disabled ? (
|
{item.disabled ? (
|
||||||
<MDBox
|
<MDBox
|
||||||
key={item.name + item.path}
|
key={item.name + item.path}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function Tile({ data, children }) {
|
|||||||
Update {data.name} <ArrowRightIcon />
|
Update {data.name} <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={`/setup/inventory/new-item/${data.widgetname}/${data.id}`}>
|
<Link to={`/setup/inventory/new-item/${data.name}/${data.widgetname}/${data.id}`}>
|
||||||
<Box className={`${classes.box} ${classes.boxEven}`}>
|
<Box className={`${classes.box} ${classes.boxEven}`}>
|
||||||
Add New {data.widgetname} <ArrowRightIcon />
|
Add New {data.widgetname} <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
@@ -49,7 +49,7 @@ export default function Tile({ data, children }) {
|
|||||||
Cycle Count <ArrowRightIcon />
|
Cycle Count <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={`/setup/inventory/browse/${data.widgetname}/${data.id}`}>
|
<Link to={`/setup/inventory/browse/${data.name}/${data.widgetname}/${data.id}`}>
|
||||||
<Box className={`${classes.box} ${classes.boxEven}`}>
|
<Box className={`${classes.box} ${classes.boxEven}`}>
|
||||||
{data.widgetname} List <ArrowRightIcon />
|
{data.widgetname} List <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -17,26 +17,30 @@ const useStyles = makeStyles(() => ({
|
|||||||
'& .MuiSwitch-root': {
|
'& .MuiSwitch-root': {
|
||||||
margin: '0'
|
margin: '0'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
maxHeight: '20rem',
|
||||||
|
overflow: 'auto'
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Toggles = props => {
|
const Toggles = props => {
|
||||||
const {boxSx, inittoggles, md, onChange, title, toggles, typoComponent, typoSx, typoVariant, xs} = props;
|
const {allDisabled, boxSx, gridStyleOverride, selectedToggles, md, onChange, title, toggles, typoComponent, typoSx, typoVariant, xs} = props;
|
||||||
const [toggleState, updateToggleState] = useState({});
|
const [toggleState, updateToggleState] = useState({});
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inittoggles && typeof inittoggles === 'string') {
|
if (typeof selectedToggles === 'string') {
|
||||||
const initToggleState = {};
|
const selectedToggleState = {};
|
||||||
inittoggles.split(',').forEach(iToggle => initToggleState[iToggle] = true);
|
selectedToggles.split(',').forEach(iToggle => selectedToggleState[iToggle] = true);
|
||||||
updateToggleState(initToggleState);
|
updateToggleState(selectedToggleState);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [selectedToggles]);
|
||||||
|
|
||||||
const handleToggle = (e, toggle) => {
|
const handleToggle = (e, toggle) => {
|
||||||
const toggleStateClone = {...toggleState, [toggle]: e.target.checked};
|
const toggleStateClone = {...toggleState, [toggle]: e.target.checked};
|
||||||
updateToggleState(toggleStateClone);
|
updateToggleState(toggleStateClone);
|
||||||
onChange && onChange(Object.keys(toggleStateClone).join(','));
|
onChange && onChange(toggleStateClone);
|
||||||
};
|
};
|
||||||
|
|
||||||
const switchRenders = toggles => toggles && toggles.map((toggle, key) => {
|
const switchRenders = toggles => toggles && toggles.map((toggle, key) => {
|
||||||
@@ -45,24 +49,26 @@ const Toggles = props => {
|
|||||||
return <MDBox key={key} display='flex' justifyContent='space-between' alignItems='center' lineHeight={1} className={classes.switchSpacer}
|
return <MDBox key={key} display='flex' justifyContent='space-between' alignItems='center' lineHeight={1} className={classes.switchSpacer}
|
||||||
sx={{ marginBottom: '20px !important' }}>
|
sx={{ marginBottom: '20px !important' }}>
|
||||||
<MDTypography variant='body2'>{toggle}</MDTypography>
|
<MDTypography variant='body2'>{toggle}</MDTypography>
|
||||||
<Switch id={id} checked={toggleState[toggle] === undefined ? false : toggleState[toggle]} onChange={e => handleToggle(e, toggle)} />
|
<Switch disabled={allDisabled} id={id} checked={toggleState[toggle] === undefined ? false : toggleState[toggle]} onChange={e => handleToggle(e, toggle)} />
|
||||||
</MDBox>;
|
</MDBox>;
|
||||||
});
|
});
|
||||||
|
|
||||||
return <Grid item id='c-Toggles' xs={xs || 12} md={md || 3} >
|
return <Grid item className='c-Toggles' xs={xs || 12} md={md || 6} sx={gridStyleOverride}>
|
||||||
<MDBox sx={boxSx || {backgroundColor: '#fff', border: '1px solid #c2c2c2', borderTop: '7px solid #007aff', borderRadius: '4px'}}>
|
<MDBox sx={boxSx || {backgroundColor: '#fff', border: '1px solid #c2c2c2', borderTop: '7px solid #007aff', borderRadius: '4px'}}>
|
||||||
<Typography gutterBottom variant={typoVariant || 'h6'} component={typoComponent || 'div'}
|
<Typography gutterBottom variant={typoVariant || 'h6'} component={typoComponent || 'div'}
|
||||||
sx={typoSx || {borderBottom: '1px solid #c2c2c2', padding: '10px 20px', marginBottom: '20px'}}>
|
sx={typoSx || {borderBottom: '1px solid #c2c2c2', padding: '10px 20px', marginBottom: '20px'}}>
|
||||||
{title || 'Title'}
|
{title || 'Title'}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{ padding: ' 0px 20px' }}>{toggles && switchRenders(toggles)}</Box>
|
<Box sx={{ padding: ' 0px 20px' }} className={classes.maxHeight}>{toggles && switchRenders(toggles)}</Box>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Grid>;
|
</Grid>;
|
||||||
};
|
};
|
||||||
|
|
||||||
Toggles.propTypes = {
|
Toggles.propTypes = {
|
||||||
|
allDisabled: PropTypes.bool,
|
||||||
boxSx: PropTypes.object,
|
boxSx: PropTypes.object,
|
||||||
inittoggles: PropTypes.string,
|
gridStyleOverride: PropTypes.object,
|
||||||
|
selectedToggles: PropTypes.string,
|
||||||
md: PropTypes.number,
|
md: PropTypes.number,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Grid,
|
Grid,
|
||||||
TextField
|
TextField
|
||||||
@@ -116,6 +118,14 @@ function WidgetNestedDataTable({
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const widgetChildren = useSelector(WidgetSelectors.getWidgetsByParentId(data._id));
|
const widgetChildren = useSelector(WidgetSelectors.getWidgetsByParentId(data._id));
|
||||||
|
|
||||||
|
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
|
||||||
|
const handleDeleteAlertClose = () => {
|
||||||
|
setDeleteAlertOpen(false);
|
||||||
|
};
|
||||||
|
const handleDeleteAlertOpen = () => {
|
||||||
|
setDeleteAlertOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@@ -193,19 +203,45 @@ function WidgetNestedDataTable({
|
|||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelected(null);
|
setSelected(null);
|
||||||
dispatch(
|
handleDeleteAlertOpen();
|
||||||
WidgetActions.editWidgetRequest({
|
|
||||||
loader: 'location-request',
|
|
||||||
slug: `${API.EDIT_WIDGET_FAMILY}${data._id}`,
|
|
||||||
deletedId: data._id,
|
|
||||||
method: 'delete',
|
|
||||||
type: 'delete'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
DELETE
|
DELETE
|
||||||
</MDButton>
|
</MDButton>
|
||||||
|
<Dialog
|
||||||
|
open={deleteAlertOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleDeleteAlertClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Confirm Delete</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Are you sure you want to delete this?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleDeleteAlertClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(
|
||||||
|
WidgetActions.editWidgetRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: `${API.EDIT_WIDGET_FAMILY}${data._id}`,
|
||||||
|
deletedId: data._id,
|
||||||
|
method: 'delete',
|
||||||
|
type: 'delete'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
handleDeleteAlertClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{open && widgetChildren ? (
|
{open && widgetChildren ? (
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/* PLOP_INJECT_IMPORT */
|
/* PLOP_INJECT_IMPORT */
|
||||||
|
import PwTablePanel from './PwTablePanel';
|
||||||
import Toggles from './Toggles';
|
import Toggles from './Toggles';
|
||||||
import AllocationManager from './AllocationManager';
|
import AllocationManager from './AllocationManager';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
/* PLOP_INJECT_EXPORT */
|
/* PLOP_INJECT_EXPORT */
|
||||||
|
PwTablePanel,
|
||||||
Toggles,
|
Toggles,
|
||||||
AllocationManager
|
AllocationManager
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,5 +24,7 @@ export default {
|
|||||||
GET_WIDGET_FAMILY_BY_INVENTORY: '/widget-family/search-by-inventory?inventory=',
|
GET_WIDGET_FAMILY_BY_INVENTORY: '/widget-family/search-by-inventory?inventory=',
|
||||||
ADD_WIDGET_FAMILY: '/widget-family',
|
ADD_WIDGET_FAMILY: '/widget-family',
|
||||||
EDIT_WIDGET_FAMILY: '/widget-family/',
|
EDIT_WIDGET_FAMILY: '/widget-family/',
|
||||||
|
GET_LABEL: '/sublevel/filter',
|
||||||
|
GET_PRODUCT_BY_ID: '/item/filter?inventory=',
|
||||||
GET_ITEMS_BY_INVENTORY: '/item/filter?inventory='
|
GET_ITEMS_BY_INVENTORY: '/item/filter?inventory='
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,32 @@
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { AuthSelectors } from 'redux/AuthRedux';
|
import { AuthSelectors } from 'redux/AuthRedux';
|
||||||
import { decode } from 'jsonwebtoken';
|
// import { decode } from 'jsonwebtoken';
|
||||||
import LOGGER from 'services/Logger';
|
import LOGGER from 'services/Logger';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import AuthActions from 'redux/AuthRedux';
|
import AuthActions from 'redux/AuthRedux';
|
||||||
|
|
||||||
|
function decode(token) {
|
||||||
|
var base64Url = token.split('.')[1];
|
||||||
|
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
||||||
|
var jsonPayload = decodeURIComponent(
|
||||||
|
atob(base64)
|
||||||
|
.split('')
|
||||||
|
.map(function (c) {
|
||||||
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||||
|
})
|
||||||
|
.join('')
|
||||||
|
);
|
||||||
|
|
||||||
|
return JSON.parse(jsonPayload);
|
||||||
|
}
|
||||||
|
|
||||||
const useAuthentication = () => {
|
const useAuthentication = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const user = useSelector(AuthSelectors.getUser);
|
const user = useSelector(AuthSelectors.getUser);
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
try {
|
try {
|
||||||
const { exp } = decode(token);
|
const decodedToken = token && decode(token);
|
||||||
if (exp < (new Date().getTime() + 1) / 1000) {
|
if (!token || decodedToken.exp < (new Date().getTime() + 1) / 1000) {
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
dispatch(AuthActions.logout());
|
dispatch(AuthActions.logout());
|
||||||
@@ -22,7 +37,6 @@ const useAuthentication = () => {
|
|||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
dispatch(AuthActions.logout());
|
dispatch(AuthActions.logout());
|
||||||
return { isAuthenticated: false };
|
|
||||||
}
|
}
|
||||||
return { isAuthenticated: !!user };
|
return { isAuthenticated: !!user };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
import './main.css';
|
||||||
import App from 'App';
|
import App from 'App';
|
||||||
|
|
||||||
// Soft UI Context Provider
|
// Soft UI Context Provider
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import PageLayout from 'layouts/PageLayout';
|
|||||||
// Material Dashboard 2 PRO React context
|
// Material Dashboard 2 PRO React context
|
||||||
import { useMaterialUIController } from 'context';
|
import { useMaterialUIController } from 'context';
|
||||||
|
|
||||||
|
import companyImage from 'assets/images/fsr-logo.png';
|
||||||
|
|
||||||
function AuthLayout({ header, title, description, illustration, children }) {
|
function AuthLayout({ header, title, description, illustration, children }) {
|
||||||
const [controller] = useMaterialUIController();
|
const [controller] = useMaterialUIController();
|
||||||
const { darkMode } = controller;
|
const { darkMode } = controller;
|
||||||
@@ -34,12 +36,30 @@ function AuthLayout({ header, title, description, illustration, children }) {
|
|||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
ml={2}
|
ml={2}
|
||||||
mt={2}
|
mt={2}
|
||||||
sx={{ backgroundImage: `url(${illustration})` }}
|
sx={{
|
||||||
|
backgroundImage: `url(${illustration})`,
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center'
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={11} sm={8} md={6} lg={4} xl={3} sx={{ mx: 'auto' }}>
|
<Grid item xs={11} sm={8} md={6} lg={4} xl={3} sx={{ mx: 'auto' }}>
|
||||||
<MDBox display="flex" flexDirection="column" justifyContent="center" height="100vh">
|
<MDBox display="flex" flexDirection="column" justifyContent="center" height="100vh">
|
||||||
<MDBox py={3} px={3} textAlign="center">
|
<MDBox py={3} px={3} textAlign="center">
|
||||||
|
<MDBox
|
||||||
|
display={{ xs: 'none', lg: 'flex' }}
|
||||||
|
width="350px"
|
||||||
|
height="117px"
|
||||||
|
borderRadius="lg"
|
||||||
|
ml={2}
|
||||||
|
my={5}
|
||||||
|
sx={{
|
||||||
|
backgroundImage: `url(${companyImage})`,
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{!header ? (
|
{!header ? (
|
||||||
<>
|
<>
|
||||||
<MDBox mb={1} textAlign="center">
|
<MDBox mb={1} textAlign="center">
|
||||||
|
|||||||
67
src/main.css
Normal file
67
src/main.css
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
fieldset legend {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader:before {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: url("./assets/images/favicon.png");
|
||||||
|
background-size: 3rem;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-animation: rotating 2s linear infinite;
|
||||||
|
-moz-animation: rotating 2s linear infinite;
|
||||||
|
-ms-animation: rotating 2s linear infinite;
|
||||||
|
-o-animation: rotating 2s linear infinite;
|
||||||
|
animation: rotating 2s linear infinite;
|
||||||
|
z-index: 1050;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader:after {
|
||||||
|
content: "";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1040;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes rotating {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
-o-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotateY(360deg);
|
||||||
|
-o-transform: rotateY(360deg);
|
||||||
|
transform: rotateY(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotating {
|
||||||
|
from {
|
||||||
|
-ms-transform: rotate(0deg);
|
||||||
|
-moz-transform: rotate(0deg);
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
-o-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
-ms-transform: rotateY(360deg);
|
||||||
|
-moz-transform: rotateY(360deg);
|
||||||
|
-webkit-transform: rotateY(360deg);
|
||||||
|
-o-transform: rotateY(360deg);
|
||||||
|
transform: rotateY(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ const useStyles = makeStyles({
|
|||||||
|
|
||||||
function AddNewItem() {
|
function AddNewItem() {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { widgetName, inventoryId, itemId } = useParams();
|
const { widgetName, inventoryName, inventoryId, itemId } = useParams();
|
||||||
const getInitialFormValues = (data) => {
|
const getInitialFormValues = (data) => {
|
||||||
return data && data._id === itemId
|
return data && data._id === itemId
|
||||||
? {
|
? {
|
||||||
@@ -135,10 +135,6 @@ function AddNewItem() {
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [pFam, setPFam] = React.useState(null);
|
|
||||||
const primaryFamily = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
|
||||||
const secondaryFamily = useSelector(WidgetSelectors.getWidgetsByParentId(pFam));
|
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: itemData,
|
initialValues: itemData,
|
||||||
@@ -217,17 +213,23 @@ function AddNewItem() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const primaryFamily = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||||
|
const secondaryFamily = useSelector(
|
||||||
|
WidgetSelectors.getWidgetsByParentId(formik.values.primaryWidgetFamilyId)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title={`${widgetName} Details`}
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
{ name: 'Inventory', path: '/setup/inventory' },
|
{ name: 'Inventory', path: '/setup/inventory' },
|
||||||
{ name: `${widgetName || 'Item'}` },
|
{ name: `${inventoryName || 'Inventory'}` },
|
||||||
{ name: `Add New ${widgetName || 'Item'}` }
|
{ name: `${itemId ? 'Edit' : 'Add'} ${widgetName || 'Item'}` }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Box mx={3} my={3}>
|
<Box mx={3} my={3}>
|
||||||
@@ -246,7 +248,12 @@ function AddNewItem() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.commonName}
|
value={formik.values.commonName}
|
||||||
error={formik.touched.commonName && Boolean(formik.errors.commonName)}
|
error={formik.touched.commonName && Boolean(formik.errors.commonName)}
|
||||||
helperText={formik.touched.commonName && formik.errors.commonName}
|
helperText={
|
||||||
|
formik.touched.commonName &&
|
||||||
|
formik.errors.commonName && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.commonName}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -341,7 +348,12 @@ function AddNewItem() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.formalName}
|
value={formik.values.formalName}
|
||||||
error={formik.touched.formalName && Boolean(formik.errors.formalName)}
|
error={formik.touched.formalName && Boolean(formik.errors.formalName)}
|
||||||
helperText={formik.touched.formalName && formik.errors.formalName}
|
helperText={
|
||||||
|
formik.touched.formalName &&
|
||||||
|
formik.errors.formalName && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.formalName}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -440,10 +452,7 @@ function AddNewItem() {
|
|||||||
formik.touched.primaryWidgetFamilyId &&
|
formik.touched.primaryWidgetFamilyId &&
|
||||||
Boolean(formik.errors.primaryWidgetFamilyId)
|
Boolean(formik.errors.primaryWidgetFamilyId)
|
||||||
}
|
}
|
||||||
onChange={(e, ...rest) => {
|
onChange={formik.handleChange}
|
||||||
setPFam(e.target.value);
|
|
||||||
formik.handleChange(e, ...rest);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<MenuItem key={'none'} value={''}>
|
<MenuItem key={'none'} value={''}>
|
||||||
None Selected
|
None Selected
|
||||||
@@ -497,7 +506,7 @@ function AddNewItem() {
|
|||||||
{itemId ? (
|
{itemId ? (
|
||||||
<ImageUploadMultiple
|
<ImageUploadMultiple
|
||||||
multiple
|
multiple
|
||||||
heading="Upload Product Image"
|
heading={`Upload ${widgetName} Image`}
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
images={formik.values.images}
|
images={formik.values.images}
|
||||||
setImages={(images) => {
|
setImages={(images) => {
|
||||||
@@ -507,7 +516,7 @@ function AddNewItem() {
|
|||||||
) : (
|
) : (
|
||||||
<ImageUploadMultiple
|
<ImageUploadMultiple
|
||||||
multiple
|
multiple
|
||||||
heading="Upload Product Image"
|
heading={`Upload ${widgetName} Image`}
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
images={formik.values.images}
|
images={formik.values.images}
|
||||||
setImages={(images) => {
|
setImages={(images) => {
|
||||||
@@ -516,7 +525,7 @@ function AddNewItem() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
{/* <Box
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@@ -539,7 +548,7 @@ function AddNewItem() {
|
|||||||
<MDButton disabled size="large" color="primary" variant="outlined">
|
<MDButton disabled size="large" color="primary" variant="outlined">
|
||||||
import
|
import
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Box>
|
</Box> */}
|
||||||
<Box
|
<Box
|
||||||
component="div"
|
component="div"
|
||||||
sx={{
|
sx={{
|
||||||
@@ -614,11 +623,18 @@ function AddNewItem() {
|
|||||||
marginBottom: '30px'
|
marginBottom: '30px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MDButton size="medium" color="error" variant="outlined">
|
<MDButton
|
||||||
|
size="medium"
|
||||||
|
color="error"
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => {
|
||||||
|
navigate('/setup/inventory');
|
||||||
|
}}
|
||||||
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
||||||
Add {widgetName}
|
Save
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import AuthActions from 'redux/AuthRedux';
|
|||||||
import { API } from 'constant';
|
import { API } from 'constant';
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
import bgImage from 'assets/images/illustrations/illustration-reset.jpg';
|
import bgImage from 'assets/images/roofing-company-houston.jpg';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
|
|
||||||
import schema from 'services/ValidationServices';
|
import schema from 'services/ValidationServices';
|
||||||
@@ -35,8 +35,7 @@ function LoginScreen() {
|
|||||||
rememberMe: true
|
rememberMe: true
|
||||||
},
|
},
|
||||||
validationSchema: schema.login,
|
validationSchema: schema.login,
|
||||||
onSubmit: (values, { resetForm, setSubmitting }) =>
|
onSubmit: (values, { resetForm, setSubmitting }) => {
|
||||||
{
|
|
||||||
const onFailedLogin = (errorMessage) => {
|
const onFailedLogin = (errorMessage) => {
|
||||||
resetForm();
|
resetForm();
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import WarehouseActions, { WarehouseSelectors } from 'redux/WarehouseRedux';
|
|||||||
import InventoryActions, { InventorySelectors } from 'redux/InventoryRedux';
|
import InventoryActions, { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
|
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
|
||||||
import PermissionsActions, { PermissionsSelectors } from 'redux/PermissionsRedux';
|
import PermissionsActions, { PermissionsSelectors } from 'redux/PermissionsRedux';
|
||||||
import { AuthSelectors } from 'redux/AuthRedux';
|
// import { AuthSelectors } from 'redux/AuthRedux';
|
||||||
import UsersActions from 'redux/UsersRedux';
|
import UsersActions from 'redux/UsersRedux';
|
||||||
|
|
||||||
import schema from 'services/ValidationServices';
|
import schema from 'services/ValidationServices';
|
||||||
@@ -29,8 +29,9 @@ import DateTimeInput from 'components/DateTimePicker';
|
|||||||
import MDInput from 'components/MDInput';
|
import MDInput from 'components/MDInput';
|
||||||
|
|
||||||
import { API } from 'constant';
|
import { API } from 'constant';
|
||||||
import UserIcon from 'assets/images/userIcon.png';
|
import BlankImage from 'assets/images/blank-profile-picture.webp';
|
||||||
import EditIcon from 'assets/images/edit-icon.png';
|
import EditIcon from 'assets/images/edit-icon.png';
|
||||||
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
labelSize: {
|
labelSize: {
|
||||||
@@ -72,11 +73,14 @@ function CreateEditUser(props) {
|
|||||||
const warehouses = useSelector(WarehouseSelectors.getWarehouseDetail);
|
const warehouses = useSelector(WarehouseSelectors.getWarehouseDetail);
|
||||||
const inventories = useSelector(InventorySelectors.getInventoryDetail);
|
const inventories = useSelector(InventorySelectors.getInventoryDetail);
|
||||||
const actions = useSelector(PermissionsSelectors.getActionsDetail);
|
const actions = useSelector(PermissionsSelectors.getActionsDetail);
|
||||||
const permissions = useSelector(PermissionsSelectors.getPermissionsDetail);
|
const visibilities = useSelector(PermissionsSelectors.getPermissionsDetail);
|
||||||
const currentUser = useSelector(AuthSelectors.getUser);
|
// const currentUser = useSelector(AuthSelectors.getUser);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [editedUser, setEditedUser] = useState(location?.state?.user);
|
const [editedUser, setEditedUser] = useState(location?.state?.user);
|
||||||
const [selectedRoles, setSelectedRoles] = useState([]);
|
const [selectedRoles, setSelectedRoles] = useState([]);
|
||||||
|
const [uploadedImg, setUploadedImg] = useState();
|
||||||
|
const [loader, setLoader] = useState();
|
||||||
|
// const [selectedPermissions, setSelectedPermissions] = useState({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (context === 'edit') {
|
if (context === 'edit') {
|
||||||
@@ -86,16 +90,52 @@ function CreateEditUser(props) {
|
|||||||
} else {
|
} else {
|
||||||
setEditedUser(editedUser);
|
setEditedUser(editedUser);
|
||||||
setSelectedRoles(editedUser.roles);
|
setSelectedRoles(editedUser.roles);
|
||||||
|
editedUser.image_url && setUploadedImg(editedUser.image_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(!warehouses || warehouses.length === 0) && dispatch(WarehouseActions.warehouseDataAction({loader: 'loading-request', slug: API.GET_WAREHOUSE_DATA,method: 'get'}));
|
(!warehouses || warehouses.length === 0) &&
|
||||||
(!inventories || inventories.length === 0) && dispatch(InventoryActions.getInventoryAction({loader: 'loading-request', slug: API.GET_INVENTORY,method: 'get'}));
|
dispatch(
|
||||||
(!roles || roles.length === 0) && dispatch(RolesActions.getRolesAction({loader: 'loading-request', slug: API.GET_ROLES_DATA, method: 'get'}));
|
WarehouseActions.warehouseDataAction({
|
||||||
(!permissions || permissions.length === 0) && dispatch(PermissionsActions.getPermissionsAction({loader: 'loading-request', slug: API.GET_PERMISSIONS_DATA, method: 'get'}));
|
loader: 'loading-request',
|
||||||
(!actions || actions.length === 0) && dispatch(PermissionsActions.getActionsAction({loader: 'loading-request', slug: API.GET_ACTIONS_DATA, method: 'get'}));
|
slug: API.GET_WAREHOUSE_DATA,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
(!inventories || inventories.length === 0) &&
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
(!visibilities || visibilities.length === 0) &&
|
||||||
|
dispatch(
|
||||||
|
PermissionsActions.getPermissionsAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_PERMISSIONS_DATA,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
(!actions || actions.length === 0) &&
|
||||||
|
dispatch(
|
||||||
|
PermissionsActions.getActionsAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_ACTIONS_DATA,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -110,10 +150,11 @@ function CreateEditUser(props) {
|
|||||||
actions: '',
|
actions: '',
|
||||||
visibilities: '',
|
visibilities: '',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
createdBy: currentUser ? currentUser.fullName : '',
|
image: '',
|
||||||
createdAt: new Date(),
|
createdBy: '',
|
||||||
updatedBy: currentUser ? currentUser.fullName : '',
|
createdAt: '',
|
||||||
updatedAt: new Date()
|
updatedBy: '',
|
||||||
|
updatedAt: ''
|
||||||
} : {
|
} : {
|
||||||
fullName: editedUser ? editedUser.fullName : '',
|
fullName: editedUser ? editedUser.fullName : '',
|
||||||
phoneNumber: editedUser ? editedUser.phoneNumber : '',
|
phoneNumber: editedUser ? editedUser.phoneNumber : '',
|
||||||
@@ -125,108 +166,207 @@ function CreateEditUser(props) {
|
|||||||
actions: editedUser?.permissions?.actions ? editedUser.permissions.actions.join(',') : '',
|
actions: editedUser?.permissions?.actions ? editedUser.permissions.actions.join(',') : '',
|
||||||
visibilities: editedUser?.permissions?.allowedUIModules ? editedUser.permissions.allowedUIModules.join(',') : '',
|
visibilities: editedUser?.permissions?.allowedUIModules ? editedUser.permissions.allowedUIModules.join(',') : '',
|
||||||
isActive: editedUser && editedUser.isActive !== undefined ? editedUser.isActive : true,
|
isActive: editedUser && editedUser.isActive !== undefined ? editedUser.isActive : true,
|
||||||
|
image: editedUser ? editedUser.image_url : EditIcon,
|
||||||
createdBy: editedUser ? editedUser.createdBy?.fullName : '',
|
createdBy: editedUser ? editedUser.createdBy?.fullName : '',
|
||||||
createdAt: editedUser ? editedUser.createdAt : '',
|
createdAt: editedUser ? editedUser.createdAt : '',
|
||||||
updatedBy: editedUser ? editedUser.updatedBy?.fullName : '',
|
updatedBy: editedUser ? editedUser.updatedBy?.fullName : '',
|
||||||
updatedAt: editedUser ? editedUser.updatedAt : ''
|
updatedAt: editedUser ? editedUser.updatedAt : ''
|
||||||
},
|
},
|
||||||
validationSchema: schema.createUser,
|
validationSchema: schema.createUser,
|
||||||
onSubmit: (values, { setSubmitting }) =>
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
{
|
|
||||||
const onValidationFailed = () => {
|
const onValidationFailed = () => {
|
||||||
|
setLoader(false);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
const onSuccessfulSubmission = () => {
|
const onSuccessfulSubmission = () => {
|
||||||
|
setLoader(false);
|
||||||
navigate('/setup/users-access');
|
navigate('/setup/users-access');
|
||||||
};
|
};
|
||||||
const adaptPayload = values => {
|
const adaptPayload = (values) => {
|
||||||
const valuesClone = {...values};
|
const valuesClone = { ...values };
|
||||||
valuesClone.permissions = {};
|
valuesClone.permissions = {};
|
||||||
valuesClone.permissions.inventoryScopes = values.inventories ? values.inventories.split(',').map(inv => ({id: inv, type: 'Inventory'})) : [];
|
valuesClone.permissions.inventoryScopes = values.inventories
|
||||||
valuesClone.permissions.warehouseScopes = values.warehouses ? values.warehouses.split(',').map(wh => ({id: wh, type: 'Warehouse'})) : [];
|
? values.inventories.split(',').map((inv) => ({ id: inv, type: 'Inventory' }))
|
||||||
|
: [];
|
||||||
|
valuesClone.permissions.warehouseScopes = values.warehouses
|
||||||
|
? values.warehouses.split(',').map((wh) => ({ id: wh, type: 'Warehouse' }))
|
||||||
|
: [];
|
||||||
valuesClone.permissions.actions = values.actions ? values.actions.split(',') : [];
|
valuesClone.permissions.actions = values.actions ? values.actions.split(',') : [];
|
||||||
valuesClone.permissions.allowedUIModules = values.visibilities ? values.visibilities.split(',') : [];
|
valuesClone.permissions.allowedUIModules = values.visibilities
|
||||||
|
? values.visibilities.split(',')
|
||||||
|
: [];
|
||||||
delete valuesClone.inventories;
|
delete valuesClone.inventories;
|
||||||
delete valuesClone.warehouses;
|
delete valuesClone.warehouses;
|
||||||
delete valuesClone.actions;
|
delete valuesClone.actions;
|
||||||
delete valuesClone.visibilities;
|
delete valuesClone.visibilities;
|
||||||
return valuesClone;
|
valuesClone.permissions = JSON.stringify(valuesClone.permissions);
|
||||||
|
valuesClone.roles = selectedRoles && selectedRoles.length > 0 ? selectedRoles.map(role => role._id) : [];
|
||||||
|
const formData = new FormData();
|
||||||
|
Object.keys(valuesClone).forEach(key => formData.append(key, valuesClone[key]));
|
||||||
|
uploadedImg && formData.append('image', uploadedImg);
|
||||||
|
setLoader(true);
|
||||||
|
return formData;
|
||||||
};
|
};
|
||||||
values.roles = selectedRoles && selectedRoles.length > 0 ? selectedRoles.map(role => role._id) : [];
|
|
||||||
dispatch(
|
dispatch(
|
||||||
UsersActions.createUserAction({
|
UsersActions.createUserAction({
|
||||||
loader: 'loading-request',
|
loader: 'loading-request',
|
||||||
slug: context === 'edit' ? API.UPDATE_USER.replace(':id', editedUser._id): API.CREATE_USER,
|
slug:
|
||||||
|
context === 'edit' ? API.UPDATE_USER.replace(':id', editedUser._id) : API.CREATE_USER,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
data: adaptPayload(values),
|
data: adaptPayload(values),
|
||||||
onValidationFailed,
|
onValidationFailed,
|
||||||
onSuccessfulSubmission,
|
onSuccessfulSubmission,
|
||||||
toastMessage: context === 'edit' ? 'Updated user __placeholder__successfully' : 'Added user __placeholder__successfully'
|
toastMessage:
|
||||||
|
context === 'edit'
|
||||||
|
? 'Updated user __placeholder__successfully'
|
||||||
|
: 'Added user __placeholder__successfully'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleMultiSelectChange = e => {
|
const handleMultiSelectChange = (e) => {
|
||||||
const uniqueRoles = [];
|
const uniqueRoles = [];
|
||||||
e.target.value.forEach(role => {
|
e.target.value.forEach((role) => {
|
||||||
const roleIndex = uniqueRoles.findIndex(uRole => uRole._id === role._id);
|
const roleIndex = uniqueRoles.findIndex((uRole) => uRole._id === role._id);
|
||||||
if (roleIndex > -1) {
|
if (roleIndex > -1) {
|
||||||
uniqueRoles.splice(roleIndex, 1);
|
uniqueRoles.splice(roleIndex, 1);
|
||||||
} else {
|
} else {
|
||||||
uniqueRoles.push(role);
|
uniqueRoles.push(role);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
formik.handleChange('roles')(uniqueRoles.map(role => role.name).join());
|
formik.handleChange('roles')(uniqueRoles.map((role) => role.name).join());
|
||||||
|
aggregatePermissions(uniqueRoles);
|
||||||
setSelectedRoles(uniqueRoles);
|
setSelectedRoles(uniqueRoles);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const aggregatePermissions = roles => {
|
||||||
|
const actions = [], visibilities = [], warehouses = [], inventories = [];
|
||||||
|
roles.forEach(role => {
|
||||||
|
if (role.permissions) {
|
||||||
|
const currActions = role.permissions.actions;
|
||||||
|
const currVisibilities = role.permissions.allowedUIModules;
|
||||||
|
const currWarehouseScopes = role.permissions.warehouseScopes;
|
||||||
|
const currInventoryScopes = role.permissions.inventoryScopes;
|
||||||
|
currActions.forEach(ac => actions.indexOf(ac) === -1 && actions.push(ac));
|
||||||
|
currVisibilities.forEach(vi => visibilities.indexOf(vi) === -1 && visibilities.push(vi));
|
||||||
|
currWarehouseScopes.forEach(currWh => warehouses.findIndex(wh => wh.id === currWh.id) === -1 && warehouses.push(currWh));
|
||||||
|
currInventoryScopes.forEach(currInv => inventories.findIndex(inv => inv.id === currInv.id) === -1 && inventories.push(currInv));
|
||||||
|
// setSelectedPermissions({...selectedPermissions, actions});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formik.handleChange('actions')(actions.join(','));
|
||||||
|
formik.handleChange('visibilities')(visibilities.join(','));
|
||||||
|
formik.handleChange('warehouses')(warehouses.map(wh => wh.id).join(','));
|
||||||
|
formik.handleChange('inventories')(inventories.map(inv => inv.id).join(','));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = e => {
|
||||||
|
const [file] = e.target.files;
|
||||||
|
if (file) {
|
||||||
|
setUploadedImg(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout className={classes.createEditUserGlobal}>
|
<DashboardLayout className={classes.createEditUserGlobal}>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<MDBox component='form' role='form' px={2} sx={{ backgroundColor: '#fff' }} onSubmit={formik.handleSubmit}>
|
<Breadcrumbs
|
||||||
<MDBox mx={4} sx={{ border: '1px solid #C4C4C4', borderRadius: '4px', padding: '30px' }}>
|
title="User Details"
|
||||||
|
route={[
|
||||||
|
{ name: 'Home', path: '/home' },
|
||||||
|
{ name: 'Setup', path: '/setup' },
|
||||||
|
{ name: 'User Access', path: '/setup/users-access' },
|
||||||
|
{ name: 'User Details' }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<MDBox component="form" role="form" px={2} className={loader ? " loader" : ""} onSubmit={formik.handleSubmit}>
|
||||||
|
<MDBox
|
||||||
|
mx={4}
|
||||||
|
sx={{
|
||||||
|
border: '1px solid #C4C4C4',
|
||||||
|
borderRadius: '4px',
|
||||||
|
padding: '30px',
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<MDBox sx={{ width: '50%', margin: 'auto' }}>
|
<MDBox sx={{ width: '50%', margin: 'auto' }}>
|
||||||
<MDBox sx={{ width: '120px', margin: 'auto', position: 'relative' }}>
|
<MDBox sx={{ width: '120px', margin: 'auto', position: 'relative' }}>
|
||||||
<img src={UserIcon} alt='img' />
|
<img src={uploadedImg ? typeof uploadedImg === 'string' ? uploadedImg : URL.createObjectURL(uploadedImg) : BlankImage}
|
||||||
<MDBox sx={{ position: 'absolute', bottom: '0', right: '0', cursor: 'pointer' }}>
|
alt='img' width='120' height='120' style={{borderRadius: '50%'}} onError={() => setUploadedImg(BlankImage)} />
|
||||||
<img src={EditIcon} alt='img' />
|
<MDBox sx={{ position: 'absolute', bottom: '0', right: '0' }}>
|
||||||
|
<label htmlFor="image" style={{ cursor: 'pointer' }}>
|
||||||
|
<img src={EditIcon} />
|
||||||
|
</label>
|
||||||
|
<input id='image' name='image' type="file" className='d-none' accept="image/png, image/gif, image/jpeg"
|
||||||
|
onChange={handleFileChange} />
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
<MDBox sx={{ marginBottom: '24px' }}>
|
||||||
<Box component='div' sx={{}} className={classes.labelSize}>
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
User Name
|
User Name
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth value={formik.values.fullName} name='fullName' type='text'
|
<MDInput
|
||||||
variant='outlined' error={formik.touched.fullName && Boolean(formik.errors.fullName)}
|
fullWidth
|
||||||
helperText={formik.touched.fullName && formik.errors.fullName} onChange={formik.handleChange} />
|
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>
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
<MDBox sx={{ marginBottom: '24px' }}>
|
||||||
<Box component='div' sx={{}} className={classes.labelSize}>
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
Email
|
Email
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth disabled={context === 'edit'} value={formik.values.email} name='email' type='email'
|
<MDInput
|
||||||
variant='outlined' error={formik.touched.email && Boolean(formik.errors.email)}
|
fullWidth
|
||||||
helperText={formik.touched.email && formik.errors.email} onChange={formik.handleChange} />
|
disabled={context === 'edit'}
|
||||||
|
value={formik.values.email}
|
||||||
|
name="email"
|
||||||
|
type="email"
|
||||||
|
variant="outlined"
|
||||||
|
error={formik.touched.email && Boolean(formik.errors.email)}
|
||||||
|
helperText={formik.touched.email && formik.errors.email}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
<MDBox sx={{ marginBottom: '24px' }}>
|
||||||
<Box component='div' sx={{}} className={classes.labelSize}>
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
Password
|
Password
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth value={formik.values.password} name='password' type='password'
|
<MDInput
|
||||||
variant='outlined' error={formik.touched.password && Boolean(formik.errors.password)}
|
fullWidth
|
||||||
helperText={formik.touched.password && formik.errors.password} onChange={formik.handleChange} />
|
value={formik.values.password}
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
variant="outlined"
|
||||||
|
error={formik.touched.password && Boolean(formik.errors.password)}
|
||||||
|
helperText={formik.touched.password && formik.errors.password}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
<MDBox sx={{ marginBottom: '24px' }}>
|
||||||
<Box component='div' sx={{}} className={classes.labelSize}>
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
Phone Number
|
Phone Number
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth value={formik.values.phoneNumber} name='phoneNumber' type='text'
|
<MDInput
|
||||||
variant='outlined' error={formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber)}
|
fullWidth
|
||||||
helperText={formik.touched.phoneNumber && formik.errors.phoneNumber} onChange={formik.handleChange} />
|
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>
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
<MDBox sx={{ marginBottom: '24px' }}>
|
||||||
<Box component='div' sx={{}} className={classes.labelSize}>
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
Role
|
Role
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', columnGap: '20px' }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', columnGap: '20px' }}>
|
||||||
@@ -234,16 +374,25 @@ function CreateEditUser(props) {
|
|||||||
<Select
|
<Select
|
||||||
multiple
|
multiple
|
||||||
displayEmpty
|
displayEmpty
|
||||||
name='roles'
|
name="roles"
|
||||||
value={selectedRoles}
|
value={selectedRoles}
|
||||||
input={<OutlinedInput />}
|
input={<OutlinedInput />}
|
||||||
error={formik.touched.roles && Boolean(formik.errors.roles)}
|
error={formik.touched.roles && Boolean(formik.errors.roles)}
|
||||||
renderValue={() => selectedRoles?.length === 0 ? 'Please select a role' : selectedRoles?.map(role => role.name).join(', ')}
|
renderValue={() =>
|
||||||
|
selectedRoles?.length === 0
|
||||||
|
? 'Please select a role'
|
||||||
|
: selectedRoles?.map((role) => role.name).join(', ')
|
||||||
|
}
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
inputProps={{ 'aria-label': 'Without label' }}
|
||||||
sx={{width: '100%'}}
|
sx={{ width: '100%' }}
|
||||||
onChange={handleMultiSelectChange}
|
onChange={handleMultiSelectChange}
|
||||||
>
|
>
|
||||||
{roles && roles.map((role, key) => <MenuItem key={key} value={role}>{role.name}</MenuItem>)}
|
{roles &&
|
||||||
|
roles.map((role, key) => (
|
||||||
|
<MenuItem key={key} value={role}>
|
||||||
|
{role.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
@@ -258,7 +407,7 @@ function CreateEditUser(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
component='div'
|
component="div"
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
lineHeight: '20px',
|
lineHeight: '20px',
|
||||||
@@ -278,7 +427,11 @@ function CreateEditUser(props) {
|
|||||||
left: '20px'
|
left: '20px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Switch name='isActive' checked={formik.values.isActive} onChange={formik.handleChange} />
|
<Switch
|
||||||
|
name="isActive"
|
||||||
|
checked={formik.values.isActive}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -287,28 +440,42 @@ function CreateEditUser(props) {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Grid container spacing={2} className={classes.margin}>
|
<Grid container spacing={2} className={classes.margin}>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<Box component='div' className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Created By
|
Created By
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth disabled name='createdBy' type='text' value={formik.values.createdBy} variant='outlined' />
|
<MDInput
|
||||||
|
fullWidth
|
||||||
|
disabled
|
||||||
|
name="createdBy"
|
||||||
|
type="text"
|
||||||
|
value={formik.values.createdBy}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<Box component='div' className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Date & Time
|
Date & Time
|
||||||
</Box>
|
</Box>
|
||||||
<DateTimeInput disabled name='createdAt' value={formik.values.createdAt} />
|
<DateTimeInput disabled name='createdAt' value={new Date(formik.values.createdAt)} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<Box component='div' className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Last Updated by
|
Last Updated by
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput fullWidth disabled name='updatedBy' type='text' value={formik.values.updatedBy} variant='outlined' />
|
<MDInput
|
||||||
|
fullWidth
|
||||||
|
disabled
|
||||||
|
name="updatedBy"
|
||||||
|
type="text"
|
||||||
|
value={formik.values.updatedBy}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<Box component='div' className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Date & Time
|
Date & Time
|
||||||
</Box>
|
</Box>
|
||||||
<DateTimeInput disabled name='updatedAt' value={formik.values.updatedAt} />
|
<DateTimeInput disabled name='updatedAt' value={new Date(formik.values.updatedAt)} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -316,33 +483,81 @@ function CreateEditUser(props) {
|
|||||||
</MDBox>
|
</MDBox>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
<Grid container spacing={4} sx={{ marginTop: '-6px' }}>
|
<Grid container spacing={4} sx={{ marginTop: '-6px' }}>
|
||||||
<AllocationManager name='warehouses' gridStyleOverride={{ paddingLeft: '4rem !important' }} initlist={formik.values.warehouses}
|
<AllocationManager
|
||||||
list={warehouses} matchProp={{a: '_id'}} title='Warehouse' onChange={val => formik.handleChange('warehouses')(val)} />
|
allDisabled={selectedRoles?.length > 0}
|
||||||
<AllocationManager name='inventories' gridStyleOverride={{ paddingRight: '2rem' }} initlist={formik.values.inventories}
|
name="warehouses"
|
||||||
list={inventories} matchProp={{a: '_id'}} title='Inventory' onChange={val => formik.handleChange('inventories')(val)} />
|
gridStyleOverride={{ paddingLeft: '4rem !important' }}
|
||||||
|
allocatedList={formik.values.warehouses}
|
||||||
|
list={warehouses}
|
||||||
|
matchProp={{ a: '_id' }}
|
||||||
|
title="Warehouse"
|
||||||
|
onChange={val => {
|
||||||
|
val = val?.map(obj => obj._id).join(',');
|
||||||
|
// setSelectedPermissions({...selectedPermissions, warehouses: val});
|
||||||
|
formik.handleChange('warehouses')(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AllocationManager
|
||||||
|
allDisabled={selectedRoles?.length > 0}
|
||||||
|
name="inventories"
|
||||||
|
gridStyleOverride={{ paddingRight: '2rem' }}
|
||||||
|
allocatedList={formik.values.inventories}
|
||||||
|
list={inventories}
|
||||||
|
matchProp={{ a: '_id' }}
|
||||||
|
title="Inventory"
|
||||||
|
onChange={val => {
|
||||||
|
val = val?.map(obj => obj._id).join(',');
|
||||||
|
// setSelectedPermissions({...selectedPermissions, inventories: val});
|
||||||
|
formik.handleChange('inventories')(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container spacing={2} sx={{ marginTop: '12px', paddingLeft: '2rem' }}>
|
<Grid container spacing={4} sx={{ marginTop: '12px'}}>
|
||||||
<Toggles name='actions' title='Actions' toggles={actions} inittoggles={formik.values.actions} onChange={val => formik.handleChange('actions')(val)} />
|
<Toggles
|
||||||
<Toggles name='visibilities' title='Application' toggles={permissions} inittoggles={formik.values.visibilities} onChange={val => formik.handleChange('visibilities')(val)} />
|
allDisabled={selectedRoles?.length > 0}
|
||||||
|
name="actions"
|
||||||
|
gridStyleOverride={{ paddingLeft: '4rem !important' }}
|
||||||
|
title="Actions"
|
||||||
|
toggles={actions}
|
||||||
|
selectedToggles={formik.values.actions}
|
||||||
|
onChange={val => {
|
||||||
|
val = Object.keys(val).join(',');
|
||||||
|
// setSelectedPermissions({...selectedPermissions, actions: val});
|
||||||
|
formik.handleChange('actions')(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Toggles
|
||||||
|
allDisabled={selectedRoles?.length > 0}
|
||||||
|
name="visibilities"
|
||||||
|
gridStyleOverride={{ paddingRight: '2rem' }}
|
||||||
|
title="Application"
|
||||||
|
toggles={visibilities}
|
||||||
|
selectedToggles={formik.values.visibilities}
|
||||||
|
onChange={val => {
|
||||||
|
val = Object.keys(val).join(',');
|
||||||
|
// setSelectedPermissions({...selectedPermissions, visibilities: val});
|
||||||
|
formik.handleChange('visibilities')(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<MDBox
|
<MDBox
|
||||||
display='flex'
|
display="flex"
|
||||||
justifyContent='center'
|
justifyContent="center"
|
||||||
alignItems='center'
|
alignItems="center"
|
||||||
lineHeight={1}
|
lineHeight={1}
|
||||||
sx={{ marginBottom: '15px', marginTop: '45px', paddingBottom: '30px' }}
|
sx={{ marginBottom: '15px', marginTop: '45px', paddingBottom: '30px' }}
|
||||||
>
|
>
|
||||||
<MDButton
|
<MDButton
|
||||||
size='medium'
|
size="medium"
|
||||||
color='error'
|
color="error"
|
||||||
variant='outlined'
|
variant="outlined"
|
||||||
type='button'
|
type="button"
|
||||||
sx={{ marginRight: '15px' }}
|
sx={{ marginRight: '15px' }}
|
||||||
onClick={() => navigate('/setup/users-access')}
|
onClick={() => navigate('/setup/users-access')}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton size='medium' color='primary' variant='contained' type='submit'>
|
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
||||||
{context === 'new' ? 'Create' : 'Save'}
|
{context === 'new' ? 'Create' : 'Save'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
|
|||||||
218
src/pages/createEditUserRole/index.js
Normal file
218
src/pages/createEditUserRole/index.js
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import MDBox from 'components/MDBox';
|
||||||
|
import DashboardNavbar from 'components/DashboardNavbar';
|
||||||
|
import Footer from 'components/Footer';
|
||||||
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
|
import { makeStyles } from '@mui/styles';
|
||||||
|
import { Box, Grid } from '@mui/material';
|
||||||
|
import MDButton from 'components/Button';
|
||||||
|
import TransferList from 'components/MDTransferList';
|
||||||
|
import DateTimeInput from 'components/DateTimePicker';
|
||||||
|
import Switch from 'components/Switch';
|
||||||
|
import MDTypography from 'components/MDTypography';
|
||||||
|
import MDInput from 'components/MDInput';
|
||||||
|
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
|
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'
|
||||||
|
},
|
||||||
|
switchSpacer: {
|
||||||
|
margin: '0',
|
||||||
|
'& .MuiFormControlLabel-root': {
|
||||||
|
margin: '0'
|
||||||
|
},
|
||||||
|
'& .MuiSwitch-root': {
|
||||||
|
margin: '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
function CreateEditUserRole() {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (
|
||||||
|
<DashboardLayout>
|
||||||
|
<DashboardNavbar />
|
||||||
|
<MDBox px={2} py={3}>
|
||||||
|
<Grid container spacing={2} className={classes.margin}>
|
||||||
|
<Grid item xs={8} md={8}>
|
||||||
|
<Grid container spacing={2} className={classes.margin}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Box component="div" sx={{}} className={classes.labelSize}>
|
||||||
|
Warehouse name
|
||||||
|
</Box>
|
||||||
|
<MDInput fullWidth name="warehousename" type="text" variant="outlined" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Description
|
||||||
|
</Box>
|
||||||
|
<TextareaAutosize className={classes.fullWidth} minRows={5} />
|
||||||
|
</Grid>
|
||||||
|
<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 name="warehousename" type="text" variant="outlined" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Date & Time
|
||||||
|
</Box>
|
||||||
|
<DateTimeInput />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Last Updated by
|
||||||
|
</Box>
|
||||||
|
<MDInput fullWidth name="warehousename" type="text" variant="outlined" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Date & Time
|
||||||
|
</Box>
|
||||||
|
<DateTimeInput />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Choose avatar component here
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid container spacing={4} sx={{ marginTop: '-6px' }}>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<MDBox
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
border: '1px solid #c2c2c2',
|
||||||
|
borderTop: '7px solid #007aff',
|
||||||
|
padding: '12px',
|
||||||
|
borderRadius: '4px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography gutterBottom variant="h6" component="div">
|
||||||
|
Warehouse
|
||||||
|
</Typography>
|
||||||
|
<TransferList />
|
||||||
|
</MDBox>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<MDBox
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
border: '1px solid #c2c2c2',
|
||||||
|
borderTop: '7px solid #007aff',
|
||||||
|
padding: '12px',
|
||||||
|
borderRadius: '4px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography gutterBottom variant="h6" component="div">
|
||||||
|
Warehouse
|
||||||
|
</Typography>
|
||||||
|
<TransferList />
|
||||||
|
</MDBox>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid container spacing={2} sx={{ marginTop: '12px' }}>
|
||||||
|
<Grid item xs={12} md={3}>
|
||||||
|
<MDBox
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
border: '1px solid #c2c2c2',
|
||||||
|
borderTop: '7px solid #007aff',
|
||||||
|
padding: '12px',
|
||||||
|
borderRadius: '4px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography gutterBottom variant="h6" component="div">
|
||||||
|
Process
|
||||||
|
</Typography>
|
||||||
|
<MDBox
|
||||||
|
display="flex"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
lineHeight={1}
|
||||||
|
className={classes.switchSpacer}
|
||||||
|
>
|
||||||
|
<MDTypography variant="body2">Sidenav Mini</MDTypography>
|
||||||
|
<Switch checked />
|
||||||
|
</MDBox>
|
||||||
|
</MDBox>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={3}>
|
||||||
|
<MDBox
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
border: '1px solid #c2c2c2',
|
||||||
|
borderTop: '7px solid #007aff',
|
||||||
|
padding: '12px',
|
||||||
|
borderRadius: '4px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography gutterBottom variant="h6" component="div">
|
||||||
|
Application
|
||||||
|
</Typography>
|
||||||
|
<MDBox
|
||||||
|
display="flex"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
lineHeight={1}
|
||||||
|
className={classes.switchSpacer}
|
||||||
|
>
|
||||||
|
<MDTypography variant="body2">Sidenav Mini</MDTypography>
|
||||||
|
<Switch checked />
|
||||||
|
</MDBox>
|
||||||
|
</MDBox>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<MDBox
|
||||||
|
display="flex"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
lineHeight={1}
|
||||||
|
sx={{ marginBottom: '15px', marginTop: '24px' }}
|
||||||
|
>
|
||||||
|
<MDButton
|
||||||
|
size="medium"
|
||||||
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
|
type="submit"
|
||||||
|
sx={{ marginRight: '15px' }}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</MDButton>
|
||||||
|
<MDButton size="medium" color="primary" variant="contained">
|
||||||
|
Save
|
||||||
|
</MDButton>
|
||||||
|
</MDBox>
|
||||||
|
</MDBox>
|
||||||
|
<Footer />
|
||||||
|
</DashboardLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default CreateEditUserRole;
|
||||||
@@ -1,365 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import MDBox from 'components/MDBox';
|
|
||||||
import DashboardNavbar from 'components/DashboardNavbar';
|
|
||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
|
||||||
import { makeStyles } from '@mui/styles';
|
|
||||||
import { Box, Grid } from '@mui/material';
|
|
||||||
import MDButton from 'components/Button';
|
|
||||||
import TransferList from 'components/MDTransferList';
|
|
||||||
import DateTimeInput from 'components/DateTimePicker';
|
|
||||||
import Switch from 'components/Switch';
|
|
||||||
import MDTypography from 'components/MDTypography';
|
|
||||||
import MDInput from 'components/MDInput';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import UserIcon from 'assets/images/userIcon.png';
|
|
||||||
import EditIcon from 'assets/images/edit-icon.png';
|
|
||||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
|
||||||
import Select from '@mui/material/Select';
|
|
||||||
|
|
||||||
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'
|
|
||||||
},
|
|
||||||
switchSpacer: {
|
|
||||||
margin: '0',
|
|
||||||
'& .MuiFormControlLabel-root': {
|
|
||||||
margin: '0'
|
|
||||||
},
|
|
||||||
'& .MuiSwitch-root': {
|
|
||||||
margin: '0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
function CreateUserRole() {
|
|
||||||
const classes = useStyles();
|
|
||||||
const [personName, setPersonName] = React.useState([]);
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
const {
|
|
||||||
target: { value }
|
|
||||||
} = event;
|
|
||||||
setPersonName(
|
|
||||||
// On autofill we get a stringified value.
|
|
||||||
typeof value === 'string' ? value.split(',') : value
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<DashboardLayout>
|
|
||||||
<DashboardNavbar />
|
|
||||||
<MDBox px={2} sx={{ backgroundColor: '#fff' }}>
|
|
||||||
<MDBox mx={2} 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 name="warehousename" type="text" variant="outlined" />
|
|
||||||
</MDBox>
|
|
||||||
<MDBox sx={{ marginBottom: '24px' }}>
|
|
||||||
<Box component="div" sx={{}} className={classes.labelSize}>
|
|
||||||
Phone Number
|
|
||||||
</Box>
|
|
||||||
<MDInput fullWidth name="warehousename" type="text" variant="outlined" />
|
|
||||||
</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
|
|
||||||
value={personName}
|
|
||||||
input={<OutlinedInput />}
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (selected.length === 0) {
|
|
||||||
return 'Placeholder';
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected.join(', ');
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
|
||||||
sx={{
|
|
||||||
width: '100%'
|
|
||||||
}}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem disabled value="">
|
|
||||||
Placeholder
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem>Lorem Ipsum</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 />
|
|
||||||
</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 name="warehousename" type="text" variant="outlined" />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Date & Time
|
|
||||||
</Box>
|
|
||||||
<DateTimeInput />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Last Updated by
|
|
||||||
</Box>
|
|
||||||
<MDInput fullWidth name="warehousename" type="text" variant="outlined" />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Date & Time
|
|
||||||
</Box>
|
|
||||||
<DateTimeInput />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</MDBox>
|
|
||||||
</MDBox>
|
|
||||||
|
|
||||||
<Grid container spacing={4} sx={{ marginTop: '-6px' }}>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<MDBox
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
border: '1px solid #c2c2c2',
|
|
||||||
borderTop: '7px solid #007aff',
|
|
||||||
padding: '12px',
|
|
||||||
borderRadius: '4px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography gutterBottom variant="h6" component="div">
|
|
||||||
Warehouse
|
|
||||||
</Typography>
|
|
||||||
<TransferList />
|
|
||||||
</MDBox>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<MDBox
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
border: '1px solid #c2c2c2',
|
|
||||||
borderTop: '7px solid #007aff',
|
|
||||||
padding: '12px',
|
|
||||||
borderRadius: '4px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography gutterBottom variant="h6" component="div">
|
|
||||||
Warehouse
|
|
||||||
</Typography>
|
|
||||||
<TransferList />
|
|
||||||
</MDBox>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid container spacing={2} sx={{ marginTop: '12px' }}>
|
|
||||||
<Grid item xs={12} md={3}>
|
|
||||||
<MDBox
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
border: '1px solid #c2c2c2',
|
|
||||||
borderTop: '7px solid #007aff',
|
|
||||||
borderRadius: '4px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
gutterBottom
|
|
||||||
variant="h6"
|
|
||||||
component="div"
|
|
||||||
sx={{
|
|
||||||
borderBottom: '1px solid #c2c2c2',
|
|
||||||
padding: '10px 20px',
|
|
||||||
marginBottom: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Process
|
|
||||||
</Typography>
|
|
||||||
<Box sx={{ padding: ' 0px 20px' }}>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Stock Tracking</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Replenishment</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Alerting</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
</Box>
|
|
||||||
</MDBox>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={3}>
|
|
||||||
<MDBox
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
border: '1px solid #c2c2c2',
|
|
||||||
borderTop: '7px solid #007aff',
|
|
||||||
borderRadius: '4px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
gutterBottom
|
|
||||||
variant="h6"
|
|
||||||
component="div"
|
|
||||||
sx={{
|
|
||||||
borderBottom: '1px solid #c2c2c2',
|
|
||||||
padding: '10px 20px',
|
|
||||||
marginBottom: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Application
|
|
||||||
</Typography>
|
|
||||||
<Box sx={{ padding: ' 0px 20px' }}>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Home</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Setup</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
<MDBox
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
lineHeight={1}
|
|
||||||
className={classes.switchSpacer}
|
|
||||||
sx={{ marginBottom: '20px !important' }}
|
|
||||||
>
|
|
||||||
<MDTypography variant="body2">Reports</MDTypography>
|
|
||||||
<Switch checked />
|
|
||||||
</MDBox>
|
|
||||||
</Box>
|
|
||||||
</MDBox>
|
|
||||||
</Grid>
|
|
||||||
</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="submit"
|
|
||||||
sx={{ marginRight: '15px' }}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</MDButton>
|
|
||||||
<MDButton size="medium" color="primary" variant="contained">
|
|
||||||
Save
|
|
||||||
</MDButton>
|
|
||||||
</MDBox>
|
|
||||||
</MDBox>
|
|
||||||
</DashboardLayout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default CreateUserRole;
|
|
||||||
@@ -12,7 +12,9 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
TextField,
|
TextField,
|
||||||
DialogActions
|
DialogActions,
|
||||||
|
Button,
|
||||||
|
DialogContentText
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import DashboardNavbar from 'components/DashboardNavbar';
|
import DashboardNavbar from 'components/DashboardNavbar';
|
||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
@@ -37,6 +39,8 @@ import Breadcrumbs from 'components/Breadcrumbs';
|
|||||||
import { WarehouseSelectors } from 'redux/WarehouseRedux';
|
import { WarehouseSelectors } from 'redux/WarehouseRedux';
|
||||||
import { InventorySelectors } from 'redux/InventoryRedux';
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
import InventoryActions from 'redux/InventoryRedux';
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import schema from 'services/ValidationServices';
|
||||||
|
|
||||||
const bottomButtonStyling = {
|
const bottomButtonStyling = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@@ -317,6 +321,10 @@ const WarehouseNestedDetails = () => {
|
|||||||
|
|
||||||
function EditWarehouseDetails() {
|
function EditWarehouseDetails() {
|
||||||
const { warehouseId } = useParams();
|
const { warehouseId } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const navigateTo = (to) => {
|
||||||
|
navigate(to);
|
||||||
|
};
|
||||||
const warehouseData = useSelector(WarehouseSelectors.getWarehouseDetailById(warehouseId));
|
const warehouseData = useSelector(WarehouseSelectors.getWarehouseDetailById(warehouseId));
|
||||||
|
|
||||||
const inventoryTypes = useSelector(InventorySelectors.getInventoryDetail);
|
const inventoryTypes = useSelector(InventorySelectors.getInventoryDetail);
|
||||||
@@ -347,11 +355,11 @@ function EditWarehouseDetails() {
|
|||||||
initialValues: {
|
initialValues: {
|
||||||
warehousename: warehouseData.name,
|
warehousename: warehouseData.name,
|
||||||
address: warehouseData.address || '',
|
address: warehouseData.address || '',
|
||||||
preferredInventories: warehouseData.preferredInventories || [],
|
preferredInventories: [...warehouseData.preferredInventories] || [],
|
||||||
specs: warehouseData.specs || '',
|
specs: warehouseData.specs || '',
|
||||||
image: warehouseData.image_url ? [{ src: warehouseData.image_url }] : []
|
image: warehouseData.image_url ? [{ src: warehouseData.image_url }] : []
|
||||||
},
|
},
|
||||||
// validationSchema: schema.warehouseForm,
|
validationSchema: schema.warehouseForm,
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
WarehouseActions.editWarehouseAction({
|
WarehouseActions.editWarehouseAction({
|
||||||
@@ -370,11 +378,20 @@ function EditWarehouseDetails() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
|
||||||
|
const handleDeleteAlertClose = () => {
|
||||||
|
setDeleteAlertOpen(false);
|
||||||
|
};
|
||||||
|
const handleDeleteAlertOpen = () => {
|
||||||
|
setDeleteAlertOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Edit Warehouse Details"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
@@ -385,17 +402,6 @@ function EditWarehouseDetails() {
|
|||||||
<Box mx={3} my={3}>
|
<Box mx={3} my={3}>
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<Box sx={{ backgroundColor: '#fff', padding: '30px' }}>
|
<Box sx={{ backgroundColor: '#fff', padding: '30px' }}>
|
||||||
<Box
|
|
||||||
component="div"
|
|
||||||
sx={{
|
|
||||||
fontSize: '22px',
|
|
||||||
letterSpacing: '0.01em',
|
|
||||||
color: '#000',
|
|
||||||
marginBottom: '30px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Form to Input
|
|
||||||
</Box>
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item xs={12} sm={6} md={6}>
|
||||||
<Box component="div" sx={{ marginBottom: '15px' }}>
|
<Box component="div" sx={{ marginBottom: '15px' }}>
|
||||||
@@ -417,7 +423,12 @@ function EditWarehouseDetails() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.warehousename}
|
value={formik.values.warehousename}
|
||||||
error={formik.touched.warehousename && Boolean(formik.errors.warehousename)}
|
error={formik.touched.warehousename && Boolean(formik.errors.warehousename)}
|
||||||
helperText={formik.touched.warehousename && formik.errors.warehousename}
|
helperText={
|
||||||
|
formik.touched.warehousename &&
|
||||||
|
formik.errors.warehousename && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.warehousename}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -440,7 +451,12 @@ function EditWarehouseDetails() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.address}
|
value={formik.values.address}
|
||||||
error={formik.touched.address && Boolean(formik.errors.address)}
|
error={formik.touched.address && Boolean(formik.errors.address)}
|
||||||
helperText={formik.touched.address && formik.errors.address}
|
helperText={
|
||||||
|
formik.touched.address &&
|
||||||
|
formik.errors.address && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.address}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -459,7 +475,6 @@ function EditWarehouseDetails() {
|
|||||||
<Select
|
<Select
|
||||||
multiple
|
multiple
|
||||||
select
|
select
|
||||||
disabled
|
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="preferredInventories"
|
name="preferredInventories"
|
||||||
@@ -492,6 +507,9 @@ function EditWarehouseDetails() {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<MenuItem disabled key={'none'} value={''}>
|
||||||
|
None Selected
|
||||||
|
</MenuItem>
|
||||||
{inventoryTypes &&
|
{inventoryTypes &&
|
||||||
inventoryTypes.map((inventory) => (
|
inventoryTypes.map((inventory) => (
|
||||||
<MenuItem key={inventory._id} value={inventory._id}>
|
<MenuItem key={inventory._id} value={inventory._id}>
|
||||||
@@ -524,7 +542,49 @@ function EditWarehouseDetails() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item sx={{ textAlign: 'end' }} xs={12} sm={6} md={6}>
|
||||||
|
<MDButton
|
||||||
|
size="large"
|
||||||
|
color="error"
|
||||||
|
variant="outlined"
|
||||||
|
onClick={handleDeleteAlertOpen}
|
||||||
|
>
|
||||||
|
Delete Warehouse
|
||||||
|
</MDButton>
|
||||||
|
<Dialog
|
||||||
|
open={deleteAlertOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleDeleteAlertClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Confirm Warehouse Delete</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Are you sure you want to delete this warehouse?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleDeleteAlertClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(
|
||||||
|
WarehouseActions.deleteWarehouseAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: '/warehouse/',
|
||||||
|
method: 'delete',
|
||||||
|
warehouseId: warehouseData._id,
|
||||||
|
navigateTo
|
||||||
|
})
|
||||||
|
);
|
||||||
|
handleDeleteAlertClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
<Box sx={{ marginTop: '30px' }}>
|
<Box sx={{ marginTop: '30px' }}>
|
||||||
<ImageUploadSingle
|
<ImageUploadSingle
|
||||||
heading="Upload Warehouse Image"
|
heading="Upload Warehouse Image"
|
||||||
@@ -545,6 +605,16 @@ function EditWarehouseDetails() {
|
|||||||
columnGap: '20px'
|
columnGap: '20px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<MDButton
|
||||||
|
size="medium"
|
||||||
|
color="error"
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => {
|
||||||
|
navigate('/setup/warehouse');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
CANCEL
|
||||||
|
</MDButton>
|
||||||
{/* ---edit-- */}
|
{/* ---edit-- */}
|
||||||
<MDButton size="large" color="primary" variant="outlined" type="submit">
|
<MDButton size="large" color="primary" variant="outlined" type="submit">
|
||||||
SAVE
|
SAVE
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ function HomepageScreen() {
|
|||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs route={[{ name: 'Home', path: '/home' }]} />
|
<Breadcrumbs title="Warehouse Management System" route={[{ name: 'Home', path: '/home' }]} />
|
||||||
<TileBasic tiles={data} />
|
<TileBasic tiles={data} />
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import DashboardNavbar from 'components/DashboardNavbar';
|
import DashboardNavbar from 'components/DashboardNavbar';
|
||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
import { Box, Grid, MenuItem, Select } from '@mui/material';
|
import {
|
||||||
|
Box,
|
||||||
|
FormControlLabel,
|
||||||
|
Grid,
|
||||||
|
MenuItem,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
useRadioGroup,
|
||||||
|
Select,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogActions,
|
||||||
|
Button
|
||||||
|
} from '@mui/material';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
import MDInput from 'components/MDInput';
|
import MDInput from 'components/MDInput';
|
||||||
import Switch from 'components/Switch';
|
import Switch from 'components/Switch';
|
||||||
import MDTypography from 'components/MDTypography';
|
import MDTypography from 'components/MDTypography';
|
||||||
@@ -18,6 +35,9 @@ import { useParams } from 'react-router-dom';
|
|||||||
import { InventorySelectors } from 'redux/InventoryRedux';
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import WidgetNestedDataTable from 'components/WidgetNestedDataTable';
|
import WidgetNestedDataTable from 'components/WidgetNestedDataTable';
|
||||||
|
import { GetIconFromSlug } from 'utils/inventorySlugTools';
|
||||||
|
import { iconSlugs } from 'utils/inventorySlugTools';
|
||||||
|
import AddCircleIcon from '@mui/icons-material/AddCircle';
|
||||||
|
|
||||||
const customStyles = {
|
const customStyles = {
|
||||||
labelSize: {
|
labelSize: {
|
||||||
@@ -63,13 +83,34 @@ const definedPolicies = [
|
|||||||
{
|
{
|
||||||
text: 'Alerting',
|
text: 'Alerting',
|
||||||
key: 'alerting'
|
key: 'alerting'
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Location',
|
|
||||||
key: 'preferredLocations'
|
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// text: 'Location',
|
||||||
|
// key: 'preferredLocations'
|
||||||
|
// }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const StyledFormControlLabel = styled((props) => <FormControlLabel {...props} />)(
|
||||||
|
({ theme, checked }) => ({
|
||||||
|
'.MuiFormControlLabel-label': checked && {
|
||||||
|
border: `1px solid ${theme.palette.primary.light}`,
|
||||||
|
borderRadius: '10px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
function MyFormControlLabel(props) {
|
||||||
|
const radioGroup = useRadioGroup();
|
||||||
|
let checked = false;
|
||||||
|
if (radioGroup) {
|
||||||
|
checked = radioGroup.value === props.value;
|
||||||
|
}
|
||||||
|
return <StyledFormControlLabel checked={checked} {...props} />;
|
||||||
|
}
|
||||||
|
MyFormControlLabel.propTypes = {
|
||||||
|
value: PropTypes.any
|
||||||
|
};
|
||||||
|
|
||||||
function InventoryScreen() {
|
function InventoryScreen() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -80,18 +121,16 @@ function InventoryScreen() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const currentInventoryData = useSelector(InventorySelectors.getInventoryDetailById(inventoryId));
|
const currentInventoryData = useSelector(InventorySelectors.getInventoryDetailById(inventoryId));
|
||||||
LOGGER.log({ currentInventoryData });
|
const [iconSelect, setIconSelect] = React.useState('');
|
||||||
// const [inventoryAllData, setInventoryAllData] = useState([]);
|
|
||||||
// const initialInventoryName='';
|
|
||||||
|
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// const filterData = inventoryData.filter((item) => item._id === inventoryId);
|
if (inventoryId) {
|
||||||
// console.log('filterData', filterData);
|
const iconFilter = iconSlugs.filter(
|
||||||
// setInitialInventoryName(filterData[0].name)
|
(iconSlug) => iconSlug === currentInventoryData.icon_slug
|
||||||
// setInventoryAllData(filterData[0].widgetName);
|
);
|
||||||
// }, []);
|
setIconSelect(GetIconFromSlug(iconFilter[0]));
|
||||||
|
}
|
||||||
// LOGGER.log('initialInventoryName', initialInventoryName);
|
}, [inventoryId]);
|
||||||
|
|
||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -99,6 +138,7 @@ function InventoryScreen() {
|
|||||||
? {
|
? {
|
||||||
name: currentInventoryData.name,
|
name: currentInventoryData.name,
|
||||||
widgetName: currentInventoryData.widgetName,
|
widgetName: currentInventoryData.widgetName,
|
||||||
|
icon_slug: currentInventoryData.icon_slug,
|
||||||
policies: {
|
policies: {
|
||||||
orderTracking: currentInventoryData.policies.orderTracking,
|
orderTracking: currentInventoryData.policies.orderTracking,
|
||||||
alerting: currentInventoryData.policies.alerting,
|
alerting: currentInventoryData.policies.alerting,
|
||||||
@@ -110,11 +150,12 @@ function InventoryScreen() {
|
|||||||
: {
|
: {
|
||||||
name: '',
|
name: '',
|
||||||
widgetName: '',
|
widgetName: '',
|
||||||
|
icon_slug: '',
|
||||||
policies: {
|
policies: {
|
||||||
orderTracking: false,
|
orderTracking: false,
|
||||||
alerting: false,
|
alerting: false,
|
||||||
replenishment: false,
|
replenishment: false,
|
||||||
preferredLocations: false,
|
preferredLocations: false, // TODO: change later
|
||||||
inventory_process: 'CCR'
|
inventory_process: 'CCR'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -130,7 +171,7 @@ function InventoryScreen() {
|
|||||||
navigateTo,
|
navigateTo,
|
||||||
data: {
|
data: {
|
||||||
...values,
|
...values,
|
||||||
icon_slug: 'testslug'
|
icon_slug: values.icon_slug
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -142,18 +183,39 @@ function InventoryScreen() {
|
|||||||
navigateTo,
|
navigateTo,
|
||||||
data: {
|
data: {
|
||||||
...values,
|
...values,
|
||||||
icon_slug: 'testslug'
|
icon_slug: values.icon_slug
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
LOGGER.log('Form values', formik.values);
|
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
|
||||||
|
const handleDeleteAlertClose = () => {
|
||||||
|
setDeleteAlertOpen(false);
|
||||||
|
};
|
||||||
|
const handleDeleteAlertOpen = () => {
|
||||||
|
setDeleteAlertOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [iconSlugOpen, setIconSlugOpen] = React.useState(null);
|
||||||
|
const handleIconSlugClose = () => {
|
||||||
|
setIconSlugOpen(false);
|
||||||
|
};
|
||||||
|
const handleIconSlugOpen = () => {
|
||||||
|
setIconSlugOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleIconSlug = (value) => {
|
||||||
|
const iconFilter = iconSlugs.filter((iconSlug) => iconSlug === value);
|
||||||
|
setIconSelect(GetIconFromSlug(iconFilter[0]));
|
||||||
|
setIconSlugOpen(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Inventory Details"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
@@ -186,7 +248,10 @@ function InventoryScreen() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.name}
|
value={formik.values.name}
|
||||||
error={formik.touched.name && Boolean(formik.errors.name)}
|
error={formik.touched.name && Boolean(formik.errors.name)}
|
||||||
helpertText={formik.touched.name && formik.errors.name}
|
helperText={
|
||||||
|
formik.touched.name &&
|
||||||
|
formik.errors.name && <div style={{ color: 'red' }}>{formik.errors.name}</div>
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -202,7 +267,12 @@ function InventoryScreen() {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.widgetName}
|
value={formik.values.widgetName}
|
||||||
error={formik.touched.widgetName && Boolean(formik.errors.widgetName)}
|
error={formik.touched.widgetName && Boolean(formik.errors.widgetName)}
|
||||||
helpertext={formik.touched.widgetName && formik.errors.widgetName}
|
helperText={
|
||||||
|
formik.touched.widgetName &&
|
||||||
|
formik.errors.widgetName && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.widgetName}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -257,8 +327,107 @@ function InventoryScreen() {
|
|||||||
</div>
|
</div>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item sx={{ textAlign: 'right' }} xs={12} sm={6} md={6}>
|
||||||
icon slugs selector
|
<MDButton
|
||||||
|
size="large"
|
||||||
|
color="error"
|
||||||
|
variant="outlined"
|
||||||
|
sx={{
|
||||||
|
marginTop: '20px'
|
||||||
|
}}
|
||||||
|
onClick={handleDeleteAlertOpen}
|
||||||
|
>
|
||||||
|
Delete Inventory
|
||||||
|
</MDButton>
|
||||||
|
<Dialog
|
||||||
|
open={deleteAlertOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleDeleteAlertClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Confirm Inventory Delete</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Are you sure you want to delete this inventory?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleDeleteAlertClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(
|
||||||
|
InventoryActions.deleteInventoryAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: '/inventory/' + inventoryId,
|
||||||
|
method: 'delete',
|
||||||
|
inventoryId,
|
||||||
|
navigateTo
|
||||||
|
})
|
||||||
|
);
|
||||||
|
handleDeleteAlertClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
height: 300,
|
||||||
|
padding: '20px',
|
||||||
|
marginTop: '80px',
|
||||||
|
textAlign: 'left'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MDBox sx={{ my: 4 }}>
|
||||||
|
<MDTypography variant="h5">Inventory Icon</MDTypography>
|
||||||
|
<MDTypography sx={customStyles.textSize}>
|
||||||
|
Choose the icon to represent the inventory
|
||||||
|
</MDTypography>
|
||||||
|
</MDBox>
|
||||||
|
|
||||||
|
<AddCircleIcon fontSize="large" onClick={handleIconSlugOpen} />
|
||||||
|
{iconSelect}
|
||||||
|
<Dialog
|
||||||
|
open={iconSlugOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleIconSlugClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Select Icon</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
<RadioGroup
|
||||||
|
row
|
||||||
|
sx={{
|
||||||
|
marginTop: '15px'
|
||||||
|
}}
|
||||||
|
aria-labelledby="demo-error-radios"
|
||||||
|
name="icon_slug"
|
||||||
|
value={formik.values.icon_slug}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
>
|
||||||
|
{iconSlugs.map((iconSlug) => (
|
||||||
|
<MyFormControlLabel
|
||||||
|
key={iconSlug}
|
||||||
|
value={iconSlug}
|
||||||
|
control={<Radio style={{ display: 'none' }} />}
|
||||||
|
label={GetIconFromSlug(iconSlug)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleIconSlugClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => handleIconSlug(formik.values.icon_slug)}>Yes</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<MDBox sx={{ ml: 'auto', mr: 'auto', mt: 3 }}>
|
<MDBox sx={{ ml: 'auto', mr: 'auto', mt: 3 }}>
|
||||||
<MDButton
|
<MDButton
|
||||||
@@ -269,12 +438,12 @@ function InventoryScreen() {
|
|||||||
navigate('/setup/inventory');
|
navigate('/setup/inventory');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{'CANCEL'}
|
{'CLOSE'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton sx={{ ml: 3 }} color="primary" variant="outlined" type="submit">
|
<MDButton sx={{ ml: 3 }} color="primary" variant="outlined" type="submit">
|
||||||
{'SAVE'}
|
{'SAVE'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton
|
{/* <MDButton
|
||||||
sx={{ ml: 3 }}
|
sx={{ ml: 3 }}
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -284,7 +453,7 @@ function InventoryScreen() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{'ADD ITEMS'}
|
{'ADD ITEMS'}
|
||||||
</MDButton>
|
</MDButton> */}
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
|
|||||||
@@ -14,7 +14,17 @@ import EnhancedTable from 'components/EnhancedTable';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import WidgetActions from 'redux/WidgetRedux';
|
import WidgetActions from 'redux/WidgetRedux';
|
||||||
import { WidgetSelectors } from 'redux/WidgetRedux';
|
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||||
import { DialogContent, DialogContentText, DialogTitle, MenuItem, Select } from '@mui/material';
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
|
MenuItem,
|
||||||
|
Select
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
const tHeads = [
|
const tHeads = [
|
||||||
{ key: 'name', name: '' },
|
{ key: 'name', name: '' },
|
||||||
@@ -34,7 +44,7 @@ const tHeads = [
|
|||||||
|
|
||||||
function ItemListing() {
|
function ItemListing() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { widgetName, inventoryId } = useParams();
|
const { inventoryName, widgetName, inventoryId } = useParams();
|
||||||
const [page, setPage] = React.useState(1);
|
const [page, setPage] = React.useState(1);
|
||||||
const [perPage, setPerPage] = React.useState(10);
|
const [perPage, setPerPage] = React.useState(10);
|
||||||
LOGGER.log({ widgetName, inventoryId });
|
LOGGER.log({ widgetName, inventoryId });
|
||||||
@@ -76,20 +86,76 @@ function ItemListing() {
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
|
||||||
|
const handleDeleteAlertClose = () => {
|
||||||
|
setDeleteAlertOpen(null);
|
||||||
|
};
|
||||||
|
const handleDeleteAlertOpen = (id) => {
|
||||||
|
setDeleteAlertOpen(id);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title={`List of ${widgetName}s`}
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
{ name: 'Inventory', path: '/setup/inventory' },
|
{ name: 'Inventory', path: '/setup/inventory' },
|
||||||
|
{ name: inventoryName || 'Inventory' },
|
||||||
{ name: `${widgetName}s List` }
|
{ name: `${widgetName}s List` }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MDBox px={2} py={3}>
|
<MDBox px={5} py={3}>
|
||||||
List of {widgetName}s{/* <pre>{JSON.stringify(data, null, 4)}</pre> */}
|
<Dialog
|
||||||
|
open={deleteAlertOpen}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
onClose={handleDeleteAlertClose}
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Confirm Delete</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Are you sure you want to delete this item?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleDeleteAlertClose}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
const refreshDispatch = () => {
|
||||||
|
dispatch(
|
||||||
|
ItemActions.itemRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_ITEMS_BY_INVENTORY,
|
||||||
|
method: 'get',
|
||||||
|
page: page - 1,
|
||||||
|
perPage,
|
||||||
|
inventoryId,
|
||||||
|
family: sFam || pFam || null
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
dispatch(
|
||||||
|
ItemActions.deleteItemRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: '/item/',
|
||||||
|
method: 'delete',
|
||||||
|
itemId: deleteAlertOpen,
|
||||||
|
refreshDispatch
|
||||||
|
})
|
||||||
|
);
|
||||||
|
handleDeleteAlertClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
<EnhancedTable
|
<EnhancedTable
|
||||||
count={count}
|
count={count}
|
||||||
page={page}
|
page={page}
|
||||||
@@ -97,7 +163,12 @@ function ItemListing() {
|
|||||||
perPage={perPage}
|
perPage={perPage}
|
||||||
setPerPage={setPerPage}
|
setPerPage={setPerPage}
|
||||||
editHandler={(id) => {
|
editHandler={(id) => {
|
||||||
navigateTo(`/setup/inventory/browse/${widgetName}/${inventoryId}/edit/${id}`);
|
navigateTo(
|
||||||
|
`/setup/inventory/browse/${inventoryName}/${widgetName}/${inventoryId}/edit/${id}`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
deleteHandler={(id) => {
|
||||||
|
handleDeleteAlertOpen(id);
|
||||||
}}
|
}}
|
||||||
resetFilters={() => {
|
resetFilters={() => {
|
||||||
setPFam('');
|
setPFam('');
|
||||||
@@ -105,21 +176,21 @@ function ItemListing() {
|
|||||||
}}
|
}}
|
||||||
filtersControl={
|
filtersControl={
|
||||||
<>
|
<>
|
||||||
<DialogTitle>Add filters</DialogTitle>
|
<Grid item sx={4}>
|
||||||
<DialogContent>
|
|
||||||
<DialogContentText>Filter by family</DialogContentText>
|
|
||||||
<Select
|
<Select
|
||||||
select
|
displayEmpty
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={pFam}
|
value={pFam}
|
||||||
|
inputProps={{ 'aria-label': 'Without label' }}
|
||||||
|
sx={{
|
||||||
|
width: 200
|
||||||
|
}}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSFam('');
|
setSFam('');
|
||||||
setPFam(e.target.value);
|
setPFam(e.target.value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem key={'none'} value={''}>
|
<MenuItem disabled key={'none'} value={''}>
|
||||||
None Selected
|
Widget family L1
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{primaryFamilies &&
|
{primaryFamilies &&
|
||||||
primaryFamilies.map((fam) => (
|
primaryFamilies.map((fam) => (
|
||||||
@@ -128,17 +199,22 @@ function ItemListing() {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid item sx={4}>
|
||||||
<Select
|
<Select
|
||||||
select
|
displayEmpty
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={sFam}
|
value={sFam}
|
||||||
|
inputProps={{ 'aria-label': 'Without label' }}
|
||||||
|
sx={{
|
||||||
|
width: 200
|
||||||
|
}}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSFam(e.target.value);
|
setSFam(e.target.value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem key={'none'} value={''}>
|
<MenuItem disabled key={'none'} value={''}>
|
||||||
None Selected
|
Widget family L2
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{secondaryFamilies &&
|
{secondaryFamilies &&
|
||||||
secondaryFamilies.map((fam) => (
|
secondaryFamilies.map((fam) => (
|
||||||
@@ -147,14 +223,14 @@ function ItemListing() {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</DialogContent>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
data={
|
data={
|
||||||
data
|
data
|
||||||
? data.map((item) => {
|
? data.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item._id,
|
_id: item._id,
|
||||||
commonName: item.commonName,
|
commonName: item.commonName,
|
||||||
formalName: item.formalName,
|
formalName: item.formalName,
|
||||||
description: item.description,
|
description: item.description,
|
||||||
|
|||||||
@@ -3,12 +3,29 @@ import DashboardNavbar from 'components/DashboardNavbar';
|
|||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
import { makeStyles } from '@mui/styles';
|
import { makeStyles } from '@mui/styles';
|
||||||
import Dropdown from 'components/Dropdown';
|
import Dropdown from 'components/Dropdown';
|
||||||
import { Grid, TableBody, TableCell, TableRow } from '@mui/material';
|
import { Box, Checkbox, Grid, TableBody, TableCell, TableRow } from '@mui/material';
|
||||||
import BasicTable from 'components/BasicTable';
|
|
||||||
import MDButton from 'components/Button';
|
import MDButton from 'components/Button';
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { LabellingSelectors } from 'redux/LabellingRedux';
|
||||||
|
import { WarehouseSelectors } from 'redux/WarehouseRedux';
|
||||||
|
import { WarehouseLocationsSelectors } from 'redux/WarehouseLocationsRedux';
|
||||||
|
import WarehouseActions from 'redux/WarehouseRedux';
|
||||||
|
import { API } from 'constant';
|
||||||
|
import WarehouseLocationsActions from 'redux/WarehouseLocationsRedux';
|
||||||
|
import LabellingActions from 'redux/LabellingRedux';
|
||||||
|
import BasicTable from 'components/BasicTable';
|
||||||
|
const label = { inputProps: { 'aria-label': 'Checkbox demo' } };
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
|
nodataStyle: {
|
||||||
|
height: '200px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: '300%'
|
||||||
|
},
|
||||||
iconSize: {
|
iconSize: {
|
||||||
width: '50%',
|
width: '50%',
|
||||||
height: '50%',
|
height: '50%',
|
||||||
@@ -25,37 +42,10 @@ const useStyles = makeStyles({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const records = [
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: ''
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const headCells = [
|
const headCells = [
|
||||||
{
|
{
|
||||||
id: 'warehouse',
|
id: 'warehouse',
|
||||||
label: 'warehouse'
|
label: 'Warehouse'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'zone',
|
id: 'zone',
|
||||||
@@ -70,65 +60,116 @@ const headCells = [
|
|||||||
label: 'Row'
|
label: 'Row'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Label',
|
id: 'bay',
|
||||||
label: 'label'
|
label: 'Bay'
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Bay',
|
|
||||||
label: 'bay'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function LabelingScreen() {
|
function LabelingScreen() {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const dropdownData = [
|
const [warehouseId, setWarehouseId] = useState('');
|
||||||
{
|
const [zoneId, setZoneId] = useState('');
|
||||||
ID: '1',
|
const [areaId, setAreaId] = useState('');
|
||||||
displayname: 'Regular, full time'
|
const [rowId, setRowId] = useState('');
|
||||||
},
|
|
||||||
{
|
const warehouseData = useSelector(WarehouseSelectors.getWarehouseDetail);
|
||||||
ID: '2',
|
const zonedata = useSelector(WarehouseLocationsSelectors.getChildrenOfParent(warehouseId));
|
||||||
displayname: 'Regular, part time'
|
const areadata = useSelector(WarehouseLocationsSelectors.getChildrenOfParent(zoneId));
|
||||||
},
|
const rowdata = useSelector(WarehouseLocationsSelectors.getChildrenOfParent(areaId));
|
||||||
{
|
|
||||||
ID: '3',
|
const [allLabelData, setAllLabelData] = useState([]);
|
||||||
displayname: 'Contractor- Arise Max'
|
const [totemLabelData, setTotemLabelData] = useState([]);
|
||||||
|
const [locationLabelData, setLocationLabelData] = useState([]);
|
||||||
|
|
||||||
|
const labelData = useSelector(LabellingSelectors.getLabelDetail);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (labelData && warehouseId && zoneId && areaId && rowId) {
|
||||||
|
setAllLabelData(labelData);
|
||||||
}
|
}
|
||||||
];
|
}, [labelData, warehouseId, zoneId, areaId]);
|
||||||
const data = [
|
|
||||||
{
|
useEffect(() => {
|
||||||
placeholder: 'Lorem Ipsum',
|
dispatch(
|
||||||
label: 'Select Warehouse'
|
WarehouseActions.warehouseDataAction({
|
||||||
},
|
loader: 'loading-request',
|
||||||
{
|
slug: API.GET_WAREHOUSE_DATA,
|
||||||
placeholder: 'Lorem Ipsum',
|
method: 'get'
|
||||||
label: 'Select Zone'
|
})
|
||||||
},
|
);
|
||||||
{
|
}, []);
|
||||||
placeholder: 'Lorem Ipsum',
|
|
||||||
label: 'Select Area'
|
const warehouseChange = (event) => {
|
||||||
},
|
const id = event.target.value;
|
||||||
{
|
const type = 'warehouse';
|
||||||
placeholder: 'Warehouse 1',
|
setWarehouseId(id);
|
||||||
label: 'Select Row'
|
setZoneId('');
|
||||||
|
setAreaId('');
|
||||||
|
setRowId('');
|
||||||
|
dispatch(
|
||||||
|
WarehouseLocationsActions.locationRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_CHILDREN_FROM_PARENT,
|
||||||
|
method: 'post',
|
||||||
|
data: { id, type }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const zoneChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
const type = 'zone';
|
||||||
|
setZoneId(id);
|
||||||
|
setAreaId('');
|
||||||
|
setRowId('');
|
||||||
|
dispatch(
|
||||||
|
WarehouseLocationsActions.locationRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_CHILDREN_FROM_PARENT,
|
||||||
|
method: 'post',
|
||||||
|
data: { id, type }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const areaChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
const type = 'area';
|
||||||
|
setAreaId(id);
|
||||||
|
setRowId('');
|
||||||
|
dispatch(
|
||||||
|
WarehouseLocationsActions.locationRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_CHILDREN_FROM_PARENT,
|
||||||
|
method: 'post',
|
||||||
|
data: { id, type }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const rowChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
setRowId(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTableItem = (e, item) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
setTotemLabelData((prev) => [...prev, item.totem_label]);
|
||||||
|
setLocationLabelData((prev) => [...prev, item.location_data]);
|
||||||
|
} else {
|
||||||
|
const filterData = allLabelData.filter((item2) => item2.bay._id !== item.bay._id);
|
||||||
|
setTotemLabelData(filterData);
|
||||||
|
setLocationLabelData(filterData);
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
const data2 = [
|
|
||||||
{
|
|
||||||
placeholder: 'Z01-A02-R001-B001',
|
|
||||||
label: 'Bay TOTEM Labels'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
placeholder: 'Z01-A02-R001-B001',
|
|
||||||
label: 'BIN Location Labels'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Search And Print Location Labels"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
@@ -137,42 +178,106 @@ function LabelingScreen() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<MDBox px={5} py={5}>
|
<MDBox px={5} py={5}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2} alignItems="end">
|
||||||
{data &&
|
<Grid item xs={12} md={2.5}>
|
||||||
data.map((item, index) => (
|
<Dropdown
|
||||||
<Grid item xs={12} sm={6} md={3} key={index}>
|
dropdownData={warehouseData}
|
||||||
<Dropdown items={item} dropdownData={dropdownData} />
|
value={warehouseId}
|
||||||
</Grid>
|
label="Select warehouse"
|
||||||
))}
|
onChange={warehouseChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={2.5}>
|
||||||
|
<Dropdown dropdownData={zonedata} label="Select Zone" onChange={zoneChange} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={2.5}>
|
||||||
|
<Dropdown dropdownData={areadata} label="Select Area" onChange={areaChange} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={2.5}>
|
||||||
|
<Dropdown dropdownData={rowdata} label="Select Row" onChange={rowChange} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={2}>
|
||||||
|
<MDButton
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
sx={{
|
||||||
|
height: '45px'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
warehouseId &&
|
||||||
|
zoneId &&
|
||||||
|
areaId &&
|
||||||
|
rowId &&
|
||||||
|
dispatch(
|
||||||
|
LabellingActions.getLabelAction({
|
||||||
|
loader: 'labelling-request',
|
||||||
|
slug: API.GET_LABEL,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
warehouse: warehouseId,
|
||||||
|
zone: zoneId,
|
||||||
|
area: areaId,
|
||||||
|
row: rowId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Filter
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<br />
|
<br />
|
||||||
<BasicTable
|
<BasicTable
|
||||||
headCells={headCells}
|
headCells={headCells}
|
||||||
records={records}
|
records={allLabelData}
|
||||||
backgroundColor="#F4F4F4"
|
backgroundColor="#E5E5E5"
|
||||||
color="#8D8D8D"
|
color="#8D8D8D"
|
||||||
>
|
>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{records &&
|
{rowId ? (
|
||||||
records.map((item) => (
|
allLabelData &&
|
||||||
<TableRow key={item.id}>
|
allLabelData.map((item) => (
|
||||||
<TableCell>{item.warehouse}</TableCell>
|
<TableRow key={item._id}>
|
||||||
<TableCell>{item.zone}</TableCell>
|
<TableCell>
|
||||||
<TableCell>{item.area}</TableCell>
|
<Checkbox
|
||||||
<TableCell>{item.row}</TableCell>
|
{...label}
|
||||||
<TableCell>{item.label}</TableCell>
|
sx={{ marginRight: '2px' }}
|
||||||
<TableCell>{item.Bay}</TableCell>
|
onChange={(e) => getTableItem(e, item)}
|
||||||
|
/>
|
||||||
|
{item?.warehouse?.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{item?.zone?.name}</TableCell>
|
||||||
|
<TableCell>{item?.row?.name}</TableCell>
|
||||||
|
<TableCell>{item?.area?.name}</TableCell>
|
||||||
|
<TableCell>{item?.bay?.name}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow className={classes.nodataStyle}>No Data</TableRow>
|
||||||
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</BasicTable>
|
</BasicTable>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2} py={5}>
|
||||||
{data2 &&
|
<Grid item xs={12} md={3}>
|
||||||
data2.map((item, index) => (
|
<Box sx={{ backgroundColor: '#FFBC26', padding: '3px 12px' }}>Bay Totem Labels</Box>
|
||||||
<Grid item xs={12} sm={6} md={3} key={index}>
|
<Box sx={{ border: '1px solid black', padding: '3px 12px', height: '300px' }}>
|
||||||
<Dropdown items={item} dropdownData={dropdownData} />
|
{totemLabelData && totemLabelData.map((item, index) => <div key={index}>{item}</div>)}
|
||||||
</Grid>
|
</Box>
|
||||||
))}
|
</Grid>
|
||||||
|
<Grid item xs={12} md={3}>
|
||||||
|
<Box sx={{ backgroundColor: '#FFBC26', padding: '3px 12px' }}>Bin Location Labels</Box>
|
||||||
|
<Box sx={{ border: '1px solid black', padding: '3px 12px', height: '300px' }}>
|
||||||
|
{locationLabelData &&
|
||||||
|
locationLabelData.map((item, index) => (
|
||||||
|
<div key={index}>
|
||||||
|
{item.map((data, index) => (
|
||||||
|
<div key={index}>{data.label}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<div className={classes.buttondiv}>
|
<div className={classes.buttondiv}>
|
||||||
<MDButton color="primary">{'Print Labels'}</MDButton>
|
<MDButton color="primary">{'Print Labels'}</MDButton>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ function LabelingHome() {
|
|||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Labeling"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Breadcrumbs from 'components/Breadcrumbs';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { InventorySelectors } from 'redux/InventoryRedux';
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
import InventoryActions from 'redux/InventoryRedux';
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
|
import schema from 'services/ValidationServices';
|
||||||
|
|
||||||
function NewWarehouseDetails() {
|
function NewWarehouseDetails() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -54,7 +55,7 @@ function NewWarehouseDetails() {
|
|||||||
specs: '',
|
specs: '',
|
||||||
image: []
|
image: []
|
||||||
},
|
},
|
||||||
// validationSchema: schema.warehouseForm,
|
validationSchema: schema.warehouseForm,
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
WarehouseActions.createWarehouseAction({
|
WarehouseActions.createWarehouseAction({
|
||||||
@@ -80,6 +81,7 @@ function NewWarehouseDetails() {
|
|||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Create A Warehouse"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
@@ -90,17 +92,6 @@ function NewWarehouseDetails() {
|
|||||||
<Box mx={3} my={3}>
|
<Box mx={3} my={3}>
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<Box sx={{ backgroundColor: '#fff', padding: '30px' }}>
|
<Box sx={{ backgroundColor: '#fff', padding: '30px' }}>
|
||||||
<Box
|
|
||||||
component="div"
|
|
||||||
sx={{
|
|
||||||
fontSize: '22px',
|
|
||||||
letterSpacing: '0.01em',
|
|
||||||
color: '#000',
|
|
||||||
marginBottom: '30px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Form to Input
|
|
||||||
</Box>
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item xs={12} sm={6} md={6}>
|
||||||
<Box component="div" sx={{ marginBottom: '15px' }}>
|
<Box component="div" sx={{ marginBottom: '15px' }}>
|
||||||
@@ -122,7 +113,12 @@ function NewWarehouseDetails() {
|
|||||||
name="warehousename"
|
name="warehousename"
|
||||||
value={formik.values.warehousename}
|
value={formik.values.warehousename}
|
||||||
error={formik.touched.warehousename && Boolean(formik.errors.warehousename)}
|
error={formik.touched.warehousename && Boolean(formik.errors.warehousename)}
|
||||||
helperText={formik.touched.warehousename && formik.errors.warehousename}
|
helperText={
|
||||||
|
formik.touched.warehousename &&
|
||||||
|
formik.errors.warehousename && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.warehousename}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -145,7 +141,12 @@ function NewWarehouseDetails() {
|
|||||||
name="address"
|
name="address"
|
||||||
value={formik.values.address}
|
value={formik.values.address}
|
||||||
error={formik.touched.address && Boolean(formik.errors.address)}
|
error={formik.touched.address && Boolean(formik.errors.address)}
|
||||||
helperText={formik.touched.address && formik.errors.address}
|
helperText={
|
||||||
|
formik.touched.address &&
|
||||||
|
formik.errors.address && (
|
||||||
|
<div style={{ color: 'red' }}>{formik.errors.address}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -196,7 +197,7 @@ function NewWarehouseDetails() {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem key={''} value={''}>
|
<MenuItem disabled key={'none'} value={''}>
|
||||||
None Selected
|
None Selected
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{inventoryTypes &&
|
{inventoryTypes &&
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function SetupHome() {
|
|||||||
icon: <InventoryIcon width={96} height={96} color="#007AFF" />
|
icon: <InventoryIcon width={96} height={96} color="#007AFF" />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'User & Access',
|
name: 'User Access',
|
||||||
path: '/setup/users-access',
|
path: '/setup/users-access',
|
||||||
icon: <ProfileCircleIcon width={96} height={96} color="#007AFF" />
|
icon: <ProfileCircleIcon width={96} height={96} color="#007AFF" />
|
||||||
},
|
},
|
||||||
@@ -33,7 +33,7 @@ function SetupHome() {
|
|||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs route={[{ name: 'Home', path: '/home' }, { name: 'Setup' }]} />
|
<Breadcrumbs title="Warehouse Management System Setup" route={[{ name: 'Home', path: '/home' }, { name: 'Setup' }]} />
|
||||||
<TileBasic tiles={data} />
|
<TileBasic tiles={data} />
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ function SetupInventory() {
|
|||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="List Of Inventories"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import moment from 'moment';
|
||||||
|
import React, { useEffect, useState, useMemo } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Grid, Tabs, Tab } from '@mui/material';
|
||||||
|
import { makeStyles } from '@mui/styles';
|
||||||
import MDBox from 'components/MDBox';
|
import MDBox from 'components/MDBox';
|
||||||
|
|
||||||
import DashboardNavbar from 'components/DashboardNavbar';
|
import DashboardNavbar from 'components/DashboardNavbar';
|
||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import { makeStyles } from '@mui/styles';
|
|
||||||
import BasicTable from 'components/BasicTable';
|
|
||||||
import { Grid, TableBody, TableCell, TableRow } from '@mui/material';
|
|
||||||
import SearchBar from 'components/SearchBar';
|
import SearchBar from 'components/SearchBar';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
|
||||||
import MDButton from 'components/Button';
|
import MDButton from 'components/Button';
|
||||||
import { useState } from 'react';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
import { Tabs, Tab } from '@mui/material';
|
import { PwTablePanel } from 'components';
|
||||||
import TabPanel from 'components/Tabs';
|
|
||||||
|
import WarehouseActions, { WarehouseSelectors } from 'redux/WarehouseRedux';
|
||||||
|
import InventoryActions, { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
|
import PermissionsActions, { PermissionsSelectors } from 'redux/PermissionsRedux';
|
||||||
import UsersActions, { UsersSelectors } from 'redux/UsersRedux';
|
import UsersActions, { UsersSelectors } from 'redux/UsersRedux';
|
||||||
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
|
import RolesActions, { RolesSelectors } from 'redux/RolesRedux';
|
||||||
import { AuthSelectors } from 'redux/AuthRedux';
|
|
||||||
import { API } from 'constant';
|
import { API } from 'constant';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import moment from 'moment';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
iconSize: {
|
iconSize: {
|
||||||
@@ -34,6 +34,9 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
statusInactive: {
|
statusInactive: {
|
||||||
color: 'red'
|
color: 'red'
|
||||||
},
|
},
|
||||||
|
limitWidth: {
|
||||||
|
maxWidth: '20rem'
|
||||||
|
},
|
||||||
margin: {
|
margin: {
|
||||||
marginBottom: '20px',
|
marginBottom: '20px',
|
||||||
borderTop: '1px solid #ddd',
|
borderTop: '1px solid #ddd',
|
||||||
@@ -53,6 +56,10 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderRadius: '0.5rem'
|
borderRadius: '0.5rem'
|
||||||
},
|
},
|
||||||
|
rightPlaced: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0
|
||||||
|
},
|
||||||
tabs: {
|
tabs: {
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
'& .MuiButtonBase-root.MuiTab-root': {
|
'& .MuiButtonBase-root.MuiTab-root': {
|
||||||
@@ -83,52 +90,117 @@ function UserAccessScreen() {
|
|||||||
const [value, setValue] = useState(0);
|
const [value, setValue] = useState(0);
|
||||||
const usersData = useSelector(UsersSelectors.getUsersDetail);
|
const usersData = useSelector(UsersSelectors.getUsersDetail);
|
||||||
const rolesData = useSelector(RolesSelectors.getRolesDetail);
|
const rolesData = useSelector(RolesSelectors.getRolesDetail);
|
||||||
const currentUser = useSelector(AuthSelectors.getUser);
|
const warehouses = useSelector(WarehouseSelectors.getWarehouseDetail);
|
||||||
|
const inventories = useSelector(InventorySelectors.getInventoryDetail);
|
||||||
|
const actions = useSelector(PermissionsSelectors.getActionsDetail);
|
||||||
|
const permissions = useSelector(PermissionsSelectors.getPermissionsDetail);
|
||||||
const [userRecords, setUserRecords] = useState([]);
|
const [userRecords, setUserRecords] = useState([]);
|
||||||
const [rolesRecords, setRoleRecords] = useState([]);
|
const [rolesRecords, setRoleRecords] = useState([]);
|
||||||
|
const [userLoader, setUserLoader] = useState(false);
|
||||||
|
const [roleLoader, setRoleLoader] = useState(false);
|
||||||
|
const [roleApiCompleted, setRoleApiCompleted] = useState(false);
|
||||||
|
const [userApiCompleted, setUserApiCompleted] = useState(false);
|
||||||
|
const [originalUserRecords, setOriginalUserRecords] = useState([]);
|
||||||
|
const [originalRolesRecords, setOriginalRoleRecords] = useState([]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(!warehouses || warehouses.length === 0) && dispatch(WarehouseActions.warehouseDataAction({loader: 'loading-request', slug: API.GET_WAREHOUSE_DATA,method: 'get'}));
|
||||||
|
(!inventories || inventories.length === 0) && dispatch(InventoryActions.getInventoryAction({loader: 'loading-request', slug: API.GET_INVENTORY,method: 'get'}));
|
||||||
|
(!rolesData || rolesData.length === 0) && dispatch(RolesActions.getRolesAction({loader: 'loading-request', slug: API.GET_ROLES_DATA, method: 'get'}));
|
||||||
|
(!permissions || permissions.length === 0) && dispatch(PermissionsActions.getPermissionsAction({loader: 'loading-request', slug: API.GET_PERMISSIONS_DATA, method: 'get'}));
|
||||||
|
(!actions || actions.length === 0) && dispatch(PermissionsActions.getActionsAction({loader: 'loading-request', slug: API.GET_ACTIONS_DATA, method: 'get'}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const userHeadCells = [
|
const userHeadCells = [
|
||||||
{ id: 'full_name', label: 'User Name', isEditAnchor: true, value: record => record.fullName },
|
{ id: 'full_name', label: 'User Name', isEditAnchor: true, value: (record) => record.fullName },
|
||||||
{ id: 'phone_number', label: 'Phone Number', value: record => record.phoneNumber },
|
{ id: 'phone_number', label: 'Phone Number', value: (record) => record.phoneNumber },
|
||||||
{ id: 'role_name', label: 'Roles', value: record => record.role_name },
|
{ id: 'role_name', label: 'Roles', value: (record) => record.role_name },
|
||||||
{ id: 'updated_by_at', label: 'Last Updated By & Date', value: record => `${record.updatedBy?.fullName ? 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 ? 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>
|
id: 'updated_by_at',
|
||||||
: <span className={classes.statusInactive}>Inactive</span>
|
label: 'Last Updated By & Date',
|
||||||
|
value: (record) =>
|
||||||
|
`${record.updatedBy?.fullName ? 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 ? 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={classes.statusInactive}>Inactive</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const rolesHeadCells = [
|
const rolesHeadCells = [
|
||||||
{ id: 'role', label: 'Role' },
|
{ id: 'role', label: 'Role', isEditAnchor: true, value: record => record.name },
|
||||||
{ id: 'permissions', label: 'Permissions' },
|
{ id: 'warehouse', label: 'Warehouse', limitWidth: true, value: record => {
|
||||||
{ id: 'status', label: 'Status' }
|
const roleWh = record.permissions?.warehouseScopes;
|
||||||
|
return warehouses && roleWh && roleWh.length === warehouses.length ? 'All' : roleWh
|
||||||
|
? warehouses.filter(wh => roleWh.findIndex(whCurr => whCurr.id === wh._id) > -1).map(wh => wh.name).join(', ') : '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ id: 'inventory', label: 'Inventories', limitWidth: true, value: record => {
|
||||||
|
const roleIn = record.permissions?.inventoryScopes;
|
||||||
|
return inventories && roleIn && roleIn.length === inventories.length ? 'All' : roleIn
|
||||||
|
? inventories.filter(inv => roleIn.findIndex(inCurr => inCurr.id === inv._id) > -1).map(inv => inv.name).join(', ') : '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ id: 'actions', label: 'Actions', limitWidth: true, value: record => actions && record.permissions?.actions
|
||||||
|
&& record.permissions?.actions?.length === actions?.length ? 'All' : record.permissions?.actions
|
||||||
|
? record.permissions?.actions.join(', ') : ''},
|
||||||
|
{ id: 'visibilities', label: 'App Modules', limitWidth: true, value: record => permissions && record.permissions?.allowedUIModules
|
||||||
|
&& record.permissions?.allowedUIModules?.length === permissions?.length ? 'All' : record.permissions?.allowedUIModules
|
||||||
|
? record.permissions?.allowedUIModules.join(', ') : ''},
|
||||||
|
{ id: 'status', label: 'Status', value: record => record.status === 'ACTIVE' ? <span className={classes.statusActive}>Active</span>
|
||||||
|
: <span className={classes.statusInactive}>Inactive</span> }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
const usersHandler = () => {
|
const usersHandler = () => {
|
||||||
|
setUserLoader(true);
|
||||||
dispatch(
|
dispatch(
|
||||||
UsersActions.getUsersAction({
|
UsersActions.getUsersAction({
|
||||||
loader: 'loading-request',
|
loader: 'loading-request',
|
||||||
slug: API.GET_USERS_DATA,
|
slug: API.GET_USERS_DATA,
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
callback: () => {
|
||||||
|
setUserLoader(false);
|
||||||
|
setUserApiCompleted(true);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const rolesHandler = () => {
|
const rolesHandler = () => {
|
||||||
|
setRoleLoader(true);
|
||||||
dispatch(
|
dispatch(
|
||||||
RolesActions.getRolesAction({
|
RolesActions.getRolesAction({
|
||||||
loader: 'loading-request',
|
loader: 'loading-request',
|
||||||
slug: API.GET_ROLES_DATA,
|
slug: API.GET_ROLES_DATA,
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
callback: () => {
|
||||||
|
setRoleLoader(false);
|
||||||
|
setRoleApiCompleted(true);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useMemo(() => rolesHandler(), []);
|
useMemo(() => rolesHandler(), []);
|
||||||
|
useMemo(() => usersHandler(), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (usersData.length) {
|
if (usersData.length) {
|
||||||
@@ -137,6 +209,7 @@ function UserAccessScreen() {
|
|||||||
item.role_name = item.roles.map((role) => role.name).join(',');
|
item.role_name = item.roles.map((role) => role.name).join(',');
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
setOriginalUserRecords(users);
|
||||||
setUserRecords(users);
|
setUserRecords(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,13 +217,14 @@ function UserAccessScreen() {
|
|||||||
let roles = JSON.parse(JSON.stringify(rolesData));
|
let roles = JSON.parse(JSON.stringify(rolesData));
|
||||||
roles = roles.map((item) => {
|
roles = roles.map((item) => {
|
||||||
item.name = item.name.split('-').join(' ').toUpperCase();
|
item.name = item.name.split('-').join(' ').toUpperCase();
|
||||||
item.permissions = item.permissions?.allowedUIModules?.join(',');
|
// item.permissions = item.permissions?.allowedUIModules?.join(',');
|
||||||
if (!item.permissions) {
|
if (!item.permissions) {
|
||||||
item.permissions = 'NA';
|
item.permissions = 'NA';
|
||||||
}
|
}
|
||||||
item.status = item.status ? 'ACTIVE' : 'INACTIVE';
|
item.status = item.status ? 'ACTIVE' : 'INACTIVE';
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
setOriginalRoleRecords(roles);
|
||||||
setRoleRecords(roles);
|
setRoleRecords(roles);
|
||||||
}
|
}
|
||||||
}, [rolesData, usersData]);
|
}, [rolesData, usersData]);
|
||||||
@@ -159,94 +233,81 @@ function UserAccessScreen() {
|
|||||||
setValue(val);
|
setValue(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledTableRow = styled(TableRow)(({ theme }) => ({
|
const handleSearch = (e, currentTab) => {
|
||||||
'&:nth-of-type(even)': {
|
const value = e.target.value;
|
||||||
backgroundColor: theme.palette.action.hover
|
let records = currentTab === 0 ? originalUserRecords : originalRolesRecords;
|
||||||
}
|
records = JSON.parse(JSON.stringify(records));
|
||||||
}));
|
records.forEach(record => record.status = record.status ? 'ACTIVE' : 'INACTIVE');
|
||||||
|
let searchList = currentTab === 0 ? ['fullName', 'phoneNumber', 'role_name', 'status'] : ['name', 'permissions', 'status'];
|
||||||
const rowRenders = userRecords && userRecords.map(record => {
|
const setter = currentTab === 0 ? setUserRecords : setRoleRecords;
|
||||||
const canEdit = columnConfig => columnConfig.isEditAnchor && currentUser.email !== record.email;
|
searchList = searchList.concat(['createdBy.fullName', 'createdAt', 'updatedBy.fullName', 'updatedAt']);
|
||||||
return <StyledTableRow key={record.id}>
|
const filteredRecords = records.filter(record => searchList.some(field => {
|
||||||
{userHeadCells.map((columnConfig, key) => <TableCell key={key} onClick={() => canEdit(columnConfig) && navigate('/setup/users-access/edit-user', {state: {user: record}})}>
|
let recordInner = {...record};
|
||||||
{canEdit(columnConfig) ? <span className={classes.iconwrap}>
|
if (field.indexOf('.') > -1) {
|
||||||
<EditIcon className={classes.iconSize}/>
|
field = field.split('.');
|
||||||
{columnConfig.value(record)}
|
recordInner = recordInner[field[0]];
|
||||||
</span> : <span>{columnConfig.value(record)}</span>}
|
field = field[1];
|
||||||
</TableCell>)}
|
}
|
||||||
</StyledTableRow>;
|
return recordInner && recordInner[field] !== undefined && typeof recordInner[field] === 'string'
|
||||||
});
|
&& recordInner[field].toLowerCase().indexOf(value?.toLowerCase()) > -1;
|
||||||
|
}));
|
||||||
|
records.forEach(record => record.status = record.status === 'ACTIVE');
|
||||||
|
setter(filteredRecords);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Access Details"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
{ name: 'Users and Access', path: '/setup/users-access' }
|
{ name: 'User Access' }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<MDBox px={0} py={3}>
|
<MDBox px={5} py={3}>
|
||||||
<Grid container spacing={1} className={classes.margin}>
|
<Grid container spacing={1} className={classes.margin + ' w-100 ms-0'}>
|
||||||
<Grid item xs={12} sm={4} md={4} className='ps-2 pt-0'>
|
<Grid item xs={12} sm={4} md={4} className="ps-0 pt-0">
|
||||||
<Tabs value={value} className={`p-0 h-100 ${classes.tabs}`} onChange={handleTabs}>
|
<Tabs value={value} className={`p-0 h-100 ${classes.tabs}`} onChange={handleTabs}>
|
||||||
<Tab label="Roles" onClick={() => rolesHandler()} />
|
|
||||||
<Tab label="Users" onClick={() => usersHandler()} />
|
<Tab label="Users" onClick={() => usersHandler()} />
|
||||||
|
<Tab label="Roles" onClick={() => rolesHandler()} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={4} md={6} className='py-2' style={{ display: 'flex', alignItems: 'center' }}>
|
<Grid
|
||||||
<SearchBar />
|
item
|
||||||
|
xs={12}
|
||||||
|
sm={4}
|
||||||
|
md={6}
|
||||||
|
className="py-2"
|
||||||
|
style={{ display: 'flex', alignItems: 'center', justifyContent: 'end' }}
|
||||||
|
>
|
||||||
|
<SearchBar onChange={e => handleSearch(e, value)} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={4} md={2} className='py-2' style={{ display: 'flex', alignItems: 'center' }}>
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
sm={4}
|
||||||
|
md={2}
|
||||||
|
className="py-2"
|
||||||
|
style={{ display: 'flex', alignItems: 'center', justifyContent: 'end' }}
|
||||||
|
>
|
||||||
<MDButton
|
<MDButton
|
||||||
color="primary"
|
color="primary"
|
||||||
size="medium"
|
size="medium"
|
||||||
onClick={() => navigate(`/setup/users-access/${value === 0 ? 'create-role' : 'create-user'}`)}
|
onClick={() =>
|
||||||
|
navigate(`/setup/users-access/${value === 0 ? 'create-user' : 'create-role'}`)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{value === 0 ? '+ CREATE ROLE' : '+ CREATE USER'}
|
{value === 0 ? '+ CREATE USER' : '+ CREATE ROLE'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid px={2}>
|
<Grid>
|
||||||
<TabPanel value={value} index={0} className={classes.radialBorder}>
|
<PwTablePanel classes={classes} headCells={userHeadCells} id="user-list" index={0} loader={userLoader} dataFetched={userApiCompleted}
|
||||||
<BasicTable
|
records={userRecords} navUrl='/setup/users-access/edit-user' table="user" value={value} />
|
||||||
headCells={rolesHeadCells}
|
<PwTablePanel classes={classes} headCells={rolesHeadCells} id="role-list" index={1} loader={roleLoader} dataFetched={roleApiCompleted}
|
||||||
records={rolesRecords}
|
records={rolesRecords} navUrl='/setup/users-access/edit-role' table="role" value={value} />
|
||||||
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>
|
|
||||||
{rowRenders}
|
|
||||||
</TableBody> : 'No Records to Display'}
|
|
||||||
</BasicTable>
|
|
||||||
</TabPanel>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function WarehouseScreen() {
|
|||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="List of Warehouses"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
import { Box, TableBody, TableCell, TableRow } from '@mui/material';
|
import { Box, Grid, TableBody, TableCell, TableRow } from '@mui/material';
|
||||||
import DashboardNavbar from 'components/DashboardNavbar';
|
import DashboardNavbar from 'components/DashboardNavbar';
|
||||||
import DashboardLayout from 'layouts/DashboardLayout';
|
import DashboardLayout from 'layouts/DashboardLayout';
|
||||||
import { makeStyles } from '@mui/styles';
|
import { makeStyles } from '@mui/styles';
|
||||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
import React, { useState } from 'react';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
|
||||||
import Select from '@mui/material/Select';
|
|
||||||
import React from 'react';
|
|
||||||
import SearchBar from 'components/SearchBar';
|
|
||||||
import BasicTable from 'components/BasicTable';
|
import BasicTable from 'components/BasicTable';
|
||||||
import Barcodeimage from 'assets/images/barcode-number.png';
|
|
||||||
import MDButton from 'components/Button';
|
import MDButton from 'components/Button';
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
import Checkbox from '@mui/material/Checkbox';
|
||||||
|
|
||||||
const label = { inputProps: { 'aria-label': 'Checkbox demo' } };
|
const label = { inputProps: { 'aria-label': 'Checkbox demo' } };
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
import Dropdown from 'components/Dropdown';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
|
import WidgetActions from 'redux/WidgetRedux';
|
||||||
|
import { API } from 'constant';
|
||||||
|
import MDBox from 'components/MDBox';
|
||||||
|
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||||
|
import ProductActions from 'redux/ProductsRedux';
|
||||||
|
import { ProductSelectors } from 'redux/ProductsRedux';
|
||||||
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
|
import QRcode from 'components/QRcode';
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
|
nodataStyle: {
|
||||||
|
height: '200px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: '600%'
|
||||||
|
},
|
||||||
labelSize: {
|
labelSize: {
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
letterSpacing: '0.01em',
|
letterSpacing: '0.01em',
|
||||||
@@ -32,69 +44,6 @@ const useStyles = makeStyles({
|
|||||||
margin: '52px 0px'
|
margin: '52px 0px'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const records = [
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: 'Senectus',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: 'Senectus',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
row: 'Nulla',
|
|
||||||
label: 'Mauris',
|
|
||||||
bay: 'Senectus',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const recordsNew = [
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
},
|
|
||||||
{
|
|
||||||
warehouse: 'Ipsum',
|
|
||||||
zone: 'Vivera',
|
|
||||||
area: 'Nisi',
|
|
||||||
barcodenumber: '2085550112',
|
|
||||||
barcodeimage: Barcodeimage
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const headCells = [
|
const headCells = [
|
||||||
{
|
{
|
||||||
@@ -110,15 +59,15 @@ const headCells = [
|
|||||||
label: 'Subfamily'
|
label: 'Subfamily'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Name',
|
id: 'formalName',
|
||||||
label: 'Name'
|
label: 'Name'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Manufacture',
|
id: 'manufacturer',
|
||||||
label: 'Manufacture'
|
label: 'Manufacture'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Size',
|
id: 'size',
|
||||||
label: 'Size'
|
label: 'Size'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -136,11 +85,11 @@ const headCellsNew = [
|
|||||||
label: 'Inventory Name'
|
label: 'Inventory Name'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Item Name',
|
id: 'formalName',
|
||||||
label: 'Item Name'
|
label: 'Item Name'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Item Description',
|
id: 'description',
|
||||||
label: 'Item Description'
|
label: 'Item Description'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -152,24 +101,103 @@ const headCellsNew = [
|
|||||||
label: 'Barcode'
|
label: 'Barcode'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function WidgetLabel() {
|
function WidgetLabel() {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [personName, setPersonName] = React.useState([]);
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const [labelData, setLabelData] = useState([]);
|
||||||
const {
|
const [inventoryId, setInventoryId] = useState('');
|
||||||
target: { value }
|
const [familyId, setFamilyId] = useState('');
|
||||||
} = event;
|
const [subFamilyId, setSubFamilyId] = useState('');
|
||||||
setPersonName(
|
const [allProductData, setAllProductData] = useState([]);
|
||||||
// On autofill we get a stringified value.
|
const [filterClick, setFilterClick] = useState(false);
|
||||||
typeof value === 'string' ? value.split(',') : value
|
|
||||||
|
const inventoryData = useSelector(InventorySelectors.getInventoryDetail);
|
||||||
|
const familyData = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||||
|
const subFamilyData = useSelector(WidgetSelectors.getWidgetsByParentId(familyId));
|
||||||
|
const productData = useSelector(ProductSelectors.getProductDetail);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
dispatch(
|
||||||
|
InventoryActions.getInventoryAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_INVENTORY,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (productData.result && filterClick) {
|
||||||
|
setAllProductData(productData?.result);
|
||||||
|
}
|
||||||
|
}, [productData, filterClick]);
|
||||||
|
|
||||||
|
const inventoryChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
setInventoryId(id);
|
||||||
|
setFamilyId('');
|
||||||
|
setSubFamilyId('');
|
||||||
|
dispatch(
|
||||||
|
WidgetActions.widgetRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const familyChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
setFamilyId(id);
|
||||||
|
setSubFamilyId('');
|
||||||
|
dispatch(
|
||||||
|
WidgetActions.widgetRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const subFamilyChange = (event) => {
|
||||||
|
const id = event.target.value;
|
||||||
|
setSubFamilyId(id);
|
||||||
|
dispatch(
|
||||||
|
WidgetActions.widgetRequest({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterHandler = () => {
|
||||||
|
setFilterClick(true);
|
||||||
|
dispatch(
|
||||||
|
ProductActions.getProductByIdAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: `${API.GET_PRODUCT_BY_ID}${inventoryId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTableItem = (e, item) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
setLabelData((prev) => [...prev, item]);
|
||||||
|
} else {
|
||||||
|
const filterData = labelData.filter((item2) => item2._id !== item._id);
|
||||||
|
setLabelData(filterData);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
|
title="Search And Print Location Labels"
|
||||||
route={[
|
route={[
|
||||||
{ name: 'Home', path: '/home' },
|
{ name: 'Home', path: '/home' },
|
||||||
{ name: 'Setup', path: '/setup' },
|
{ name: 'Setup', path: '/setup' },
|
||||||
@@ -177,159 +205,104 @@ function WidgetLabel() {
|
|||||||
{ name: 'Widget Label' }
|
{ name: 'Widget Label' }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Box mx={3} my={3}>
|
<MDBox px={5} py={5}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} sm={6} md={3}>
|
||||||
|
<Dropdown
|
||||||
|
label="Select Inventory"
|
||||||
|
dropdownData={inventoryData}
|
||||||
|
value={inventoryId}
|
||||||
|
onChange={inventoryChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={3}>
|
||||||
|
<Dropdown
|
||||||
|
label="Select Family"
|
||||||
|
dropdownData={familyData}
|
||||||
|
value={familyId}
|
||||||
|
onChange={familyChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={3}>
|
||||||
|
<Dropdown
|
||||||
|
label="Select Sub Family"
|
||||||
|
value={subFamilyId}
|
||||||
|
dropdownData={subFamilyData}
|
||||||
|
onChange={subFamilyChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={3}>
|
||||||
|
<MDButton
|
||||||
|
color="primary"
|
||||||
|
sx={{ minWidth: '100%', marginTop: '50px', padding: '13px 40px' }}
|
||||||
|
onClick={() => filterHandler()}
|
||||||
|
>
|
||||||
|
{'Filter'}
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
<Box
|
<Box
|
||||||
sx ={{
|
sx={{
|
||||||
display: 'grid',
|
marginTop: '24px',
|
||||||
gridTemplateColumns: ' repeat(5, 1fr)',
|
backgroundColor: '#FFFFFF',
|
||||||
gridColumnGap :'20px'
|
overflowX: 'auto',
|
||||||
|
overflowY: 'auto',
|
||||||
|
height: '60vh'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Select Inventory
|
|
||||||
</Box>
|
|
||||||
<Box className={classes.customLabel}>
|
|
||||||
<Select
|
|
||||||
multiple
|
|
||||||
displayEmpty
|
|
||||||
value={personName}
|
|
||||||
input={<OutlinedInput />}
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (selected.length === 0) {
|
|
||||||
return 'Placeholder';
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected.join(', ');
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
|
||||||
sx={{
|
|
||||||
width: '100%'
|
|
||||||
}}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem disabled value="">
|
|
||||||
Placeholder
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem>Lorem Ipsum</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Select Family
|
|
||||||
</Box>
|
|
||||||
<Box className={classes.customLabel}>
|
|
||||||
<Select
|
|
||||||
multiple
|
|
||||||
displayEmpty
|
|
||||||
value={personName}
|
|
||||||
input={<OutlinedInput />}
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (selected.length === 0) {
|
|
||||||
return 'Placeholder';
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected.join(', ');
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
|
||||||
sx={{
|
|
||||||
width: '100%'
|
|
||||||
}}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem disabled value="">
|
|
||||||
Placeholder
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem>Lorem Ipsum</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Select Sub Family
|
|
||||||
</Box>
|
|
||||||
<Box className={classes.customLabel}>
|
|
||||||
<Select
|
|
||||||
multiple
|
|
||||||
displayEmpty
|
|
||||||
value={personName}
|
|
||||||
input={<OutlinedInput />}
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (selected.length === 0) {
|
|
||||||
return 'Placeholder';
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected.join(', ');
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'Without label' }}
|
|
||||||
sx={{
|
|
||||||
width: '100%'
|
|
||||||
}}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem disabled value="">
|
|
||||||
Placeholder
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem>Lorem Ipsum</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Box component="div" className={classes.labelSize}>
|
|
||||||
Search Keyword
|
|
||||||
</Box>
|
|
||||||
<Box className={classes.customLabel}>
|
|
||||||
<SearchBar />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<MDButton color="primary" sx={{ minWidth:'100%', marginTop:'30px', padding:'13px 40px' }} >{'Filter'}</MDButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ marginTop: '24px', backgroundColor: '#FFFFFF' }}>
|
|
||||||
<BasicTable
|
<BasicTable
|
||||||
headCells={headCells}
|
headCells={headCells}
|
||||||
records={records}
|
records={allProductData}
|
||||||
backgroundColor="#E5E5E5"
|
backgroundColor="#E5E5E5"
|
||||||
color="#8D8D8D"
|
color="#8D8D8D"
|
||||||
>
|
>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{records &&
|
{filterClick && allProductData.length ? (
|
||||||
records.map((item) => (
|
allProductData &&
|
||||||
|
allProductData.map((item) => (
|
||||||
<TableRow key={item.id}>
|
<TableRow key={item.id}>
|
||||||
<TableCell><Checkbox {...label} sx={{ marginRight:'2px' }} /> {item.warehouse}</TableCell>
|
|
||||||
<TableCell>{item.zone}</TableCell>
|
|
||||||
<TableCell>{item.area}</TableCell>
|
|
||||||
<TableCell>{item.row}</TableCell>
|
|
||||||
<TableCell>{item.label}</TableCell>
|
|
||||||
<TableCell>{item.bay}</TableCell>
|
|
||||||
<TableCell>{item.barcodenumber}</TableCell>
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<img src={item.barcodeimage} alt="img" width="200px" />
|
<Checkbox
|
||||||
|
{...label}
|
||||||
|
sx={{ marginRight: '2px' }}
|
||||||
|
onChange={(e) => getTableItem(e, item)}
|
||||||
|
/>
|
||||||
|
{item?.inventory?.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{item?.widgetfamily?.name}</TableCell>
|
||||||
|
<TableCell>{item?.location?.sub_levels}</TableCell>
|
||||||
|
<TableCell>{item?.formalName}</TableCell>
|
||||||
|
<TableCell>{item?.manufacturer}</TableCell>
|
||||||
|
<TableCell>{item?.size}</TableCell>
|
||||||
|
<TableCell>{item?._id}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<QRcode payload={item._id} width={100} height={100} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow className={classes.nodataStyle}>No Data</TableRow>
|
||||||
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</BasicTable>
|
</BasicTable>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginTop: '24px', backgroundColor: '#FFFFFF' }}>
|
<Box sx={{ marginTop: '24px', backgroundColor: '#FFFFFF' }}>
|
||||||
<BasicTable
|
<BasicTable
|
||||||
headCells={headCellsNew}
|
headCells={headCellsNew}
|
||||||
records={records}
|
records={labelData}
|
||||||
backgroundColor="#E5E5E5"
|
backgroundColor="#E5E5E5"
|
||||||
color="#8D8D8D"
|
color="#8D8D8D"
|
||||||
>
|
>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{recordsNew &&
|
{labelData &&
|
||||||
recordsNew.map((item) => (
|
labelData.map((item) => (
|
||||||
<TableRow key={item.id}>
|
<TableRow key={item.id}>
|
||||||
<TableCell>{item.warehouse}</TableCell>
|
<TableCell>{item?.inventory?.name}</TableCell>
|
||||||
<TableCell>{item.zone}</TableCell>
|
<TableCell>{item.formalName}</TableCell>
|
||||||
<TableCell>{item.area}</TableCell>
|
<TableCell>{item.description}</TableCell>
|
||||||
<TableCell>{item.barcodenumber}</TableCell>
|
<TableCell>{item._id}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<img src={item.barcodeimage} alt="img" width="200px" />
|
<QRcode payload={item._id} width={100} height={100} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
@@ -339,7 +312,7 @@ function WidgetLabel() {
|
|||||||
<div className={classes.buttondiv}>
|
<div className={classes.buttondiv}>
|
||||||
<MDButton color="primary">{'Print Labels'}</MDButton>
|
<MDButton color="primary">{'Print Labels'}</MDButton>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</MDBox>
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ const { Types, Creators } = createActions({
|
|||||||
addInventoryFailure: ['error'],
|
addInventoryFailure: ['error'],
|
||||||
updateInventoryAction: ['payload'],
|
updateInventoryAction: ['payload'],
|
||||||
updateInventorySuccess: ['data'],
|
updateInventorySuccess: ['data'],
|
||||||
|
deleteInventoryAction: ['payload'],
|
||||||
|
deleteInventorySuccess: ['data'],
|
||||||
updateInventoryFailure: ['error'],
|
updateInventoryFailure: ['error'],
|
||||||
getInventoryTypesAction: ['payload'],
|
getInventoryTypesAction: ['payload'],
|
||||||
getInventoryTypesSuccess: ['data'],
|
getInventoryTypesSuccess: ['data'],
|
||||||
@@ -98,6 +100,21 @@ export const onUpdateInventorySuccess = (state, { data }) =>
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const onDeleteInventoryAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onDeleteInventorySuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
getInventoryDetail: data.deletedInventoryID
|
||||||
|
? [...state.getInventoryDetail.filter((x) => x._id !== data.deletedInventoryID)]
|
||||||
|
: state.getInventoryDetail
|
||||||
|
});
|
||||||
|
|
||||||
export const onUpdateInventoryFailure = (state, { error }) =>
|
export const onUpdateInventoryFailure = (state, { error }) =>
|
||||||
state.merge({
|
state.merge({
|
||||||
fetching: _.without(state.fetching, error?.loader),
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
@@ -133,6 +150,8 @@ export const inventoryReducer = createReducer(INITIAL_STATE, {
|
|||||||
[Types.ADD_INVENTORY_FAILURE]: onAddInventoryFailure,
|
[Types.ADD_INVENTORY_FAILURE]: onAddInventoryFailure,
|
||||||
[Types.UPDATE_INVENTORY_ACTION]: onUpdateInventoryAction,
|
[Types.UPDATE_INVENTORY_ACTION]: onUpdateInventoryAction,
|
||||||
[Types.UPDATE_INVENTORY_SUCCESS]: onUpdateInventorySuccess,
|
[Types.UPDATE_INVENTORY_SUCCESS]: onUpdateInventorySuccess,
|
||||||
|
[Types.DELETE_INVENTORY_ACTION]: onDeleteInventoryAction,
|
||||||
|
[Types.DELETE_INVENTORY_SUCCESS]: onDeleteInventorySuccess,
|
||||||
[Types.UPDATE_INVENTORY_FAILURE]: onUpdateInventoryFailure,
|
[Types.UPDATE_INVENTORY_FAILURE]: onUpdateInventoryFailure,
|
||||||
[Types.GET_INVENTORY_TYPES_ACTION]: onGetInventoryTypesAction,
|
[Types.GET_INVENTORY_TYPES_ACTION]: onGetInventoryTypesAction,
|
||||||
[Types.GET_INVENTORY_TYPES_SUCCESS]: onGetInventoryTypesSuccess,
|
[Types.GET_INVENTORY_TYPES_SUCCESS]: onGetInventoryTypesSuccess,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ const { Types, Creators } = createActions({
|
|||||||
addItemSuccess: ['data'],
|
addItemSuccess: ['data'],
|
||||||
editItemRequest: ['payload'],
|
editItemRequest: ['payload'],
|
||||||
editItemSuccess: ['data'],
|
editItemSuccess: ['data'],
|
||||||
|
deleteItemRequest: ['payload'],
|
||||||
|
deleteItemSuccess: ['data'],
|
||||||
oneItemRequest: ['payload'],
|
oneItemRequest: ['payload'],
|
||||||
oneItemSuccess: ['data']
|
oneItemSuccess: ['data']
|
||||||
});
|
});
|
||||||
@@ -91,6 +93,18 @@ export const onEditItemSuccess = (state, { data }) =>
|
|||||||
item: null
|
item: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const onDeleteItemRequest = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onDeleteItemSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
export const onItemFailure = (state, { error }) =>
|
export const onItemFailure = (state, { error }) =>
|
||||||
state.merge({
|
state.merge({
|
||||||
fetching: _.without(state.fetching, error?.loader),
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
@@ -106,6 +120,8 @@ export const itemReducer = createReducer(INITIAL_STATE, {
|
|||||||
[Types.ADD_ITEM_SUCCESS]: onAddItemSuccess,
|
[Types.ADD_ITEM_SUCCESS]: onAddItemSuccess,
|
||||||
[Types.EDIT_ITEM_REQUEST]: onEditItemRequest,
|
[Types.EDIT_ITEM_REQUEST]: onEditItemRequest,
|
||||||
[Types.EDIT_ITEM_SUCCESS]: onEditItemSuccess,
|
[Types.EDIT_ITEM_SUCCESS]: onEditItemSuccess,
|
||||||
|
[Types.DELETE_ITEM_REQUEST]: onDeleteItemRequest,
|
||||||
|
[Types.DELETE_ITEM_SUCCESS]: onDeleteItemSuccess,
|
||||||
[Types.ONE_ITEM_REQUEST]: onOneItemRequest,
|
[Types.ONE_ITEM_REQUEST]: onOneItemRequest,
|
||||||
[Types.ONE_ITEM_SUCCESS]: onOneItemSuccess
|
[Types.ONE_ITEM_SUCCESS]: onOneItemSuccess
|
||||||
});
|
});
|
||||||
|
|||||||
54
src/redux/LabellingRedux.js
Normal file
54
src/redux/LabellingRedux.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { createActions, createReducer } from 'reduxsauce';
|
||||||
|
import Immutable from 'seamless-immutable';
|
||||||
|
import _ from 'underscore';
|
||||||
|
import { getFetchingValue, getErrorValue } from '../services/Utils';
|
||||||
|
|
||||||
|
/* ------------- Types and Action Creators ------------- */
|
||||||
|
const { Types, Creators } = createActions({
|
||||||
|
getLabelAction: ['payload'],
|
||||||
|
getLabelSuccess: ['data'],
|
||||||
|
getLabelFailure: ['error']
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LabellingTypes = Types;
|
||||||
|
const LabellingActions = Creators;
|
||||||
|
export default LabellingActions;
|
||||||
|
|
||||||
|
/* ------------- Initial State ------------- */
|
||||||
|
export const INITIAL_STATE = Immutable({
|
||||||
|
getLabelDetail: [],
|
||||||
|
getLabelLoading: false,
|
||||||
|
getLabelerror: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------- Selectors ------------- */
|
||||||
|
export const LabellingSelectors = {
|
||||||
|
getLabelDetail: (state) => state.labelling.getLabelDetail
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------- Reducers ------------- */
|
||||||
|
export const onGetLabelAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetLabelSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
getLabelDetail: data.getLabelDetail
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetLabelFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------- Hookup Reducers To Types ------------- */
|
||||||
|
export const labellingReducer = createReducer(INITIAL_STATE, {
|
||||||
|
[Types.GET_LABEL_ACTION]: onGetLabelAction,
|
||||||
|
[Types.GET_LABEL_SUCCESS]: onGetLabelSuccess,
|
||||||
|
[Types.GET_LABEL_FAILURE]: onGetLabelFailure
|
||||||
|
});
|
||||||
@@ -5,6 +5,9 @@ import { getFetchingValue, getErrorValue } from '../services/Utils';
|
|||||||
|
|
||||||
/* ------------- Types and Action Creators ------------- */
|
/* ------------- Types and Action Creators ------------- */
|
||||||
const { Types, Creators } = createActions({
|
const { Types, Creators } = createActions({
|
||||||
|
getProductByIdAction: ['payload'],
|
||||||
|
getProductByIdSuccess: ['data'],
|
||||||
|
getProductByIdFailure: ['error'],
|
||||||
addProductAction: ['payload'],
|
addProductAction: ['payload'],
|
||||||
addProductSuccess: ['data'],
|
addProductSuccess: ['data'],
|
||||||
addProductFailure: ['error']
|
addProductFailure: ['error']
|
||||||
@@ -18,15 +21,35 @@ export default ProductActions;
|
|||||||
export const INITIAL_STATE = Immutable({
|
export const INITIAL_STATE = Immutable({
|
||||||
addProductDetail: [],
|
addProductDetail: [],
|
||||||
addProductLoading: false,
|
addProductLoading: false,
|
||||||
addProducterror: {}
|
addProducterror: {},
|
||||||
|
getProductByIdDetail: []
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ------------- Selectors ------------- */
|
/* ------------- Selectors ------------- */
|
||||||
export const ProductSelectors = {
|
export const ProductSelectors = {
|
||||||
addProductDetail: (state) => state.product.productDetail
|
addProductDetail: (state) => state.product.productDetail,
|
||||||
|
getProductDetail: (state) => state.product.getProductByIdDetail
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------- Reducers ------------- */
|
/* ------------- Reducers ------------- */
|
||||||
|
export const onGetProductByIdAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetProductByIdSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
getProductByIdDetail: data.getProductByIdDetail
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetProductByIdFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
export const onAddProductAction = (state, { payload }) =>
|
export const onAddProductAction = (state, { payload }) =>
|
||||||
state.merge({
|
state.merge({
|
||||||
fetching: _.uniq([state.fetching, payload?.loader]),
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
@@ -48,6 +71,10 @@ export const onAddProductFailure = (state, { error }) =>
|
|||||||
|
|
||||||
/* ------------- Hookup Reducers To Types ------------- */
|
/* ------------- Hookup Reducers To Types ------------- */
|
||||||
export const productReducer = createReducer(INITIAL_STATE, {
|
export const productReducer = createReducer(INITIAL_STATE, {
|
||||||
|
[Types.GET_PRODUCT_BY_ID_ACTION]: onGetProductByIdAction,
|
||||||
|
[Types.GET_PRODUCT_BY_ID_SUCCESS]: onGetProductByIdSuccess,
|
||||||
|
[Types.GET_PRODUCT_BY_ID_FAILURE]: onGetProductByIdFailure,
|
||||||
|
[Types.ADD_PRODUCT_FAILURE]: onAddProductFailure,
|
||||||
[Types.ADD_PRODUCT_ACTION]: onAddProductAction,
|
[Types.ADD_PRODUCT_ACTION]: onAddProductAction,
|
||||||
[Types.ADD_PRODUCT_SUCCESS]: onAddProductSuccess,
|
[Types.ADD_PRODUCT_SUCCESS]: onAddProductSuccess,
|
||||||
[Types.ADD_PRODUCT_FAILURE]: onAddProductFailure
|
[Types.ADD_PRODUCT_FAILURE]: onAddProductFailure
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ const { Types, Creators } = createActions({
|
|||||||
|
|
||||||
editWarehouseAction: ['payload'],
|
editWarehouseAction: ['payload'],
|
||||||
editWarehouseSuccess: ['data'],
|
editWarehouseSuccess: ['data'],
|
||||||
editWarehouseFailure: ['error']
|
editWarehouseFailure: ['error'],
|
||||||
|
|
||||||
|
deleteWarehouseAction: ['payload'],
|
||||||
|
deleteWarehouseSuccess: ['data']
|
||||||
});
|
});
|
||||||
|
|
||||||
export const WarehouseTypes = Types;
|
export const WarehouseTypes = Types;
|
||||||
@@ -96,6 +99,21 @@ export const onEditWarehouseSuccess = (state, { data }) =>
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const onDeleteWarehouseAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onDeleteWarehouseSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
warehouseDetail: data?.deletedWarehouseID
|
||||||
|
? [...state.warehouseDetail.filter((x) => x._id !== data?.deletedWarehouseID)]
|
||||||
|
: state.warehouseDetail
|
||||||
|
});
|
||||||
|
|
||||||
export const onEditWarehouseFailure = (state, { error }) =>
|
export const onEditWarehouseFailure = (state, { error }) =>
|
||||||
state.merge({
|
state.merge({
|
||||||
fetching: _.without(state.fetching, error?.loader),
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
@@ -113,5 +131,7 @@ export const warehouseReducer = createReducer(INITIAL_STATE, {
|
|||||||
|
|
||||||
[Types.EDIT_WAREHOUSE_ACTION]: onEditWarehouseAction,
|
[Types.EDIT_WAREHOUSE_ACTION]: onEditWarehouseAction,
|
||||||
[Types.EDIT_WAREHOUSE_SUCCESS]: onEditWarehouseSuccess,
|
[Types.EDIT_WAREHOUSE_SUCCESS]: onEditWarehouseSuccess,
|
||||||
[Types.EDIT_WAREHOUSE_FAILURE]: onEditWarehouseFailure
|
[Types.EDIT_WAREHOUSE_FAILURE]: onEditWarehouseFailure,
|
||||||
|
[Types.DELETE_WAREHOUSE_ACTION]: onDeleteWarehouseAction,
|
||||||
|
[Types.DELETE_WAREHOUSE_SUCCESS]: onDeleteWarehouseSuccess
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { rolesReducer } from './RolesRedux';
|
|||||||
import { permissionsReducer } from './PermissionsRedux';
|
import { permissionsReducer } from './PermissionsRedux';
|
||||||
import { WarehouseLocationsReducer } from './WarehouseLocationsRedux';
|
import { WarehouseLocationsReducer } from './WarehouseLocationsRedux';
|
||||||
import { widgetReducer } from './WidgetRedux';
|
import { widgetReducer } from './WidgetRedux';
|
||||||
|
import { labellingReducer } from './LabellingRedux';
|
||||||
import { itemReducer } from './ItemRedux';
|
import { itemReducer } from './ItemRedux';
|
||||||
|
|
||||||
// Combine all reducers.
|
// Combine all reducers.
|
||||||
@@ -21,6 +22,7 @@ const appReducer = combineReducers({
|
|||||||
product: productReducer,
|
product: productReducer,
|
||||||
inventory: inventoryReducer,
|
inventory: inventoryReducer,
|
||||||
widgets: widgetReducer,
|
widgets: widgetReducer,
|
||||||
|
labelling: labellingReducer,
|
||||||
items: itemReducer
|
items: itemReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import NewWarehouseDetails from 'pages/newWarehouseDetails';
|
|||||||
import EditWarehouseDetails from 'pages/editWarehouseDetails';
|
import EditWarehouseDetails from 'pages/editWarehouseDetails';
|
||||||
import LabelingHome from 'pages/labellingHome';
|
import LabelingHome from 'pages/labellingHome';
|
||||||
import SetupInventory from 'pages/setupInventory';
|
import SetupInventory from 'pages/setupInventory';
|
||||||
import CreateUserRole from 'pages/createUserRole';
|
import CreateEditUserRole from 'pages/createEditUserRole';
|
||||||
import CreateEditUser from 'pages/createEditUser';
|
import CreateEditUser from 'pages/createEditUser';
|
||||||
import WidgetLabel from 'pages/widgetLabel';
|
import WidgetLabel from 'pages/widgetLabel';
|
||||||
import ItemListing from 'pages/itemListing';
|
import ItemListing from 'pages/itemListing';
|
||||||
@@ -114,22 +114,21 @@ const protectedRoutes = [
|
|||||||
name: 'Add New Item',
|
name: 'Add New Item',
|
||||||
key: 'add-new-item',
|
key: 'add-new-item',
|
||||||
hide: true,
|
hide: true,
|
||||||
route: '/setup/inventory/new-item/:widgetName/:inventoryId',
|
route: '/setup/inventory/new-item/:inventoryName/:widgetName/:inventoryId',
|
||||||
component: <AddNewItem />
|
component: <AddNewItem />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Update Item',
|
name: 'Update Item',
|
||||||
key: 'udpate-item',
|
key: 'udpate-item',
|
||||||
hide: true,
|
hide: true,
|
||||||
route: '/setup/inventory/browse/:widgetName/:inventoryId/edit/:itemId',
|
route: '/setup/inventory/browse/:inventoryName/:widgetName/:inventoryId/edit/:itemId',
|
||||||
component: <AddNewItem />
|
component: <AddNewItem />
|
||||||
},
|
},
|
||||||
// /setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${payload?.id}
|
|
||||||
{
|
{
|
||||||
name: 'View Items',
|
name: 'View Items',
|
||||||
key: 'view-items',
|
key: 'view-items',
|
||||||
hide: true,
|
hide: true,
|
||||||
route: '/setup/inventory/browse/:widgetName/:inventoryId',
|
route: '/setup/inventory/browse/:inventoryName/:widgetName/:inventoryId',
|
||||||
component: <ItemListing />
|
component: <ItemListing />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -177,21 +176,28 @@ const protectedRoutes = [
|
|||||||
key: 'create-role',
|
key: 'create-role',
|
||||||
route: '/setup/users-access/create-role',
|
route: '/setup/users-access/create-role',
|
||||||
hide: true,
|
hide: true,
|
||||||
component: <CreateUserRole />
|
component: <CreateEditUserRole />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create User',
|
name: 'Create User',
|
||||||
key: 'create-user',
|
key: 'create-user',
|
||||||
route: '/setup/users-access/create-user',
|
route: '/setup/users-access/create-user',
|
||||||
hide: true,
|
hide: true,
|
||||||
component: <CreateEditUser context='new' />
|
component: <CreateEditUser context="new" />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Edot User',
|
name: 'Edit User',
|
||||||
key: 'edit-user',
|
key: 'edit-user',
|
||||||
route: '/setup/users-access/edit-user',
|
route: '/setup/users-access/edit-user',
|
||||||
hide: true,
|
hide: true,
|
||||||
component: <CreateEditUser context='edit' />
|
component: <CreateEditUser context='edit' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Edit Role',
|
||||||
|
key: 'edit-role',
|
||||||
|
route: '/setup/users-access/edit-role',
|
||||||
|
hide: true,
|
||||||
|
component: <CreateEditUserRole context='edit' />
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ export function* onRequestAddInventoryData({ payload }) {
|
|||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
toast('New inventory added');
|
toast.success('New inventory added', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
InventoryActions.addInventorySuccess({
|
InventoryActions.addInventorySuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -72,7 +74,9 @@ export function* onRequestAddInventoryData({ payload }) {
|
|||||||
);
|
);
|
||||||
payload.navigateTo();
|
payload.navigateTo();
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to add inventory');
|
toast.error('Failed to add inventory', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
payload.onFailedAddInventoryData(response.data.error);
|
payload.onFailedAddInventoryData(response.data.error);
|
||||||
yield put(
|
yield put(
|
||||||
InventoryActions.addInventoryFailure({
|
InventoryActions.addInventoryFailure({
|
||||||
@@ -91,16 +95,20 @@ export function* onRequestUpdateInventoryData({ payload }) {
|
|||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
toast('Updated inventory successfully');
|
toast.success('Updated inventory successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
InventoryActions.updateInventorySuccess({
|
InventoryActions.updateInventorySuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
updateInventory: response?.data?.data
|
updateInventory: response?.data?.data
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
payload.navigateTo();
|
// payload.navigateTo();
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to update inventory');
|
toast.error('Failed to update inventory', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
InventoryActions.updateInventoryFailure({
|
InventoryActions.updateInventoryFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -109,9 +117,37 @@ export function* onRequestUpdateInventoryData({ payload }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* onRequestDeleteInventoryData({ payload }) {
|
||||||
|
const response = yield call(ApiServices[payload?.method], AuthorizedAPI, payload?.slug);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
toast.success('Deleted inventory successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
payload.navigateTo();
|
||||||
|
yield put(
|
||||||
|
InventoryActions.deleteInventorySuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
deletedInventoryID: payload?.inventoryId
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
toast.error('Failed to delete inventory', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
yield put(
|
||||||
|
InventoryActions.updateInventoryFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
takeEvery(InventoryTypes.GET_INVENTORY_ACTION, onRequestGetInventoryData),
|
takeEvery(InventoryTypes.GET_INVENTORY_ACTION, onRequestGetInventoryData),
|
||||||
takeEvery(InventoryTypes.ADD_INVENTORY_ACTION, onRequestAddInventoryData),
|
takeEvery(InventoryTypes.ADD_INVENTORY_ACTION, onRequestAddInventoryData),
|
||||||
|
takeEvery(InventoryTypes.DELETE_INVENTORY_ACTION, onRequestDeleteInventoryData),
|
||||||
takeEvery(InventoryTypes.UPDATE_INVENTORY_ACTION, onRequestUpdateInventoryData),
|
takeEvery(InventoryTypes.UPDATE_INVENTORY_ACTION, onRequestUpdateInventoryData),
|
||||||
takeEvery(InventoryTypes.GET_INVENTORY_TYPES_ACTION, onRequestGetInventoryTypesData)
|
takeEvery(InventoryTypes.GET_INVENTORY_TYPES_ACTION, onRequestGetInventoryTypesData)
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ export function* onRequestOneItem({ payload }) {
|
|||||||
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${payload?.itemId}`
|
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${payload?.itemId}`
|
||||||
// );
|
// );
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to get item details');
|
toast.error('Failed to get item details', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
ItemActions.itemFailure({
|
ItemActions.itemFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -100,7 +102,9 @@ export function* onAddRequestItem({ payload }) {
|
|||||||
createFormData(payload?.data)
|
createFormData(payload?.data)
|
||||||
);
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
toast(`Added item: ${payload.data.commonName}`);
|
toast.success(`Added item: ${payload.data.commonName}`, {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
// payload.navigateTo(
|
// payload.navigateTo(
|
||||||
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${response?.data?.data?._id}`
|
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${response?.data?.data?._id}`
|
||||||
// );
|
// );
|
||||||
@@ -112,7 +116,9 @@ export function* onAddRequestItem({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to add item');
|
toast.error('Failed to add item', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
ItemActions.itemFailure({
|
ItemActions.itemFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -130,7 +136,9 @@ export function* onEditRequestItem({ payload }) {
|
|||||||
createFormData(payload?.data)
|
createFormData(payload?.data)
|
||||||
);
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
toast(`Successfully edited item: ${payload.data.commonName}`);
|
toast.success(`Successfully edited item: ${payload.data.commonName}`, {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
payload.navigateTo('/setup/inventory');
|
payload.navigateTo('/setup/inventory');
|
||||||
yield put(
|
yield put(
|
||||||
ItemActions.addItemSuccess({
|
ItemActions.addItemSuccess({
|
||||||
@@ -139,7 +147,39 @@ export function* onEditRequestItem({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to edit item');
|
toast.error('Failed to edit item', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
yield put(
|
||||||
|
ItemActions.itemFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* onDeleteRequestItem({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug + payload?.itemId
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
toast.success('Successfully deleted item', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
payload.refreshDispatch();
|
||||||
|
yield put(
|
||||||
|
ItemActions.deleteItemSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
item: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
toast.error('Failed to delete item', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
ItemActions.itemFailure({
|
ItemActions.itemFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -153,5 +193,6 @@ export default [
|
|||||||
takeEvery(ItemTypes.ITEM_REQUEST, onRequestItem),
|
takeEvery(ItemTypes.ITEM_REQUEST, onRequestItem),
|
||||||
takeEvery(ItemTypes.ONE_ITEM_REQUEST, onRequestOneItem),
|
takeEvery(ItemTypes.ONE_ITEM_REQUEST, onRequestOneItem),
|
||||||
takeEvery(ItemTypes.ADD_ITEM_REQUEST, onAddRequestItem),
|
takeEvery(ItemTypes.ADD_ITEM_REQUEST, onAddRequestItem),
|
||||||
takeEvery(ItemTypes.EDIT_ITEM_REQUEST, onEditRequestItem)
|
takeEvery(ItemTypes.EDIT_ITEM_REQUEST, onEditRequestItem),
|
||||||
|
takeEvery(ItemTypes.DELETE_ITEM_REQUEST, onDeleteRequestItem)
|
||||||
];
|
];
|
||||||
|
|||||||
31
src/sagas/Labelling.js
Normal file
31
src/sagas/Labelling.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { AuthorizedAPI } from 'config';
|
||||||
|
import { call, put, takeEvery } from 'redux-saga/effects';
|
||||||
|
import LabellingActions from 'redux/LabellingRedux';
|
||||||
|
import { LabellingTypes } from 'redux/LabellingRedux';
|
||||||
|
import ApiServices from 'services/API/ApiServices';
|
||||||
|
|
||||||
|
export function* onRequestGetLabelData({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
LabellingActions.getLabelSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
getLabelDetail: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload.onFailedGetLabelData(response.data.error);
|
||||||
|
yield put(
|
||||||
|
LabellingActions.getLabelFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default [takeEvery(LabellingTypes.GET_LABEL_ACTION, onRequestGetLabelData)];
|
||||||
@@ -28,4 +28,32 @@ export function* onRequestAddProductData({ payload }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default [takeLatest(ProductTypes.ADD_PRODUCT_ACTION, onRequestAddProductData)];
|
|
||||||
|
export function* onRequestGetProductById({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
ProductActions.getProductByIdSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
getProductByIdDetail: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload.onFailedGetProductById(response.data.error);
|
||||||
|
yield put(
|
||||||
|
ProductActions.getProductByIdFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default [
|
||||||
|
takeLatest(ProductTypes.ADD_PRODUCT_ACTION, onRequestAddProductData),
|
||||||
|
takeLatest(ProductTypes.GET_PRODUCT_BY_ID_ACTION, onRequestGetProductById)
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AuthorizedAPI } from 'config';
|
import { AuthorizedAPI } from 'config';
|
||||||
import { takeLatest, call, put } from 'redux-saga/effects';
|
import { takeLatest, call, put } from 'redux-saga/effects';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
import RolesActions, { RolesTypes } from '../redux/RolesRedux';
|
import RolesActions, { RolesTypes } from '../redux/RolesRedux';
|
||||||
import ApiServices from 'services/API/ApiServices';
|
import ApiServices from 'services/API/ApiServices';
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ export function* onRequestRolesData({ payload }) {
|
|||||||
payload?.slug,
|
payload?.slug,
|
||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
|
payload?.callback && payload?.callback();
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
yield put(
|
yield put(
|
||||||
RolesActions.getRolesSuccess({
|
RolesActions.getRolesSuccess({
|
||||||
@@ -18,6 +20,7 @@ export function* onRequestRolesData({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
toast('Failed to fetch roles');
|
||||||
payload.onFailedRolesData(response.data.error);
|
payload.onFailedRolesData(response.data.error);
|
||||||
yield put(
|
yield put(
|
||||||
RolesActions.getRolesFailure({
|
RolesActions.getRolesFailure({
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export function* onRequestUsersData({ payload }) {
|
|||||||
payload?.slug,
|
payload?.slug,
|
||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
|
payload?.callback && payload?.callback();
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
yield put(
|
yield put(
|
||||||
UsersActions.getUsersSuccess({
|
UsersActions.getUsersSuccess({
|
||||||
@@ -19,6 +20,7 @@ export function* onRequestUsersData({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
toast('Failed to fetch user list');
|
||||||
payload.onFailedUsersData(response.data.error);
|
payload.onFailedUsersData(response.data.error);
|
||||||
yield put(
|
yield put(
|
||||||
UsersActions.getUsersFailure({
|
UsersActions.getUsersFailure({
|
||||||
@@ -34,8 +36,13 @@ export function* onCreateUserData({ payload }) {
|
|||||||
ApiServices[payload?.method],
|
ApiServices[payload?.method],
|
||||||
AuthorizedAPI,
|
AuthorizedAPI,
|
||||||
payload?.slug,
|
payload?.slug,
|
||||||
payload?.data
|
payload?.data,
|
||||||
|
{
|
||||||
|
processData: false,
|
||||||
|
contentType: false
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
payload?.callback && payload?.callback(false);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
const data = response.data?.data;
|
const data = response.data?.data;
|
||||||
const msg = payload.toastMessage.replace('__placeholder__', data && data.fullName ? '"' + data.fullName + '" ' : '');
|
const msg = payload.toastMessage.replace('__placeholder__', data && data.fullName ? '"' + data.fullName + '" ' : '');
|
||||||
@@ -48,8 +55,9 @@ export function* onCreateUserData({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
toast('Something went wrong!');
|
const error = response?.originalError?.response?.data?.error;
|
||||||
payload.onValidationFailed(response.data?.error);
|
toast(error && error.indexOf('E11000') > -1 ? 'Email already exists!' : 'Something went wrong!');
|
||||||
|
payload.onValidationFailed();
|
||||||
yield put(
|
yield put(
|
||||||
UsersActions.createUserFailure({
|
UsersActions.createUserFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const makeFormData = (data) => {
|
|||||||
data.preferredInventories.forEach((prefInv, idx) => {
|
data.preferredInventories.forEach((prefInv, idx) => {
|
||||||
formData.append(`preferredInventories[${idx}]`, prefInv);
|
formData.append(`preferredInventories[${idx}]`, prefInv);
|
||||||
});
|
});
|
||||||
if (data.image[0].file) formData.append('image', data.image[0].file);
|
if (data.image[0]?.file) formData.append('image', data.image[0].file);
|
||||||
return formData;
|
return formData;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,7 +52,9 @@ export function* onRequestCreateWarehouse({ payload }) {
|
|||||||
);
|
);
|
||||||
if (response?.status === 200 && response?.data?.message) {
|
if (response?.status === 200 && response?.data?.message) {
|
||||||
const warehouse = response?.data?.message;
|
const warehouse = response?.data?.message;
|
||||||
toast('Warehouse created successfully');
|
toast.success('Warehouse created successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseActions.createWarehouseSuccess({
|
WarehouseActions.createWarehouseSuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -64,7 +66,9 @@ export function* onRequestCreateWarehouse({ payload }) {
|
|||||||
);
|
);
|
||||||
payload.navigateTo(response?.data?.message?._id);
|
payload.navigateTo(response?.data?.message?._id);
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to create warehouse');
|
toast.error('Failed to create warehouse', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseActions.createWarehouseFailure({
|
WarehouseActions.createWarehouseFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -82,7 +86,9 @@ export function* onRequestEditWarehouse({ payload }) {
|
|||||||
makeFormData(payload?.data)
|
makeFormData(payload?.data)
|
||||||
);
|
);
|
||||||
if (response?.status === 200 && response?.data?.data) {
|
if (response?.status === 200 && response?.data?.data) {
|
||||||
toast('Warehouse edited successfully');
|
toast.success('Warehouse edited successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
const warehouse = response?.data?.data;
|
const warehouse = response?.data?.data;
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseActions.editWarehouseSuccess({
|
WarehouseActions.editWarehouseSuccess({
|
||||||
@@ -94,7 +100,39 @@ export function* onRequestEditWarehouse({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
toast('Failed to edit warehouse');
|
toast.error('Failed to edit warehouse', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
yield put(
|
||||||
|
WarehouseActions.editWarehouseFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* onRequestDeleteWarehouse({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug + payload?.warehouseId
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
toast.success('Warehouse deleted successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
|
payload.navigateTo('/setup/warehouse');
|
||||||
|
yield put(
|
||||||
|
WarehouseActions.deleteWarehouseSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
deletedWarehouseID: payload?.warehouseId
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
toast.error('Failed to delete warehouse', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseActions.editWarehouseFailure({
|
WarehouseActions.editWarehouseFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -107,5 +145,6 @@ export function* onRequestEditWarehouse({ payload }) {
|
|||||||
export default [
|
export default [
|
||||||
takeLatest(WarehouseTypes.WAREHOUSE_DATA_ACTION, onRequestWarehouseData),
|
takeLatest(WarehouseTypes.WAREHOUSE_DATA_ACTION, onRequestWarehouseData),
|
||||||
takeLatest(WarehouseTypes.CREATE_WAREHOUSE_ACTION, onRequestCreateWarehouse),
|
takeLatest(WarehouseTypes.CREATE_WAREHOUSE_ACTION, onRequestCreateWarehouse),
|
||||||
takeLatest(WarehouseTypes.EDIT_WAREHOUSE_ACTION, onRequestEditWarehouse)
|
takeLatest(WarehouseTypes.EDIT_WAREHOUSE_ACTION, onRequestEditWarehouse),
|
||||||
|
takeLatest(WarehouseTypes.DELETE_WAREHOUSE_ACTION, onRequestDeleteWarehouse)
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AuthorizedAPI } from 'config';
|
import { AuthorizedAPI } from 'config';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
import { call, put, takeEvery } from 'redux-saga/effects';
|
import { call, put, takeEvery } from 'redux-saga/effects';
|
||||||
import WarehouseLocationsActions from 'redux/WarehouseLocationsRedux';
|
import WarehouseLocationsActions from 'redux/WarehouseLocationsRedux';
|
||||||
import { WarehouseLocationsTypes } from 'redux/WarehouseLocationsRedux';
|
import { WarehouseLocationsTypes } from 'redux/WarehouseLocationsRedux';
|
||||||
@@ -42,6 +43,9 @@ export function* onAddRequestLocation({ payload }) {
|
|||||||
);
|
);
|
||||||
LOGGER.log('add response', response.data);
|
LOGGER.log('add response', response.data);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
|
toast.success('Location created successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationSuccess({
|
WarehouseLocationsActions.locationSuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -52,7 +56,9 @@ export function* onAddRequestLocation({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
payload.onFailedLocation(response.data.error);
|
toast.error('Failed to create warehouse location', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationFailure({
|
WarehouseLocationsActions.locationFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -71,6 +77,9 @@ export function* onDeleteRequestLocation({ payload }) {
|
|||||||
);
|
);
|
||||||
LOGGER.log('delete response', response.data);
|
LOGGER.log('delete response', response.data);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
|
toast.success('Location deleted successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationSuccess({
|
WarehouseLocationsActions.locationSuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -78,7 +87,9 @@ export function* onDeleteRequestLocation({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
payload.onFailedLocation(response.data.error);
|
toast.error('Failed to delete warehouse location', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationFailure({
|
WarehouseLocationsActions.locationFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -97,6 +108,9 @@ export function* onEditRequestLocation({ payload }) {
|
|||||||
);
|
);
|
||||||
LOGGER.log('edit response', response.data);
|
LOGGER.log('edit response', response.data);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
|
toast.success('Location edited successfully', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationSuccess({
|
WarehouseLocationsActions.locationSuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -108,7 +122,9 @@ export function* onEditRequestLocation({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
payload.onFailedLocation(response.data.error);
|
toast.error('Failed to edit warehouse location', {
|
||||||
|
theme: 'colored'
|
||||||
|
});
|
||||||
yield put(
|
yield put(
|
||||||
WarehouseLocationsActions.locationFailure({
|
WarehouseLocationsActions.locationFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AuthorizedAPI } from 'config';
|
import { AuthorizedAPI } from 'config';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
import { call, put, takeEvery } from 'redux-saga/effects';
|
import { call, put, takeEvery } from 'redux-saga/effects';
|
||||||
import ApiServices from 'services/API/ApiServices';
|
import ApiServices from 'services/API/ApiServices';
|
||||||
import WidgetActions, { WidgetTypes } from '../redux/WidgetRedux';
|
import WidgetActions, { WidgetTypes } from '../redux/WidgetRedux';
|
||||||
@@ -35,6 +36,12 @@ export function* onEditRequestWidget({ payload }) {
|
|||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
|
toast.success(
|
||||||
|
`Successfully ${payload?.type !== 'delete' ? payload?.type : 'delet'}ed widget family`,
|
||||||
|
{
|
||||||
|
theme: 'colored'
|
||||||
|
}
|
||||||
|
);
|
||||||
yield put(
|
yield put(
|
||||||
WidgetActions.editWidgetSuccess({
|
WidgetActions.editWidgetSuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
@@ -44,6 +51,12 @@ export function* onEditRequestWidget({ payload }) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
toast.error(
|
||||||
|
payload?.type ? `Failed to ${payload?.type} widget family` : 'Failed to fulfill request',
|
||||||
|
{
|
||||||
|
theme: 'colored'
|
||||||
|
}
|
||||||
|
);
|
||||||
yield put(
|
yield put(
|
||||||
WidgetActions.widgetFailure({
|
WidgetActions.widgetFailure({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import RolesSaga from './Roles';
|
|||||||
import PermissionsSaga from './Permissions';
|
import PermissionsSaga from './Permissions';
|
||||||
import WarehouseLocationsSaga from './WarehouseLocations';
|
import WarehouseLocationsSaga from './WarehouseLocations';
|
||||||
import WidgetSaga from './Widget';
|
import WidgetSaga from './Widget';
|
||||||
|
import LabellingSaga from './Labelling';
|
||||||
import ItemSaga from './Item';
|
import ItemSaga from './Item';
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
@@ -20,5 +21,6 @@ export default function* rootSaga() {
|
|||||||
yield all([...PermissionsSaga]);
|
yield all([...PermissionsSaga]);
|
||||||
yield all([...WarehouseLocationsSaga]);
|
yield all([...WarehouseLocationsSaga]);
|
||||||
yield all([...WidgetSaga]);
|
yield all([...WidgetSaga]);
|
||||||
|
yield all([...LabellingSaga]);
|
||||||
yield all([...ItemSaga]);
|
yield all([...ItemSaga]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// REST API SERVICES
|
// REST API SERVICES
|
||||||
export default {
|
export default {
|
||||||
post: (API, slug, payload) => API.post(slug, payload),
|
post: (API, slug, payload, headers) => headers ? API.post(slug, payload, {headers}) : API.post(slug, payload),
|
||||||
get: (API, slug) => API.get(slug),
|
get: (API, slug) => API.get(slug),
|
||||||
delete: (API, slug) => {
|
delete: (API, slug) => {
|
||||||
return API.delete(slug);
|
return API.delete(slug);
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ const schema = {
|
|||||||
addNewItem: Yup.object({
|
addNewItem: Yup.object({
|
||||||
commonName: Yup.string('Enter details').required(),
|
commonName: Yup.string('Enter details').required(),
|
||||||
formalName: Yup.string('Enter details').required(),
|
formalName: Yup.string('Enter details').required(),
|
||||||
description: Yup.string('Enter details').required(),
|
description: Yup.string('Enter details'),
|
||||||
manufacturer: Yup.string('Enter details').required(),
|
manufacturer: Yup.string('Enter details'),
|
||||||
size: Yup.string('Enter details').required(),
|
size: Yup.string('Enter details'),
|
||||||
color: Yup.string('Enter details').required(),
|
color: Yup.string('Enter details'),
|
||||||
type: Yup.string('Enter details').required(),
|
type: Yup.string('Enter details'),
|
||||||
unitOfMaterial: Yup.string('Enter details').required(),
|
unitOfMaterial: Yup.string('Enter details'),
|
||||||
unitCost: Yup.number().test((val) => val >= 0),
|
unitCost: Yup.number().test((val) => val >= 0),
|
||||||
packageCount: Yup.number().test((val) => val >= 0),
|
packageCount: Yup.number().test((val) => val >= 0),
|
||||||
countPerPallet: Yup.number().test((val) => val >= 0),
|
countPerPallet: Yup.number().test((val) => val >= 0),
|
||||||
countPerPalletPackage: Yup.number().test((val) => val >= 0),
|
countPerPalletPackage: Yup.number().test((val) => val >= 0),
|
||||||
primaryWidgetFamilyId: Yup.string('Enter details').required(),
|
primaryWidgetFamilyId: Yup.string('Enter details'),
|
||||||
secondaryWidgetFamilyId: Yup.string('Enter details'),
|
secondaryWidgetFamilyId: Yup.string('Enter details'),
|
||||||
policiesMetadata: Yup.object({
|
policiesMetadata: Yup.object({
|
||||||
underStockLevelCount: Yup.number().test((val) => val >= 0),
|
underStockLevelCount: Yup.number().test((val) => val >= 0),
|
||||||
@@ -54,8 +54,8 @@ const schema = {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
addInventory: Yup.object({
|
addInventory: Yup.object({
|
||||||
name: Yup.string('Enter Widget Name').required('Widget Name is required'),
|
name: Yup.string('Enter Inventory Name').required('Inventory Name is required'),
|
||||||
widgetName: Yup.string('Enter Inventory name').required('Inventory name is required'),
|
widgetName: Yup.string('Enter Widget name').required('Widget Name is required'),
|
||||||
policies: Yup.object({
|
policies: Yup.object({
|
||||||
orderTracking: Yup.boolean(),
|
orderTracking: Yup.boolean(),
|
||||||
alerting: Yup.boolean(),
|
alerting: Yup.boolean(),
|
||||||
@@ -63,11 +63,13 @@ const schema = {
|
|||||||
preferredLocations: Yup.boolean(),
|
preferredLocations: Yup.boolean(),
|
||||||
inventory_process: Yup.string()
|
inventory_process: Yup.string()
|
||||||
}),
|
}),
|
||||||
image: Yup.array()
|
icons: Yup.string()
|
||||||
}),
|
}),
|
||||||
|
|
||||||
createUser: Yup.object({
|
createUser: Yup.object({
|
||||||
fullName: Yup.string('Enter Full Name').required('User Name is required'),
|
fullName: Yup.string('Enter Full Name').required('User Name is required'),
|
||||||
|
email: Yup.string('Enter Email').required('Email is required'),
|
||||||
|
password: Yup.string('Enter Password').required('Password is required'),
|
||||||
phoneNumber: Yup.string('Enter Phone Numbe').required('Phone Number is required'),
|
phoneNumber: Yup.string('Enter Phone Numbe').required('Phone Number is required'),
|
||||||
roles: Yup.string('Please select at least one role').required('At least one role is required')
|
roles: Yup.string('Please select at least one role').required('At least one role is required')
|
||||||
})
|
})
|
||||||
|
|||||||
18
src/utils/inventorySlugTools.js
Normal file
18
src/utils/inventorySlugTools.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import EquipmentIcon from 'assets/images/EquimpmentIcon';
|
||||||
|
import FleetIcon from 'assets/images/FleetIcon';
|
||||||
|
import RawMaterialIcon from 'assets/images/RawMaterialIcon';
|
||||||
|
|
||||||
|
export const GetIconFromSlug = (slug) => {
|
||||||
|
switch (slug) {
|
||||||
|
case 'equipment':
|
||||||
|
return <EquipmentIcon />;
|
||||||
|
case 'fleet':
|
||||||
|
return <FleetIcon />;
|
||||||
|
case 'rawmaterial':
|
||||||
|
return <RawMaterialIcon />;
|
||||||
|
default:
|
||||||
|
return <RawMaterialIcon />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const iconSlugs = ['equipment', 'fleet', 'rawmaterial'];
|
||||||
Reference in New Issue
Block a user