Fixes/ll inventory (#69)
* inventory data changes * update Inventory changes * Fixed: removed unnecessary imports * Disabled: cycle count * Added: Inventory types sagas * Fix: null check * Updated: policies * Fixed: formik values * update: allow single image * Update: Policies control * Updated: new inventory add form * Update: new inventory conditional render * Update: populate formik fields * Added: Validation * Added: edit functionality, disabled fields * Update: housekeeping * Fix: iconslug and key * Update: route handling * Added: endpoints * Added: widget nested page * Added: sagas * Added: redux handling * Update: new product page functionality * Added: inventory page functionality * Fixed: form validation * Fix: route handling Co-authored-by: evdigitech <evdigitech@gmail.com> Co-authored-by: Llewellyn Dsouza <lledsouza2209@gmail.com>
This commit is contained in:
@@ -34,24 +34,24 @@ export default function Tile({ data, children }) {
|
|||||||
</Box>
|
</Box>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
<AccordionDetails className={`${classes.row2} ${expand ? null : classes.remove}`}>
|
<AccordionDetails className={`${classes.row2} ${expand ? null : classes.remove}`}>
|
||||||
<Link to={data.path.update}>
|
<Link to={`/setup/inventory/update/${data.id}`}>
|
||||||
<Box className={classes.box}>
|
<Box className={classes.box}>
|
||||||
Update {data.name} <ArrowRightIcon />
|
Update {data.name} <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={data.path.addNew}>
|
<Link to={`/setup/inventory/new-item/${data.widgetname}/${data.id}`}>
|
||||||
<Box className={`${classes.box} ${classes.boxEven}`}>
|
<Box className={`${classes.box} ${classes.boxEven}`}>
|
||||||
Add New {data.name} <ArrowRightIcon />
|
Add New {data.widgetname} <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={data.path.cycleCount}>
|
<Link to="#">
|
||||||
<Box className={classes.box}>
|
<Box className={classes.boxDisabled}>
|
||||||
Cycle Count <ArrowRightIcon />
|
Cycle Count <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={data.path.list}>
|
<Link to="/">
|
||||||
<Box className={`${classes.box} ${classes.boxEven}`}>
|
<Box className={`${classes.box} ${classes.boxEven}`}>
|
||||||
{data.name} List <ArrowRightIcon />
|
{data.widgetname} List <ArrowRightIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Link>
|
</Link>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
|
|||||||
@@ -83,6 +83,23 @@ const useStyles = makeStyles({
|
|||||||
},
|
},
|
||||||
remove: {
|
remove: {
|
||||||
display: 'none'
|
display: 'none'
|
||||||
|
},
|
||||||
|
boxDisabled: {
|
||||||
|
display: 'flex',
|
||||||
|
color: '#cccccc',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
padding: '13px 0 13px 10px',
|
||||||
|
borderTop: '1px solid lightgray',
|
||||||
|
'& svg': {
|
||||||
|
opacity: '0'
|
||||||
|
},
|
||||||
|
'&:hover': {
|
||||||
|
cursor: 'auto',
|
||||||
|
'& svg': {
|
||||||
|
opacity: '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
329
src/components/WidgetNestedDataTable/index.js
Normal file
329
src/components/WidgetNestedDataTable/index.js
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
/* eslint-disable indent */
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
|
TextField
|
||||||
|
} from '@mui/material';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
|
||||||
|
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||||
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
import MDButton from 'components/Button';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||||
|
import WidgetActions from 'redux/WidgetRedux';
|
||||||
|
import { API } from 'constant';
|
||||||
|
import { useFormik } from 'formik';
|
||||||
|
import LOGGER from 'services/Logger';
|
||||||
|
|
||||||
|
function MaterialForm({ formType, setFormOpen, selected, inventoryId }) {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const formik = useFormik({
|
||||||
|
initialValues:
|
||||||
|
formType === 'family'
|
||||||
|
? { name: '', inventoryId }
|
||||||
|
: formType === 'subfamily'
|
||||||
|
? { name: '', inventoryId, parentId: selected._id || '' }
|
||||||
|
: { name: formType.name, inventoryId, parentId: formType.parent?._id || undefined },
|
||||||
|
onSubmit: (values) => {
|
||||||
|
LOGGER.log('Form values and field info', values);
|
||||||
|
['family', 'subfamily'].includes(formType)
|
||||||
|
? dispatch(
|
||||||
|
WidgetActions.editWidgetRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: API.ADD_WIDGET_FAMILY,
|
||||||
|
method: 'post',
|
||||||
|
data: values,
|
||||||
|
type: 'add'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
: dispatch(
|
||||||
|
WidgetActions.editWidgetRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: `${API.EDIT_WIDGET_FAMILY}${inventoryId}`,
|
||||||
|
method: 'patch',
|
||||||
|
data: values,
|
||||||
|
type: 'edit'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
setFormOpen(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open
|
||||||
|
onClose={() => {
|
||||||
|
setFormOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
{['family', 'subfamily'].includes(formType) ? 'Create' : 'Edit'} material{' '}
|
||||||
|
{['family', 'subfamily'].includes(formType) ? formType : null}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
{/* <DialogContentText>Some more text if needed</DialogContentText> */}
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
fullWidth
|
||||||
|
margin="dense"
|
||||||
|
label="Name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
variant="standard"
|
||||||
|
value={formik.values.name}
|
||||||
|
error={formik.touched.name && Boolean(formik.errors.name)}
|
||||||
|
helperText={formik.touched.name && formik.errors.name}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MDButton
|
||||||
|
onClick={() => {
|
||||||
|
setFormOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</MDButton>
|
||||||
|
<MDButton onClick={formik.handleSubmit}>Save</MDButton>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialForm.propTypes = {
|
||||||
|
formType: PropTypes.any,
|
||||||
|
setFormOpen: PropTypes.any,
|
||||||
|
selected: PropTypes.any,
|
||||||
|
inventoryId: PropTypes.any
|
||||||
|
};
|
||||||
|
|
||||||
|
function WidgetNestedDataTable({
|
||||||
|
data,
|
||||||
|
selected,
|
||||||
|
setSelected,
|
||||||
|
setFormOpen,
|
||||||
|
setFormType,
|
||||||
|
inventoryId
|
||||||
|
}) {
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const widgetChildren = useSelector(WidgetSelectors.getWidgetsByParentId(data._id));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
borderLeftWidth: '2px',
|
||||||
|
borderLeftStyle: 'solid',
|
||||||
|
borderLeftColor: '#aedaed',
|
||||||
|
|
||||||
|
borderTopWidth: '1px',
|
||||||
|
borderTopStyle: 'solid',
|
||||||
|
borderTopColor: '#BDD0DB',
|
||||||
|
|
||||||
|
background:
|
||||||
|
selected?._id === data._id
|
||||||
|
? 'linear-gradient(135deg, ' + '#aedaed' + ' 0%, #f9f9f9 20%)'
|
||||||
|
: '#f9f9f9'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid container key={data._id}>
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<IconButton
|
||||||
|
disabled={!widgetChildren?.length}
|
||||||
|
aria-label="expand row"
|
||||||
|
size="small"
|
||||||
|
sx={{ marginLeft: '12px' }}
|
||||||
|
onClick={() => setOpen(!open)}
|
||||||
|
>
|
||||||
|
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowRightIcon />}
|
||||||
|
</IconButton>
|
||||||
|
<MDButton
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
sx={{
|
||||||
|
textTransform: 'capitalize',
|
||||||
|
minWidth: '45px',
|
||||||
|
minHeight: '28px',
|
||||||
|
marginLeft: '5px',
|
||||||
|
marginRight: '20px',
|
||||||
|
boxShadow: 'none',
|
||||||
|
fontWeight: '500',
|
||||||
|
padding: '0'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setFormType(data);
|
||||||
|
setFormOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
EDIT
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
item
|
||||||
|
xs={10}
|
||||||
|
onClick={() => {
|
||||||
|
setSelected(data);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid item xs={9}>
|
||||||
|
{data.name}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={1}>
|
||||||
|
<MDButton
|
||||||
|
disabled
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
sx={{
|
||||||
|
textTransform: 'capitalize',
|
||||||
|
minWidth: '45px',
|
||||||
|
minHeight: '28px',
|
||||||
|
marginLeft: '5px',
|
||||||
|
marginRight: '20px',
|
||||||
|
boxShadow: 'none',
|
||||||
|
fontWeight: '500',
|
||||||
|
padding: '0 6'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
// dispatch(
|
||||||
|
// WarehouseLocationsActions.deleteLocationRequest({
|
||||||
|
// loader: 'location-request',
|
||||||
|
// slug: API.LOCATION_DELETE,
|
||||||
|
// method: 'post',
|
||||||
|
// data: { type: data.location, id: data.id }
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
DELETE
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{open && widgetChildren ? (
|
||||||
|
<Box Box sx={{ marginLeft: '25px', marginBottom: '15px' }}>
|
||||||
|
{/* Add headers here */}
|
||||||
|
{widgetChildren.map((data) => (
|
||||||
|
<WidgetNestedDataTable
|
||||||
|
key={data._id}
|
||||||
|
data={data}
|
||||||
|
selected={selected}
|
||||||
|
setSelected={setSelected}
|
||||||
|
setFormOpen={setFormOpen}
|
||||||
|
setFormType={setFormType}
|
||||||
|
inventoryId={inventoryId}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetNestedDataTable.propTypes = {
|
||||||
|
data: PropTypes.any,
|
||||||
|
selected: PropTypes.any,
|
||||||
|
setSelected: PropTypes.any,
|
||||||
|
setFormOpen: PropTypes.any,
|
||||||
|
setFormType: PropTypes.any,
|
||||||
|
inventoryId: PropTypes.any
|
||||||
|
};
|
||||||
|
|
||||||
|
const bottomButtonStyling = {
|
||||||
|
width: '200px',
|
||||||
|
marginTop: '25px',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
borderRadius: '100px',
|
||||||
|
padding: '13px 30px'
|
||||||
|
};
|
||||||
|
|
||||||
|
function WidgetNestedDataTableContainer({ inventoryId }) {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [selected, setSelected] = React.useState(null);
|
||||||
|
const [formType, setFormType] = React.useState('family');
|
||||||
|
const [formOpen, setFormOpen] = React.useState(false);
|
||||||
|
const widgetFamilyData = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(
|
||||||
|
WidgetActions.widgetRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${inventoryId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{widgetFamilyData &&
|
||||||
|
widgetFamilyData.map((p) => (
|
||||||
|
<WidgetNestedDataTable
|
||||||
|
key={p._id}
|
||||||
|
data={p}
|
||||||
|
selected={selected}
|
||||||
|
setSelected={setSelected}
|
||||||
|
setFormOpen={setFormOpen}
|
||||||
|
setFormType={setFormType}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<Grid container spacing={5} justifyContent="center">
|
||||||
|
<Grid item>
|
||||||
|
<MDButton
|
||||||
|
size="medium"
|
||||||
|
sx={bottomButtonStyling}
|
||||||
|
color="primary"
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => {
|
||||||
|
setFormType('family');
|
||||||
|
setFormOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Family
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<MDButton
|
||||||
|
size="medium"
|
||||||
|
sx={bottomButtonStyling}
|
||||||
|
disabled={selected?.parent}
|
||||||
|
color={selected && !selected?.parent ? 'primary' : 'secondary'}
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => {
|
||||||
|
setFormType('subfamily');
|
||||||
|
setFormOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add SubFamily
|
||||||
|
</MDButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{/* <pre>{JSON.stringify(selected, null, 4)}</pre> */}
|
||||||
|
|
||||||
|
{formOpen && (
|
||||||
|
<MaterialForm
|
||||||
|
formType={formType}
|
||||||
|
setFormOpen={setFormOpen}
|
||||||
|
selected={selected}
|
||||||
|
inventoryId={inventoryId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetNestedDataTableContainer.propTypes = {
|
||||||
|
inventoryId: PropTypes.any
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WidgetNestedDataTableContainer;
|
||||||
@@ -13,5 +13,10 @@ export default {
|
|||||||
ADD_NEW_SUBLEVEL: '/sublevel',
|
ADD_NEW_SUBLEVEL: '/sublevel',
|
||||||
ADD_PRODUCT: '/item/',
|
ADD_PRODUCT: '/item/',
|
||||||
ADD_INVENTORY: '/inventory',
|
ADD_INVENTORY: '/inventory',
|
||||||
LOCATION_DELETE: '/dashboard/delete-location'
|
GET_INVENTORY: '/inventory/all?page=0&perPage=50',
|
||||||
|
GET_INVENTORY_TYPES: '/inventory/types',
|
||||||
|
LOCATION_DELETE: '/dashboard/delete-location',
|
||||||
|
GET_WIDGET_FAMILY_BY_INVENTORY: '/widget-family/search-by-inventory?inventory=',
|
||||||
|
ADD_WIDGET_FAMILY: '/widget-family',
|
||||||
|
EDIT_WIDGET_FAMILY: '/widget-family/'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,11 +15,14 @@ import CrossIcon from 'assets/images/CrossIcon';
|
|||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import schema from 'services/ValidationServices';
|
import schema from 'services/ValidationServices';
|
||||||
import MDInput from 'components/MDInput';
|
import MDInput from 'components/MDInput';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import ProductActions from 'redux/ProductsRedux';
|
import ProductActions from 'redux/ProductsRedux';
|
||||||
import { API } from 'constant';
|
import { API } from 'constant';
|
||||||
import LOGGER from 'services/Logger';
|
import LOGGER from 'services/Logger';
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||||
|
import WidgetActions from 'redux/WidgetRedux';
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
labelSize: {
|
labelSize: {
|
||||||
@@ -43,47 +46,53 @@ const useStyles = makeStyles({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const inventoryTypes = ['Perishable', 'Material', 'Product', 'Inventory', 'Fleet'];
|
function AddNewItem() {
|
||||||
|
|
||||||
function AddNewProduct() {
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const { widgetName, inventoryId } = useParams();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [Manufacturer, setManufacturer] = React.useState('');
|
const [Manufacturer, setManufacturer] = React.useState('');
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
|
||||||
const handleClickOpen = () => {
|
React.useEffect(() => {
|
||||||
setOpen(true);
|
dispatch(
|
||||||
};
|
WidgetActions.widgetRequest({
|
||||||
|
loader: 'location-request',
|
||||||
|
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${inventoryId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleClose = () => {
|
const [pFam, setPFam] = React.useState(null);
|
||||||
setOpen(false);
|
const primaryFamily = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||||
};
|
const secondaryFamily = useSelector(WidgetSelectors.getWidgetsByParentId(pFam));
|
||||||
|
LOGGER.log({ primaryFamily, secondaryFamily });
|
||||||
const handleChange = (event) => {
|
|
||||||
setManufacturer(event.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
warehousename: '',
|
commonName: '',
|
||||||
|
formalName: '',
|
||||||
description: '',
|
description: '',
|
||||||
manufacturer: '',
|
manufacturer: '',
|
||||||
type: '',
|
|
||||||
unitofmaterial: '',
|
|
||||||
packagecount: '',
|
|
||||||
formalname: '',
|
|
||||||
size: '',
|
size: '',
|
||||||
color: '',
|
color: '',
|
||||||
unitcost: '',
|
type: '',
|
||||||
countperpallet: '',
|
unitOfMaterial: '',
|
||||||
countperpalletpackage: '',
|
unitCost: 0,
|
||||||
productfamilyassociation: '',
|
packageCount: 0,
|
||||||
under: '',
|
countPerPallet: 0,
|
||||||
over: '',
|
countPerPalletPackage: 0,
|
||||||
alert: '',
|
primaryWidgetFamilyId: '',
|
||||||
|
secondaryWidgetFamilyId: '',
|
||||||
|
policiesMetadata: {
|
||||||
|
underStockLevelCount: 0,
|
||||||
|
overStockLevelCount: 0,
|
||||||
|
alertStockLevelCount: 0,
|
||||||
|
reorderStockLevelCount: 0
|
||||||
|
},
|
||||||
images: []
|
images: []
|
||||||
},
|
},
|
||||||
validationSchema: schema.addNewProduct,
|
validationSchema: schema.addNewItem,
|
||||||
onSubmit: (values, onSubmitProps) => {
|
onSubmit: (values, onSubmitProps) => {
|
||||||
LOGGER.log('values', values);
|
LOGGER.log('values', values);
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -92,25 +101,33 @@ function AddNewProduct() {
|
|||||||
slug: API.ADD_PRODUCT,
|
slug: API.ADD_PRODUCT,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data: {
|
||||||
commonName: values.warehousename,
|
commonName: values.commonName,
|
||||||
formalName: values.formalname,
|
formalName: values.formalName,
|
||||||
description: values.description,
|
description: values.description,
|
||||||
manufacturer: values.manufacturer,
|
manufacturer: values.manufacturer,
|
||||||
size: values.size,
|
size: values.size,
|
||||||
color: values.color,
|
color: values.color,
|
||||||
type: values.type,
|
type: values.type,
|
||||||
unitOfMaterial: values.unitofmaterial,
|
unitOfMaterial: values.unitOfMaterial,
|
||||||
unitCost: values.unitcost,
|
unitCost: values.unitCost,
|
||||||
packageCount: values.packagecount,
|
packageCount: values.packageCount,
|
||||||
countPerPallet: values.countperpallet,
|
countPerPallet: values.countPerPallet,
|
||||||
countPerPalletPackage: values.countperpalletpackage,
|
countPerPalletPackage: values.countPerPalletPackage,
|
||||||
customAttributes: [
|
customAttributes: [],
|
||||||
{ fieldName: 'someName', fieldType: 'String', fieldValue: 'someValue' }
|
policiesMetadata: {
|
||||||
],
|
underStockLevelCount: values.policiesMetadata.underStockLevelCount,
|
||||||
widgetFamilyId: '61dcdd10699e8f55b44c606d'
|
overStockLevelCount: values.policiesMetadata.overStockLevelCount,
|
||||||
|
alertStockLevelCount: values.policiesMetadata.alertStockLevelCount,
|
||||||
|
reorderStockLevelCount: values.policiesMetadata.reorderStockLevelCount
|
||||||
|
},
|
||||||
|
widgetFamilyId:
|
||||||
|
values.secondaryWidgetFamilyId === ''
|
||||||
|
? values.primaryWidgetFamilyId
|
||||||
|
: values.secondaryWidgetFamilyId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
// navigate to inventory page?
|
||||||
onSubmitProps.resetForm();
|
onSubmitProps.resetForm();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -124,8 +141,8 @@ function AddNewProduct() {
|
|||||||
{ 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: 'Products' },
|
{ name: `${widgetName || 'Item'}` },
|
||||||
{ name: 'Add New Product' }
|
{ name: `Add New ${widgetName || 'Item'}` }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Box mx={3} my={3}>
|
<Box mx={3} my={3}>
|
||||||
@@ -135,16 +152,16 @@ function AddNewProduct() {
|
|||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item xs={12} sm={6} md={6}>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Warehouse name
|
{widgetName || 'Item'} name
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="warehousename"
|
name="commonName"
|
||||||
type="text"
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.warehousename}
|
value={formik.values.commonName}
|
||||||
error={formik.touched.warehousename && Boolean(formik.errors.warehousename)}
|
error={formik.touched.commonName && Boolean(formik.errors.commonName)}
|
||||||
helperText={formik.touched.warehousename && formik.errors.warehousename}
|
helperText={formik.touched.commonName && formik.errors.commonName}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -170,91 +187,46 @@ function AddNewProduct() {
|
|||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Manufacturer
|
Manufacturer
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth>
|
<MDInput
|
||||||
<Select
|
fullWidth
|
||||||
select
|
name="manufacturer"
|
||||||
fullWidth
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="manufacturer"
|
value={formik.values.manufacturer}
|
||||||
value={formik.values.manufacturer}
|
error={formik.touched.manufacturer && Boolean(formik.errors.manufacturer)}
|
||||||
error={formik.touched.manufacturer && Boolean(formik.errors.manufacturer)}
|
helperText={formik.touched.manufacturer && formik.errors.manufacturer}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
>
|
/>
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<FormHelperText>
|
|
||||||
{formik.errors.manufacturer &&
|
|
||||||
formik.touched.manufacturer &&
|
|
||||||
formik.errors.manufacturer}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Type
|
Type
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth>
|
<MDInput
|
||||||
<Select
|
fullWidth
|
||||||
select
|
name="type"
|
||||||
fullWidth
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="type"
|
value={formik.values.type}
|
||||||
value={formik.values.type}
|
error={formik.touched.type && Boolean(formik.errors.type)}
|
||||||
error={formik.touched.type && Boolean(formik.errors.type)}
|
helperText={formik.touched.type && formik.errors.type}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
>
|
/>
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<FormHelperText>
|
|
||||||
{formik.errors.type && formik.touched.type && formik.errors.type}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Unit of Material
|
Unit of Material
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth>
|
<MDInput
|
||||||
<Select
|
fullWidth
|
||||||
select
|
name="unitOfMaterial"
|
||||||
fullWidth
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="unitofmaterial"
|
value={formik.values.unitOfMaterial}
|
||||||
value={formik.values.unitofmaterial}
|
error={formik.touched.unitOfMaterial && Boolean(formik.errors.unitOfMaterial)}
|
||||||
error={
|
helperText={formik.touched.unitOfMaterial && formik.errors.unitOfMaterial}
|
||||||
formik.touched.unitofmaterial && Boolean(formik.errors.unitofmaterial)
|
onChange={formik.handleChange}
|
||||||
}
|
/>
|
||||||
onChange={formik.handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<FormHelperText>
|
|
||||||
{formik.errors.unitofmaterial &&
|
|
||||||
formik.touched.unitofmaterial &&
|
|
||||||
formik.errors.unitofmaterial}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
@@ -262,12 +234,12 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="packagecount"
|
name="packageCount"
|
||||||
type="text"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.packagecount}
|
value={formik.values.packageCount}
|
||||||
error={formik.touched.packagecount && Boolean(formik.errors.packagecount)}
|
error={formik.touched.packageCount && Boolean(formik.errors.packageCount)}
|
||||||
helperText={formik.touched.packagecount && formik.errors.packagecount}
|
helperText={formik.touched.packageCount && formik.errors.packageCount}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -279,12 +251,12 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="formalname"
|
name="formalName"
|
||||||
type="text"
|
type="text"
|
||||||
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}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -292,57 +264,31 @@ function AddNewProduct() {
|
|||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Size
|
Size
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth>
|
<MDInput
|
||||||
<Select
|
fullWidth
|
||||||
select
|
name="size"
|
||||||
fullWidth
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="size"
|
value={formik.values.size}
|
||||||
value={formik.values.size}
|
error={formik.touched.size && Boolean(formik.errors.size)}
|
||||||
error={formik.touched.size && Boolean(formik.errors.size)}
|
helperText={formik.touched.size && formik.errors.size}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
>
|
/>
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<FormHelperText>
|
|
||||||
{formik.errors.size && formik.touched.size && formik.errors.size}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Color
|
Color
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth>
|
<MDInput
|
||||||
<Select
|
fullWidth
|
||||||
select
|
name="color"
|
||||||
fullWidth
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="color"
|
value={formik.values.color}
|
||||||
value={formik.values.color}
|
error={formik.touched.color && Boolean(formik.errors.color)}
|
||||||
error={formik.touched.color && Boolean(formik.errors.color)}
|
helperText={formik.touched.color && formik.errors.color}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
>
|
/>
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<FormHelperText>
|
|
||||||
{formik.errors.color && formik.touched.color && formik.errors.color}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '24px' }}>
|
<Box component="div" sx={{ marginBottom: '24px' }}>
|
||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
@@ -350,12 +296,12 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="unitcost"
|
name="unitCost"
|
||||||
type="text"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.unitcost}
|
value={formik.values.unitCost}
|
||||||
error={formik.touched.unitcost && Boolean(formik.errors.unitcost)}
|
error={formik.touched.unitCost && Boolean(formik.errors.unitCost)}
|
||||||
helperText={formik.touched.unitcost && formik.errors.unitcost}
|
helperText={formik.touched.unitCost && formik.errors.unitCost}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -365,12 +311,12 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="countperpallet"
|
name="countPerPallet"
|
||||||
type="text"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.countperpallet}
|
value={formik.values.countPerPallet}
|
||||||
error={formik.touched.countperpallet && Boolean(formik.errors.countperpallet)}
|
error={formik.touched.countPerPallet && Boolean(formik.errors.countPerPallet)}
|
||||||
helperText={formik.touched.countperpallet && formik.errors.countperpallet}
|
helperText={formik.touched.countPerPallet && formik.errors.countPerPallet}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -380,16 +326,16 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="countperpalletpackage"
|
name="countPerPalletPackage"
|
||||||
type="text"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.countperpalletpackage}
|
value={formik.values.countPerPalletPackage}
|
||||||
error={
|
error={
|
||||||
formik.touched.countperpalletpackage &&
|
formik.touched.countPerPalletPackage &&
|
||||||
Boolean(formik.errors.countperpalletpackage)
|
Boolean(formik.errors.countPerPalletPackage)
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
formik.touched.countperpalletpackage && formik.errors.countperpalletpackage
|
formik.touched.countPerPalletPackage && formik.errors.countPerPalletPackage
|
||||||
}
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
@@ -398,32 +344,36 @@ function AddNewProduct() {
|
|||||||
<Box component="div" className={classes.labelSize}>
|
<Box component="div" className={classes.labelSize}>
|
||||||
Product Family Association
|
Product Family Association
|
||||||
</Box>
|
</Box>
|
||||||
<FormControl fullWidth sx={{ marginBottom: '32px' }}>
|
<FormControl fullWidth>
|
||||||
<Select
|
<Select
|
||||||
select
|
select
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="productfamilyassociation"
|
name="primaryWidgetFamilyId"
|
||||||
value={formik.values.productfamilyassociation}
|
value={formik.values.primaryWidgetFamilyId}
|
||||||
error={
|
error={
|
||||||
formik.touched.productfamilyassociation &&
|
formik.touched.primaryWidgetFamilyId &&
|
||||||
Boolean(formik.errors.productfamilyassociation)
|
Boolean(formik.errors.primaryWidgetFamilyId)
|
||||||
}
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={(e, ...rest) => {
|
||||||
|
setPFam(e.target.value);
|
||||||
|
formik.handleChange(e, ...rest);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem key={''} value={''}>
|
<MenuItem key={'none'} value={''}>
|
||||||
None Selected
|
None Selected
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{inventoryTypes.map((name) => (
|
{primaryFamily &&
|
||||||
<MenuItem key={name} value={name}>
|
primaryFamily.map((fam) => (
|
||||||
{name}
|
<MenuItem key={fam._id} value={fam._id}>
|
||||||
</MenuItem>
|
{fam.name}
|
||||||
))}
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<FormHelperText>
|
<FormHelperText>
|
||||||
{formik.errors.productfamilyassociation &&
|
{formik.errors.primaryWidgetFamilyId &&
|
||||||
formik.touched.productfamilyassociation &&
|
formik.touched.primaryWidgetFamilyId &&
|
||||||
formik.errors.productfamilyassociation}
|
formik.errors.primaryWidgetFamilyId}
|
||||||
</FormHelperText>
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
@@ -431,27 +381,28 @@ function AddNewProduct() {
|
|||||||
select
|
select
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
name="productfamilyassociation"
|
name="secondaryWidgetFamilyId"
|
||||||
value={formik.values.productfamilyassociation}
|
value={formik.values.secondaryWidgetFamilyId}
|
||||||
error={
|
error={
|
||||||
formik.touched.productfamilyassociation &&
|
formik.touched.secondaryWidgetFamilyId &&
|
||||||
Boolean(formik.errors.productfamilyassociation)
|
Boolean(formik.errors.secondaryWidgetFamilyId)
|
||||||
}
|
}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
>
|
>
|
||||||
<MenuItem key={''} value={''}>
|
<MenuItem key={'none'} value={''}>
|
||||||
None Selected
|
None Selected
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{inventoryTypes.map((name) => (
|
{secondaryFamily &&
|
||||||
<MenuItem key={name} value={name}>
|
secondaryFamily.map((fam) => (
|
||||||
{name}
|
<MenuItem key={fam._id} value={fam._id}>
|
||||||
</MenuItem>
|
{fam.name}
|
||||||
))}
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<FormHelperText>
|
<FormHelperText>
|
||||||
{formik.errors.productfamilyassociation &&
|
{formik.errors.secondaryWidgetFamilyId &&
|
||||||
formik.touched.productfamilyassociation &&
|
formik.touched.secondaryWidgetFamilyId &&
|
||||||
formik.errors.productfamilyassociation}
|
formik.errors.secondaryWidgetFamilyId}
|
||||||
</FormHelperText>
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -459,7 +410,6 @@ function AddNewProduct() {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Box>
|
<Box>
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
multiple
|
|
||||||
heading="Upload Product Image"
|
heading="Upload Product Image"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
images={formik.values.images}
|
images={formik.values.images}
|
||||||
@@ -482,7 +432,9 @@ function AddNewProduct() {
|
|||||||
size="large"
|
size="large"
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={handleClickOpen}
|
onClick={() => {
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
add custom fields
|
add custom fields
|
||||||
</MDButton>
|
</MDButton>
|
||||||
@@ -508,12 +460,10 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="under"
|
name="policiesMetadata.underStockLevelCount"
|
||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.under}
|
value={formik.values.policiesMetadata.underStockLevelCount}
|
||||||
error={formik.touched.under && Boolean(formik.errors.under)}
|
|
||||||
helperText={formik.touched.under && formik.errors.under}
|
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -523,12 +473,10 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="over"
|
name="policiesMetadata.overStockLevelCount"
|
||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.over}
|
value={formik.values.policiesMetadata.overStockLevelCount}
|
||||||
error={formik.touched.over && Boolean(formik.errors.over)}
|
|
||||||
helperText={formik.touched.over && formik.errors.over}
|
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -538,12 +486,23 @@ function AddNewProduct() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="alert"
|
name="policiesMetadata.alertStockLevelCount"
|
||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.alert}
|
value={formik.values.policiesMetadata.alertStockLevelCount}
|
||||||
error={formik.touched.alert && Boolean(formik.errors.alert)}
|
onChange={formik.handleChange}
|
||||||
helperText={formik.touched.alert && formik.errors.alert}
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Box component="div" className={classes.labelSize}>
|
||||||
|
Reorder
|
||||||
|
</Box>
|
||||||
|
<MDInput
|
||||||
|
fullWidth
|
||||||
|
name="policiesMetadata.reorderStockLevelCount"
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
value={formik.values.policiesMetadata.reorderStockLevelCount}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -558,10 +517,10 @@ function AddNewProduct() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MDButton size="medium" color="error" variant="outlined">
|
<MDButton size="medium" color="error" variant="outlined">
|
||||||
cancel
|
Cancel
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
<MDButton size="medium" color="primary" variant="contained" type="submit">
|
||||||
add ITem
|
Add {widgetName}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -584,7 +543,12 @@ function AddNewProduct() {
|
|||||||
padding: '10px 20px'
|
padding: '10px 20px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MDButton sx={{ padding: '0px', minWidth: '14px' }} onClick={handleClose}>
|
<MDButton
|
||||||
|
sx={{ padding: '0px', minWidth: '14px' }}
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<CrossIcon className={classes.cursorPointer} />
|
<CrossIcon className={classes.cursorPointer} />
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -628,7 +592,9 @@ function AddNewProduct() {
|
|||||||
return <em>Placeholder</em>;
|
return <em>Placeholder</em>;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={handleChange}
|
onChange={(event) => {
|
||||||
|
setManufacturer(event.target.value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value={10}>Ten</MenuItem>
|
<MenuItem value={10}>Ten</MenuItem>
|
||||||
<MenuItem value={20}>Twenty</MenuItem>
|
<MenuItem value={20}>Twenty</MenuItem>
|
||||||
@@ -648,7 +614,9 @@ function AddNewProduct() {
|
|||||||
return <em>Placeholder</em>;
|
return <em>Placeholder</em>;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={handleChange}
|
onChange={(event) => {
|
||||||
|
setManufacturer(event.target.value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value={10}>Ten</MenuItem>
|
<MenuItem value={10}>Ten</MenuItem>
|
||||||
<MenuItem value={20}>Twenty</MenuItem>
|
<MenuItem value={20}>Twenty</MenuItem>
|
||||||
@@ -783,4 +751,4 @@ function AddNewProduct() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddNewProduct;
|
export default AddNewItem;
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
|
import React from 'react';
|
||||||
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, TableBody, TableCell, TableRow } from '@mui/material';
|
import { Box, Grid, MenuItem, Select } from '@mui/material';
|
||||||
import MDInput from 'components/MDInput';
|
import MDInput from 'components/MDInput';
|
||||||
import ImageUpload from 'components/ImageUpload';
|
import ImageUpload from 'components/ImageUpload';
|
||||||
import Switch from 'components/Switch';
|
import Switch from 'components/Switch';
|
||||||
import MDTypography from 'components/MDTypography';
|
import MDTypography from 'components/MDTypography';
|
||||||
import MDBox from 'components/MDBox';
|
import MDBox from 'components/MDBox';
|
||||||
import Dropdown from 'components/Dropdown';
|
|
||||||
import MDButton from 'components/Button';
|
import MDButton from 'components/Button';
|
||||||
import BasicTable from 'components/BasicTable';
|
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import schema from 'services/ValidationServices';
|
import schema from 'services/ValidationServices';
|
||||||
import { API } from 'constant';
|
import { API } from 'constant';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import InventoryActions from 'redux/InventoryRedux';
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
import LOGGER from 'services/Logger';
|
import LOGGER from 'services/Logger';
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import WidgetNestedDataTable from 'components/WidgetNestedDataTable';
|
||||||
|
|
||||||
const customStyles = {
|
const customStyles = {
|
||||||
labelSize: {
|
labelSize: {
|
||||||
@@ -49,110 +52,98 @@ const customStyles = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const stockBox = [
|
const definedPolicies = [
|
||||||
{
|
{
|
||||||
text: 'Stock Tracking'
|
text: 'Order Tracking',
|
||||||
|
key: 'orderTracking'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Replenishment'
|
text: 'Replenishment',
|
||||||
|
key: 'replenishment'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Alerting'
|
text: 'Alerting',
|
||||||
|
key: 'alerting'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Check In/Out'
|
text: 'Location',
|
||||||
},
|
key: 'preferredLocations'
|
||||||
{
|
|
||||||
text: 'Maintenance'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Location'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const records = [
|
|
||||||
{
|
|
||||||
level1: 'Ipsum',
|
|
||||||
level2: 'Vivera'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
level1: 'Ipsum',
|
|
||||||
level2: 'Vivera'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const headCells = [
|
|
||||||
{
|
|
||||||
id: 'level1',
|
|
||||||
label: 'Level 1'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'level2',
|
|
||||||
label: 'Level 2'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const dropdownData = [
|
|
||||||
{
|
|
||||||
ID: '1',
|
|
||||||
displayname: 'Regular, full time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: '2',
|
|
||||||
displayname: 'Regular, part time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: '3',
|
|
||||||
displayname: 'Contractor- Arise Max'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const inventoryTypes = ['Perishable', 'Material', 'Product', 'Inventory', 'Fleet'];
|
|
||||||
|
|
||||||
const dataLevel = [
|
|
||||||
{
|
|
||||||
placeholder: 'Lorem Ipsum',
|
|
||||||
label: 'Level 1'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
placeholder: 'Lorem Ipsum',
|
|
||||||
label: 'Level 2'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function InventoryScreen() {
|
function InventoryScreen() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { inventoryId } = useParams();
|
||||||
|
|
||||||
|
const currentInventoryData = useSelector(InventorySelectors.getInventoryDetailById(inventoryId));
|
||||||
|
LOGGER.log({ currentInventoryData });
|
||||||
|
// const [inventoryAllData, setInventoryAllData] = useState([]);
|
||||||
|
// const initialInventoryName='';
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const filterData = inventoryData.filter((item) => item._id === inventoryId);
|
||||||
|
// console.log('filterData', filterData);
|
||||||
|
// setInitialInventoryName(filterData[0].name)
|
||||||
|
// setInventoryAllData(filterData[0].widgetName);
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// LOGGER.log('initialInventoryName', initialInventoryName);
|
||||||
|
|
||||||
|
/* eslint-disable indent */
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: inventoryId
|
||||||
inventoryname: '',
|
? {
|
||||||
inventorytype: '',
|
name: currentInventoryData.name,
|
||||||
widgetname: '',
|
widgetName: currentInventoryData.widgetName,
|
||||||
policies: false,
|
policies: {
|
||||||
images: []
|
orderTracking: currentInventoryData.policies.orderTracking,
|
||||||
},
|
alerting: currentInventoryData.policies.alerting,
|
||||||
|
replenishment: currentInventoryData.policies.replenishment,
|
||||||
|
preferredLocations: false, // TODO: change later when implemented on BE
|
||||||
|
inventory_process: currentInventoryData.policies.inventory_process
|
||||||
|
},
|
||||||
|
image: [{ src: currentInventoryData.image }]
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
name: '',
|
||||||
|
widgetName: '',
|
||||||
|
policies: {
|
||||||
|
orderTracking: false,
|
||||||
|
alerting: false,
|
||||||
|
replenishment: false,
|
||||||
|
preferredLocations: false,
|
||||||
|
inventory_process: 'CCR'
|
||||||
|
},
|
||||||
|
image: []
|
||||||
|
},
|
||||||
validationSchema: schema.addInventory,
|
validationSchema: schema.addInventory,
|
||||||
onSubmit: (values, onSubmitProps) => {
|
onSubmit: (values, onSubmitProps) => {
|
||||||
LOGGER.log('values', values);
|
LOGGER.log('values', values);
|
||||||
dispatch(
|
inventoryId
|
||||||
InventoryActions.addInventoryAction({
|
? dispatch(
|
||||||
loader: 'loading-request',
|
InventoryActions.updateInventoryAction({
|
||||||
slug: API.ADD_INVENTORY,
|
loader: 'loading-request',
|
||||||
method: 'post',
|
slug: `${API.ADD_INVENTORY}/${inventoryId}`,
|
||||||
data: {
|
method: 'patch',
|
||||||
name: values.inventoryname,
|
data: {
|
||||||
type: values.inventorytype,
|
...values,
|
||||||
policies: {
|
image: values.image[0]?.file || null
|
||||||
alerting: {
|
|
||||||
lowestStockLevel: true,
|
|
||||||
highestStockLevel: true,
|
|
||||||
alertStockLevel: true,
|
|
||||||
reOrderLevel: true
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
)
|
||||||
})
|
: dispatch(
|
||||||
);
|
InventoryActions.addInventoryAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.ADD_INVENTORY,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
...values,
|
||||||
|
image: values.image[0]?.file || null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
// navigate to edit inventory page
|
||||||
onSubmitProps.resetForm();
|
onSubmitProps.resetForm();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -187,67 +178,43 @@ function InventoryScreen() {
|
|||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="inventoryname"
|
disabled={inventoryId}
|
||||||
|
name="name"
|
||||||
type="text"
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={formik.values.inventoryname}
|
value={formik.values.name}
|
||||||
error={formik.touched.inventoryname && Boolean(formik.errors.inventoryname)}
|
error={formik.touched.name && Boolean(formik.errors.name)}
|
||||||
helpertText={formik.touched.inventoryname && formik.errors.inventoryname}
|
helpertText={formik.touched.name && formik.errors.name}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box component="div" sx={{ marginBottom: '20px' }}>
|
|
||||||
<Box component="div" sx={customStyles.labelSize}>
|
|
||||||
Inventory Type
|
|
||||||
</Box>
|
|
||||||
<Select
|
|
||||||
select
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
name="inventorytype"
|
|
||||||
value={formik.values.inventorytype}
|
|
||||||
error={formik.touched.inventorytype && Boolean(formik.errors.inventorytype)}
|
|
||||||
helperText={formik.touched.inventorytype && formik.errors.inventorytype}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
>
|
|
||||||
<MenuItem key={''} value={''}>
|
|
||||||
None Selected
|
|
||||||
</MenuItem>
|
|
||||||
{inventoryTypes.map((name) => (
|
|
||||||
<MenuItem key={name} value={name}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Grid item xs={12} sm={12} md={12}>
|
<Grid item xs={12}>
|
||||||
<Box component="div" sx={customStyles.labelSize}>
|
<Box component="div" sx={customStyles.labelSize}>
|
||||||
Widget Name
|
Widget Name
|
||||||
</Box>
|
</Box>
|
||||||
<MDInput
|
<MDInput
|
||||||
fullWidth
|
fullWidth
|
||||||
name="widgetname"
|
disabled={inventoryId}
|
||||||
|
name="widgetName"
|
||||||
type="text"
|
type="text"
|
||||||
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}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<MDBox sx={{ my: 4 }}>
|
<MDBox sx={{ my: 4 }}>
|
||||||
<MDTypography variant="h5">Policies</MDTypography>
|
<MDTypography variant="h5">Policies</MDTypography>
|
||||||
<MDTypography sx={customStyles.textSize}>
|
<MDTypography sx={customStyles.textSize}>
|
||||||
Egestas pulvinar ornare vulputate porttitor consectetur condimentum at tellus
|
Choose policies to be applied
|
||||||
quis. Leo pellentesque ipsum, a purus dignissim aliquam, orci. Elementum
|
|
||||||
ullamcorper a sit eleifend ante ullamcorper ornare mi pharetra.
|
|
||||||
</MDTypography>
|
</MDTypography>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
<MDBox
|
<MDBox
|
||||||
mr={{ xs: 0, xl: 8 }}
|
mr={{ xs: 0, xl: 8 }}
|
||||||
sx={{
|
sx={{
|
||||||
width: '40%',
|
width: '60%',
|
||||||
padding: '12.5px 10px',
|
padding: '12.5px 10px',
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
border: 'solid 0.5px #c4c4c4',
|
border: 'solid 0.5px #c4c4c4',
|
||||||
@@ -256,87 +223,69 @@ function InventoryScreen() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div sx={customStyles.wrap}>
|
<div sx={customStyles.wrap}>
|
||||||
{stockBox.map((item) => (
|
{definedPolicies.map((item) => (
|
||||||
<>
|
<div sx={customStyles.gridWrap} key={item.key}>
|
||||||
<div sx={customStyles.gridWrap}>
|
<MDTypography sx={customStyles.textWrap}>{item.text}</MDTypography>
|
||||||
<MDTypography sx={customStyles.textWrap}>{item.text}</MDTypography>
|
<Switch
|
||||||
<Switch
|
disabled={inventoryId}
|
||||||
name="policies"
|
name={`policies.${item.key}`}
|
||||||
checked={formik.values.policies}
|
checked={formik.values.policies[item.key]}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
))}
|
))}
|
||||||
|
<Box component="div" sx={{ marginBottom: '20px' }}>
|
||||||
|
<Box component="div" sx={customStyles.labelSize}>
|
||||||
|
Inventory Process
|
||||||
|
</Box>
|
||||||
|
<Select
|
||||||
|
select
|
||||||
|
fullWidth
|
||||||
|
disabled={inventoryId}
|
||||||
|
variant="outlined"
|
||||||
|
name="policies.inventory_process"
|
||||||
|
value={formik.values.policies.inventory_process}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem key="CCR" value="CCR">
|
||||||
|
CCR
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key="PPR" value="PPR">
|
||||||
|
PPR
|
||||||
|
</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={6}>
|
<Grid item xs={12} sm={6} md={6}>
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
multiple
|
heading="Upload Inventory Image"
|
||||||
heading="Upload Inventory Images"
|
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
images={formik.values.images}
|
images={formik.values.image}
|
||||||
setImages={(images) => {
|
setImages={(images) => {
|
||||||
formik.setFieldValue('images', images);
|
formik.setFieldValue('image', images);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={12} md={12}>
|
<MDBox sx={{ ml: 'auto', mr: 'auto', mt: 3 }}>
|
||||||
<Grid container spacing={1}>
|
<MDButton
|
||||||
{dataLevel &&
|
sx={{ ml: 3 }}
|
||||||
dataLevel.map((item, index) => (
|
color="error"
|
||||||
<Grid item xs={12} sm={6} md={4} key={index}>
|
variant="outlined"
|
||||||
<Dropdown items={item} dropdownData={dropdownData} />
|
onClick={() => {
|
||||||
</Grid>
|
navigate('/setup/inventory');
|
||||||
))}
|
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
|
||||||
<MDButton color="primary" circular="true" sx={customStyles.marginTop}>
|
|
||||||
{'add hierarchy level'}
|
|
||||||
</MDButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sm={12} md={12}>
|
|
||||||
<MDBox
|
|
||||||
sx={{
|
|
||||||
// backgroundColor: '#E5E5E5',
|
|
||||||
width: '100%',
|
|
||||||
padding: '9px'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MDTypography
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#E5E5E5',
|
|
||||||
width: '100%',
|
|
||||||
padding: '9px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Widget hierarchy
|
|
||||||
</MDTypography>
|
|
||||||
<BasicTable
|
|
||||||
headCells={headCells}
|
|
||||||
records={records}
|
|
||||||
backgroundColor="#E5E5E5"
|
|
||||||
color="#343434"
|
|
||||||
>
|
|
||||||
<TableBody>
|
|
||||||
{records &&
|
|
||||||
records.map((item) => (
|
|
||||||
<TableRow key={item.id}>
|
|
||||||
<TableCell>{item.level1}</TableCell>
|
|
||||||
<TableCell>{item.level2}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</BasicTable>
|
|
||||||
</MDBox>
|
|
||||||
</Grid>
|
|
||||||
<MDBox sx={{ ml: 'auto', mr: 'auto', mt: 3 }}>
|
|
||||||
<MDButton sx={{ ml: 3 }} color="error" variant="outlined">
|
|
||||||
{'CANCEL'}
|
{'CANCEL'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton sx={{ ml: 3 }} color="primary" variant="outlined" type="submit">
|
<MDButton
|
||||||
|
sx={{ ml: 3 }}
|
||||||
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
|
disabled={inventoryId}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
{'SAVE'}
|
{'SAVE'}
|
||||||
</MDButton>
|
</MDButton>
|
||||||
<MDButton sx={{ ml: 3 }} color="primary">
|
<MDButton sx={{ ml: 3 }} color="primary">
|
||||||
@@ -346,6 +295,7 @@ function InventoryScreen() {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</form>
|
</form>
|
||||||
|
{inventoryId ? <WidgetNestedDataTable inventoryId={inventoryId} /> : null}
|
||||||
</MDBox>
|
</MDBox>
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,42 +5,53 @@ import EquipmentIcon from 'assets/images/EquimpmentIcon';
|
|||||||
import ProductsIcon from 'assets/images/ProductsIcon';
|
import ProductsIcon from 'assets/images/ProductsIcon';
|
||||||
import FleetIcon from 'assets/images/FleetIcon';
|
import FleetIcon from 'assets/images/FleetIcon';
|
||||||
import RawMaterialIcon from 'assets/images/RawMaterialIcon';
|
import RawMaterialIcon from 'assets/images/RawMaterialIcon';
|
||||||
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
|
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||||
import { Grid } from '@mui/material';
|
import { Grid } from '@mui/material';
|
||||||
import Tile from 'components/TileComponent';
|
import Tile from 'components/TileComponent';
|
||||||
import MDButton from 'components/Button';
|
import MDButton from 'components/Button';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import Breadcrumbs from 'components/Breadcrumbs';
|
import Breadcrumbs from 'components/Breadcrumbs';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { API } from 'constant';
|
||||||
|
|
||||||
|
function getIconFromSlug(slug) {
|
||||||
|
switch (slug) {
|
||||||
|
case 'equipment':
|
||||||
|
return <EquipmentIcon />;
|
||||||
|
case 'product':
|
||||||
|
return <ProductsIcon />;
|
||||||
|
case 'fleet':
|
||||||
|
return <FleetIcon />;
|
||||||
|
case 'rawmaterial':
|
||||||
|
default:
|
||||||
|
return <RawMaterialIcon />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function SetupInventory() {
|
function SetupInventory() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const inventoryData = useSelector(InventorySelectors.getInventoryDetail);
|
||||||
|
const [inventoryAllData, setInventoryAllData] = useState([]);
|
||||||
|
|
||||||
const tiles = [
|
useEffect(() => {
|
||||||
{
|
if (inventoryData?.length) {
|
||||||
name: 'Raw Material',
|
setInventoryAllData(inventoryData);
|
||||||
path: { update: '/', addNew: '/', cycleCount: '/', list: '/' },
|
|
||||||
icon: <RawMaterialIcon />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Products',
|
|
||||||
path: {
|
|
||||||
update: '/',
|
|
||||||
addNew: '/setup/inventory/product/add-new-product',
|
|
||||||
cycleCount: '/',
|
|
||||||
list: '/'
|
|
||||||
},
|
|
||||||
icon: <ProductsIcon />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Equipment',
|
|
||||||
path: { update: '/', addNew: '/', cycleCount: '/', list: '/' },
|
|
||||||
icon: <EquipmentIcon />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Fleet',
|
|
||||||
path: { update: '/', addNew: '/', cycleCount: '/', list: '/' },
|
|
||||||
icon: <FleetIcon />
|
|
||||||
}
|
}
|
||||||
];
|
}, [inventoryData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(
|
||||||
|
InventoryActions.getInventoryAction({
|
||||||
|
loader: 'loading-request',
|
||||||
|
slug: API.GET_INVENTORY,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<DashboardNavbar />
|
<DashboardNavbar />
|
||||||
@@ -51,20 +62,18 @@ function SetupInventory() {
|
|||||||
{ name: 'Inventory' }
|
{ name: 'Inventory' }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<MDButton
|
<MDButton sx={{ ml: 3 }} color="primary" onClick={() => navigate('/setup/inventory/new')}>
|
||||||
sx={{ ml: 3 }}
|
|
||||||
color="primary"
|
|
||||||
onClick={() => navigate('/setup/inventory/inventory-new')}
|
|
||||||
>
|
|
||||||
Create Inventory
|
Create Inventory
|
||||||
</MDButton>
|
</MDButton>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<MDBox px={2} py={3}>
|
<MDBox px={2} py={3}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{tiles &&
|
{inventoryAllData &&
|
||||||
tiles.map((tile) => (
|
inventoryAllData.map((tile) => (
|
||||||
<Grid item xs={12} sm={6} md={tiles.length > 4 ? 4 : 6} key={tile.name}>
|
<Grid item xs={12} sm={6} md={inventoryAllData?.length > 4 ? 4 : 6} key={tile._id}>
|
||||||
<Tile data={{ name: tile.name, path: tile.path }}>{tile.icon}</Tile>
|
<Tile data={{ name: tile?.name, widgetname: tile?.widgetName, id: tile?._id }}>
|
||||||
|
{getIconFromSlug(tile.icon_slug)}
|
||||||
|
</Tile>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -5,9 +5,18 @@ import { getFetchingValue, getErrorValue } from '../services/Utils';
|
|||||||
|
|
||||||
/* ------------- Types and Action Creators ------------- */
|
/* ------------- Types and Action Creators ------------- */
|
||||||
const { Types, Creators } = createActions({
|
const { Types, Creators } = createActions({
|
||||||
|
getInventoryAction: ['payload'],
|
||||||
|
getInventorySuccess: ['data'],
|
||||||
|
getInventoryFailure: ['error'],
|
||||||
addInventoryAction: ['payload'],
|
addInventoryAction: ['payload'],
|
||||||
addInventorySuccess: ['data'],
|
addInventorySuccess: ['data'],
|
||||||
addInventoryFailure: ['error']
|
addInventoryFailure: ['error'],
|
||||||
|
updateInventoryAction: ['payload'],
|
||||||
|
updateInventorySuccess: ['data'],
|
||||||
|
updateInventoryFailure: ['error'],
|
||||||
|
getInventoryTypesAction: ['payload'],
|
||||||
|
getInventoryTypesSuccess: ['data'],
|
||||||
|
getInventoryTypesFailure: ['error']
|
||||||
});
|
});
|
||||||
|
|
||||||
export const InventoryTypes = Types;
|
export const InventoryTypes = Types;
|
||||||
@@ -16,17 +25,44 @@ export default InventoryActions;
|
|||||||
|
|
||||||
/* ------------- Initial State ------------- */
|
/* ------------- Initial State ------------- */
|
||||||
export const INITIAL_STATE = Immutable({
|
export const INITIAL_STATE = Immutable({
|
||||||
|
getInventoryDetail: [],
|
||||||
addInventoryDetail: [],
|
addInventoryDetail: [],
|
||||||
|
updateInventoryDetail: [],
|
||||||
addInventoryLoading: false,
|
addInventoryLoading: false,
|
||||||
addInventoryerror: {}
|
addInventoryerror: {},
|
||||||
|
inventoryTypes: []
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ------------- Selectors ------------- */
|
/* ------------- Selectors ------------- */
|
||||||
export const InventorySelectors = {
|
export const InventorySelectors = {
|
||||||
addInventoryDetail: (state) => state.inventory.inventoryDetail
|
addInventoryDetail: (state) => state.inventory.inventoryDetail,
|
||||||
|
getInventoryDetail: (state) => state.inventory.getInventoryDetail,
|
||||||
|
getInventoryDetailById: (id) => (state) =>
|
||||||
|
state.inventory.getInventoryDetail.find((x) => x._id === id),
|
||||||
|
getInventoryTypes: (state) => state.inventory.inventoryTypes,
|
||||||
|
updateInventoryDetail: (state) => state.inventory.updateInventoryDetail
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------- Reducers ------------- */
|
/* ------------- Reducers ------------- */
|
||||||
|
export const onGetInventoryAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetInventorySuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
getInventoryDetail: data.getInventoryDetail
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetInventoryFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
|
|
||||||
export const onAddInventoryAction = (state, { payload }) =>
|
export const onAddInventoryAction = (state, { payload }) =>
|
||||||
state.merge({
|
state.merge({
|
||||||
fetching: _.uniq([state.fetching, payload?.loader]),
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
@@ -37,7 +73,7 @@ export const onAddInventorySuccess = (state, { data }) =>
|
|||||||
state.merge({
|
state.merge({
|
||||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
error: getErrorValue(state?.error, data?.loader),
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
addInventoryDetail: data.addInventoryDetail
|
getInventoryDetail: [...state.getInventoryDetail, data.newInventory]
|
||||||
});
|
});
|
||||||
|
|
||||||
export const onAddInventoryFailure = (state, { error }) =>
|
export const onAddInventoryFailure = (state, { error }) =>
|
||||||
@@ -46,9 +82,59 @@ export const onAddInventoryFailure = (state, { error }) =>
|
|||||||
error: { ...state.error, [error?.loader]: error?.error }
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const onUpdateInventoryAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onUpdateInventorySuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
getInventoryDetail: [
|
||||||
|
...state.getInventoryDetail.filter((x) => x._id !== data.newInventory._id),
|
||||||
|
data.newInventory
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onUpdateInventoryFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetInventoryTypesAction = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetInventoryTypesSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
inventoryTypes: data.inventoryTypes
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onGetInventoryTypesFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
|
|
||||||
/* ------------- Hookup Reducers To Types ------------- */
|
/* ------------- Hookup Reducers To Types ------------- */
|
||||||
export const inventoryReducer = createReducer(INITIAL_STATE, {
|
export const inventoryReducer = createReducer(INITIAL_STATE, {
|
||||||
|
[Types.GET_INVENTORY_ACTION]: onGetInventoryAction,
|
||||||
|
[Types.GET_INVENTORY_SUCCESS]: onGetInventorySuccess,
|
||||||
|
[Types.GET_INVENTORY_FAILURE]: onGetInventoryFailure,
|
||||||
[Types.ADD_INVENTORY_ACTION]: onAddInventoryAction,
|
[Types.ADD_INVENTORY_ACTION]: onAddInventoryAction,
|
||||||
[Types.ADD_INVENTORY_SUCCESS]: onAddInventorySuccess,
|
[Types.ADD_INVENTORY_SUCCESS]: onAddInventorySuccess,
|
||||||
[Types.ADD_INVENTORY_FAILURE]: onAddInventoryFailure
|
[Types.ADD_INVENTORY_FAILURE]: onAddInventoryFailure,
|
||||||
|
[Types.UPDATE_INVENTORY_ACTION]: onUpdateInventoryAction,
|
||||||
|
[Types.UPDATE_INVENTORY_SUCCESS]: onUpdateInventorySuccess,
|
||||||
|
[Types.UPDATE_INVENTORY_FAILURE]: onUpdateInventoryFailure,
|
||||||
|
[Types.GET_INVENTORY_TYPES_ACTION]: onGetInventoryTypesAction,
|
||||||
|
[Types.GET_INVENTORY_TYPES_SUCCESS]: onGetInventoryTypesSuccess,
|
||||||
|
[Types.GET_INVENTORY_TYPES_FAILURE]: onGetInventoryTypesFailure
|
||||||
});
|
});
|
||||||
|
|||||||
101
src/redux/WidgetRedux.js
Normal file
101
src/redux/WidgetRedux.js
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
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({
|
||||||
|
widgetRequest: ['payload'],
|
||||||
|
widgetSuccess: ['data'],
|
||||||
|
editWidgetRequest: ['payload'],
|
||||||
|
editWidgetSuccess: ['data'],
|
||||||
|
widgetFailure: ['error'],
|
||||||
|
logout: null
|
||||||
|
});
|
||||||
|
|
||||||
|
export const WidgetTypes = Types;
|
||||||
|
const WidgetActions = Creators;
|
||||||
|
export default WidgetActions;
|
||||||
|
|
||||||
|
/* ------------- Initial State ------------- */
|
||||||
|
export const INITIAL_STATE = Immutable({
|
||||||
|
list: [],
|
||||||
|
fetching: [],
|
||||||
|
error: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------- Selectors ------------- */
|
||||||
|
export const WidgetSelectors = {
|
||||||
|
getWidgets: (state) => state.widgets.list,
|
||||||
|
getWidgetById: (id) => (state) => state.widgets.list.find((x) => x._id === id),
|
||||||
|
getWidgetsByInventoryId: (id) => (state) =>
|
||||||
|
state.widgets.list.filter((x) => x.inventory._id === id),
|
||||||
|
getWidgetFamiliesByInventoryId: (id) => (state) =>
|
||||||
|
state.widgets.list.filter((x) => !x.parent && x.inventory._id === id),
|
||||||
|
getWidgetsByParentId: (id) => (state) => state.widgets.list.filter((x) => x.parent?._id === id)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------- Reducers ------------- */
|
||||||
|
export const onWidgetRequest = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onEditWidgetRequest = (state, { payload }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||||
|
error: getErrorValue(state?.error, payload?.loader)
|
||||||
|
});
|
||||||
|
|
||||||
|
const mergeWidgetStates = (stateData, widgets) => {
|
||||||
|
if (!widgets) return stateData; // undefined check
|
||||||
|
|
||||||
|
const idsInNewWidgets = widgets.map((x) => x._id);
|
||||||
|
|
||||||
|
const newState = stateData.filter((x) => !idsInNewWidgets.includes(x._id));
|
||||||
|
|
||||||
|
return [...newState, ...widgets];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onWidgetSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
list: mergeWidgetStates(state.list, data.widgets)
|
||||||
|
});
|
||||||
|
|
||||||
|
const mergeEditWidgetStates = (stateList, widget, type) => {
|
||||||
|
if (!widget) return stateList; // undefined check
|
||||||
|
|
||||||
|
if (type === 'add') {
|
||||||
|
return [...stateList, widget];
|
||||||
|
} else if (type === 'edit') {
|
||||||
|
const newState = stateList.filter((x) => x._id !== widget._id);
|
||||||
|
return [...newState, widget];
|
||||||
|
} else {
|
||||||
|
return stateList;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onEditWidgetSuccess = (state, { data }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||||
|
error: getErrorValue(state?.error, data?.loader),
|
||||||
|
list: mergeEditWidgetStates(state.list, data.widget, data.type)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const onWidgetFailure = (state, { error }) =>
|
||||||
|
state.merge({
|
||||||
|
fetching: _.without(state.fetching, error?.loader),
|
||||||
|
error: { ...state.error, [error?.loader]: error?.error }
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ------------- Hookup Reducers To Types ------------- */
|
||||||
|
export const widgetReducer = createReducer(INITIAL_STATE, {
|
||||||
|
[Types.WIDGET_REQUEST]: onWidgetRequest,
|
||||||
|
[Types.EDIT_WIDGET_REQUEST]: onEditWidgetRequest,
|
||||||
|
[Types.WIDGET_SUCCESS]: onWidgetSuccess,
|
||||||
|
[Types.EDIT_WIDGET_SUCCESS]: onEditWidgetSuccess,
|
||||||
|
[Types.WIDGET_FAILURE]: onWidgetFailure
|
||||||
|
});
|
||||||
@@ -6,6 +6,7 @@ import { productReducer } from './ProductsRedux';
|
|||||||
import { inventoryReducer } from './InventoryRedux';
|
import { inventoryReducer } from './InventoryRedux';
|
||||||
import { rolesReducer } from './RolesRedux';
|
import { rolesReducer } from './RolesRedux';
|
||||||
import { WarehouseLocationsReducer } from './WarehouseLocationsRedux';
|
import { WarehouseLocationsReducer } from './WarehouseLocationsRedux';
|
||||||
|
import { widgetReducer } from './WidgetRedux';
|
||||||
|
|
||||||
// Combine all reducers.
|
// Combine all reducers.
|
||||||
const appReducer = combineReducers({
|
const appReducer = combineReducers({
|
||||||
@@ -15,7 +16,8 @@ const appReducer = combineReducers({
|
|||||||
roles: rolesReducer,
|
roles: rolesReducer,
|
||||||
warehouseLocations: WarehouseLocationsReducer,
|
warehouseLocations: WarehouseLocationsReducer,
|
||||||
product: productReducer,
|
product: productReducer,
|
||||||
inventory: inventoryReducer
|
inventory: inventoryReducer,
|
||||||
|
widgets: widgetReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
const rootReducer = (state, action) => {
|
const rootReducer = (state, action) => {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ import LabelingHome from 'pages/labellingHome';
|
|||||||
import SetupInventory from 'pages/setupInventory';
|
import SetupInventory from 'pages/setupInventory';
|
||||||
import HomeIcon from 'assets/images/HomeIcon';
|
import HomeIcon from 'assets/images/HomeIcon';
|
||||||
import SetupIcon from 'assets/images/SetupIcon';
|
import SetupIcon from 'assets/images/SetupIcon';
|
||||||
import AddNewProduct from '../pages/addNewProduct';
|
import AddNewItem from '../pages/addNewProduct';
|
||||||
import CreateUserRole from 'pages/createUserRole';
|
import CreateUserRole from 'pages/createUserRole';
|
||||||
import WidgetLabel from 'pages/widgetLabel';
|
import WidgetLabel from 'pages/widgetLabel';
|
||||||
|
|
||||||
@@ -141,15 +141,22 @@ const protectedRoutes = [
|
|||||||
name: 'Inventory Definition',
|
name: 'Inventory Definition',
|
||||||
key: 'inventory-new',
|
key: 'inventory-new',
|
||||||
hide: true,
|
hide: true,
|
||||||
route: '/setup/inventory/inventory-new',
|
route: '/setup/inventory/new',
|
||||||
component: <InventoryScreen />
|
component: <InventoryScreen />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Add New Product',
|
name: 'Inventory Definition',
|
||||||
key: 'add-new-product',
|
key: 'inventory-update',
|
||||||
hide: true,
|
hide: true,
|
||||||
route: '/setup/inventory/product/add-new-product',
|
route: '/setup/inventory/update/:inventoryId',
|
||||||
component: <AddNewProduct />
|
component: <InventoryScreen />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Add New Item',
|
||||||
|
key: 'add-new-item',
|
||||||
|
hide: true,
|
||||||
|
route: '/setup/inventory/new-item/:widgetName/:inventoryId',
|
||||||
|
component: <AddNewItem />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Location Labeling',
|
name: 'Location Labeling',
|
||||||
|
|||||||
@@ -1,21 +1,85 @@
|
|||||||
import { AuthorizedAPI } from 'config';
|
import { AuthorizedAPI } from 'config';
|
||||||
import { takeLatest, call, put } from 'redux-saga/effects';
|
import { takeLatest, call, put, takeEvery } from 'redux-saga/effects';
|
||||||
import InventoryActions from 'redux/InventoryRedux';
|
import InventoryActions from 'redux/InventoryRedux';
|
||||||
import { InventoryTypes } from 'redux/InventoryRedux';
|
import { InventoryTypes } from 'redux/InventoryRedux';
|
||||||
import ApiServices from 'services/API/ApiServices';
|
import ApiServices from 'services/API/ApiServices';
|
||||||
|
|
||||||
export function* onRequestAddInventoryData({ payload }) {
|
export function* onRequestGetInventoryData({ payload }) {
|
||||||
const response = yield call(
|
const response = yield call(
|
||||||
ApiServices[payload?.method],
|
ApiServices[payload?.method],
|
||||||
AuthorizedAPI,
|
AuthorizedAPI,
|
||||||
payload?.slug,
|
payload?.slug,
|
||||||
payload?.data
|
payload?.data
|
||||||
);
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
InventoryActions.getInventorySuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
getInventoryDetail: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload.onFailedGetInventoryData(response.data.error);
|
||||||
|
yield put(
|
||||||
|
InventoryActions.getInventoryFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* onRequestGetInventoryTypesData({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
InventoryActions.getInventoryTypesSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
inventoryTypes: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload.onFailedGetInventoryData(response.data.error);
|
||||||
|
yield put(
|
||||||
|
InventoryActions.getInventoryTypesFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseDataToFormData = (data) => {
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append('name', data.name);
|
||||||
|
formData.append('widgetName', data.widgetName);
|
||||||
|
formData.append('icon_slug', 'testslug');
|
||||||
|
formData.append('policies[orderTracking]', data.policies.orderTracking);
|
||||||
|
formData.append('policies[alerting]', data.policies.alerting);
|
||||||
|
formData.append('policies[replenishment]', data.policies.replenishment);
|
||||||
|
formData.append('policies[preferredLocations]', data.policies.preferredLocations);
|
||||||
|
formData.append('policies[inventory_process]', data.policies.inventory_process);
|
||||||
|
data.image && formData.append('image', data.image);
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function* onRequestAddInventoryData({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
parseDataToFormData(payload?.data)
|
||||||
|
);
|
||||||
if (response?.status === 200) {
|
if (response?.status === 200) {
|
||||||
yield put(
|
yield put(
|
||||||
InventoryActions.addInventorySuccess({
|
InventoryActions.addInventorySuccess({
|
||||||
loader: payload?.loader,
|
loader: payload?.loader,
|
||||||
addInventoryDetail: response?.data?.data
|
newInventory: response?.data?.data?.inventoryData
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -28,4 +92,34 @@ export function* onRequestAddInventoryData({ payload }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default [takeLatest(InventoryTypes.ADD_INVENTORY_ACTION, onRequestAddInventoryData)];
|
|
||||||
|
export function* onRequestUpdateInventoryData({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
InventoryActions.updateInventorySuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
updateInventoryDetail: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload.onFailedUpdateInventoryData(response.data.error);
|
||||||
|
yield put(
|
||||||
|
InventoryActions.updateInventoryFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default [
|
||||||
|
takeLatest(InventoryTypes.GET_INVENTORY_ACTION, onRequestGetInventoryData),
|
||||||
|
takeLatest(InventoryTypes.ADD_INVENTORY_ACTION, onRequestAddInventoryData),
|
||||||
|
takeLatest(InventoryTypes.UPDATE_INVENTORY_ACTION, onRequestUpdateInventoryData),
|
||||||
|
takeEvery(InventoryTypes.GET_INVENTORY_TYPES_ACTION, onRequestGetInventoryTypesData)
|
||||||
|
];
|
||||||
|
|||||||
58
src/sagas/Widget.js
Normal file
58
src/sagas/Widget.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { AuthorizedAPI } from 'config';
|
||||||
|
import { call, put, takeEvery } from 'redux-saga/effects';
|
||||||
|
import ApiServices from 'services/API/ApiServices';
|
||||||
|
import WidgetActions, { WidgetTypes } from '../redux/WidgetRedux';
|
||||||
|
|
||||||
|
export function* onRequestWidget({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
WidgetActions.widgetSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
widgets: response?.data?.data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
yield put(
|
||||||
|
WidgetActions.widgetFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.message
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* onEditRequestWidget({ payload }) {
|
||||||
|
const response = yield call(
|
||||||
|
ApiServices[payload?.method],
|
||||||
|
AuthorizedAPI,
|
||||||
|
payload?.slug,
|
||||||
|
payload?.data
|
||||||
|
);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
yield put(
|
||||||
|
WidgetActions.editWidgetSuccess({
|
||||||
|
loader: payload?.loader,
|
||||||
|
widget: response?.data?.data,
|
||||||
|
type: payload?.type
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
yield put(
|
||||||
|
WidgetActions.widgetFailure({
|
||||||
|
loader: payload?.loader,
|
||||||
|
error: response?.message
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default [
|
||||||
|
takeEvery(WidgetTypes.WIDGET_REQUEST, onRequestWidget),
|
||||||
|
takeEvery(WidgetTypes.EDIT_WIDGET_REQUEST, onEditRequestWidget)
|
||||||
|
];
|
||||||
@@ -6,6 +6,7 @@ import ProductSaga from './Product';
|
|||||||
import InventorySaga from './Inventory';
|
import InventorySaga from './Inventory';
|
||||||
import RolesSaga from './Roles';
|
import RolesSaga from './Roles';
|
||||||
import WarehouseLocationsSaga from './WarehouseLocations';
|
import WarehouseLocationsSaga from './WarehouseLocations';
|
||||||
|
import WidgetSaga from './Widget';
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield all([...AuthSaga]);
|
yield all([...AuthSaga]);
|
||||||
@@ -15,4 +16,5 @@ export default function* rootSaga() {
|
|||||||
yield all([...InventorySaga]);
|
yield all([...InventorySaga]);
|
||||||
yield all([...RolesSaga]);
|
yield all([...RolesSaga]);
|
||||||
yield all([...WarehouseLocationsSaga]);
|
yield all([...WarehouseLocationsSaga]);
|
||||||
|
yield all([...WidgetSaga]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,33 +28,41 @@ const schema = {
|
|||||||
attributes: Yup.string('Enter other attributes')
|
attributes: Yup.string('Enter other attributes')
|
||||||
}),
|
}),
|
||||||
|
|
||||||
addNewProduct: Yup.object({
|
addNewItem: Yup.object({
|
||||||
warehousename: Yup.string('Enter warehouse name').required('warehouse name is required'),
|
commonName: Yup.string('Enter details').required(),
|
||||||
description: Yup.string('Enter Description').required('description is required'),
|
formalName: Yup.string('Enter details').required(),
|
||||||
manufacturer: Yup.string('Enter manufacturer').required('manufacturer is required'),
|
description: Yup.string('Enter details').required(),
|
||||||
type: Yup.string('Enter type').required('type is required'),
|
manufacturer: Yup.string('Enter details').required(),
|
||||||
unitofmaterial: Yup.string('Enter unitofmaterial').required('Unit of material is required'),
|
size: Yup.string('Enter details').required(),
|
||||||
packagecount: Yup.number('Enter packagecount').required('Package Count is required'),
|
color: Yup.string('Enter details').required(),
|
||||||
formalname: Yup.string('Enter formal name').required('Formal Name is required'),
|
type: Yup.string('Enter details').required(),
|
||||||
size: Yup.string('Enter Size').required('Size is required'),
|
unitOfMaterial: Yup.string('Enter details').required(),
|
||||||
color: Yup.string('Enter Color').required('Color is required'),
|
unitCost: Yup.number().test((val) => val >= 0),
|
||||||
unitcost: Yup.number('Enter UnitCost').required('Unit Cost is required'),
|
packageCount: Yup.number().test((val) => val >= 0),
|
||||||
countperpallet: Yup.number('Enter countperpallet').required('Count per pallet is required'),
|
countPerPallet: Yup.number().test((val) => val >= 0),
|
||||||
countperpalletpackage: Yup.number('Enter countperpalletpackage').required(
|
countPerPalletPackage: Yup.number().test((val) => val >= 0),
|
||||||
'count per pallet package is required'
|
primaryWidgetFamilyId: Yup.string('Enter details').required(),
|
||||||
),
|
secondaryWidgetFamilyId: Yup.string('Enter details'),
|
||||||
productfamilyassociation: Yup.string('Enter productfamilyassociation').required(
|
policiesMetadata: Yup.object({
|
||||||
'product Family Association is required'
|
underStockLevelCount: Yup.number().test((val) => val >= 0),
|
||||||
),
|
overStockLevelCount: Yup.number().test((val) => val >= 0),
|
||||||
under: Yup.number().required('required'),
|
alertStockLevelCount: Yup.number().test((val) => val >= 0),
|
||||||
over: Yup.number().required('required'),
|
reorderStockLevelCount: Yup.number().test((val) => val >= 0)
|
||||||
alert: Yup.number().required('required')
|
}),
|
||||||
|
images: Yup.array()
|
||||||
}),
|
}),
|
||||||
|
|
||||||
addInventory: Yup.object({
|
addInventory: Yup.object({
|
||||||
inventoryname: Yup.string('Enter Inventory name').required('Inventory name is required'),
|
name: Yup.string('Enter Widget Name').required('Widget Name is required'),
|
||||||
inventorytype: Yup.string('Enter inventory Type').required('inventory Type 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({
|
||||||
|
orderTracking: Yup.boolean(),
|
||||||
|
alerting: Yup.boolean(),
|
||||||
|
replenishment: Yup.boolean(),
|
||||||
|
preferredLocations: Yup.boolean(),
|
||||||
|
inventory_process: Yup.string()
|
||||||
|
}),
|
||||||
|
image: Yup.array()
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user