Merge branch 'develop' of https://github.com/kfnawaz/plaidware-wms-web into feature/wms-55_develop
This commit is contained in:
@@ -44,6 +44,7 @@ const buildBreadcrumbs = (route, light) => {
|
||||
fontWeight="regular"
|
||||
textTransform="capitalize"
|
||||
color={light ? 'white' : 'dark'}
|
||||
key={el}
|
||||
sx={{ lineHeight: 0 }}
|
||||
>
|
||||
{el.name}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import PropTypes from 'prop-types';
|
||||
import SearchBar from 'components/SearchBar';
|
||||
import MDButton from 'components/Button';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import Fade from '@mui/material/Fade';
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Table from '@mui/material/Table';
|
||||
import TableBody from '@mui/material/TableBody';
|
||||
@@ -15,10 +10,8 @@ import TableContainer from '@mui/material/TableContainer';
|
||||
import TableHead from '@mui/material/TableHead';
|
||||
import TableRow from '@mui/material/TableRow';
|
||||
import Paper from '@mui/material/Paper';
|
||||
// import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||
// import IconButton from '@mui/material/IconButton';
|
||||
// import Collapse from '@mui/material/Collapse';
|
||||
import TablePagination from 'components/TablePagination';
|
||||
import { Dialog, DialogActions, MenuItem, Select } from '@mui/material';
|
||||
|
||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||
[`&.${tableCellClasses.head}`]: {
|
||||
@@ -47,16 +40,16 @@ const StyledTableRow = styled(TableRow)(({ theme }) => ({
|
||||
|
||||
Row.propTypes = {
|
||||
rowData: PropTypes.array,
|
||||
tHeads: PropTypes.array
|
||||
tHeads: PropTypes.array,
|
||||
editHandler: PropTypes.any
|
||||
};
|
||||
|
||||
function Row({ tHeads, rowData }) {
|
||||
function Row({ tHeads, rowData, editHandler }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<StyledTableRow sx={{ '&odd > *': { borderBottom: 'unset' } }}>
|
||||
<StyledTableCell sx={{ width: '10%', display: 'flex', alignItems: 'center' }}>
|
||||
<MDButton
|
||||
disabled
|
||||
size="small"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
@@ -69,6 +62,9 @@ function Row({ tHeads, rowData }) {
|
||||
fontWeight: '500',
|
||||
padding: '0'
|
||||
}}
|
||||
onClick={() => {
|
||||
editHandler(rowData._id);
|
||||
}}
|
||||
>
|
||||
EDIT
|
||||
</MDButton>
|
||||
@@ -82,15 +78,24 @@ function Row({ tHeads, rowData }) {
|
||||
);
|
||||
}
|
||||
|
||||
function EnhancedTable({ data, tHeads }) {
|
||||
// const [anchorEl, setAnchorEl] = React.useState(false);
|
||||
// const open = Boolean(anchorEl);
|
||||
// const handleClick = (event) => {
|
||||
// setAnchorEl(event.currentTarget);
|
||||
// };
|
||||
// const handleClose = () => {
|
||||
// setAnchorEl(null);
|
||||
// };
|
||||
function EnhancedTable({
|
||||
count,
|
||||
page,
|
||||
setPage,
|
||||
perPage,
|
||||
setPerPage,
|
||||
data,
|
||||
tHeads,
|
||||
editHandler,
|
||||
filtersControl,
|
||||
resetFilters
|
||||
}) {
|
||||
const [filtersOpen, setFiltersOpen] = React.useState(false);
|
||||
|
||||
const handleFiltersClose = () => {
|
||||
setFiltersOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
@@ -109,9 +114,7 @@ function EnhancedTable({ data, tHeads }) {
|
||||
padding: '16px'
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box>{/* <SearchBar /> */}</Box>
|
||||
<Box sx={{ display: 'flex', columnGap: '15px' }}>
|
||||
<MDButton
|
||||
size="small"
|
||||
@@ -123,10 +126,31 @@ function EnhancedTable({ data, tHeads }) {
|
||||
minHeight: '44px',
|
||||
fontWeight: '500'
|
||||
}}
|
||||
onClick={() => {
|
||||
setFiltersOpen(true);
|
||||
}}
|
||||
>
|
||||
Sorting
|
||||
Filter
|
||||
</MDButton>
|
||||
<MDButton
|
||||
{filtersControl ? (
|
||||
<Dialog open={filtersOpen} onClose={handleFiltersClose}>
|
||||
{filtersControl}
|
||||
<DialogActions>
|
||||
<MDButton onClick={resetFilters}>Reset Filters</MDButton>
|
||||
<MDButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setFiltersOpen(false);
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</MDButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
) : null}
|
||||
{/* <MDButton
|
||||
id="fade-button"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
@@ -144,8 +168,8 @@ function EnhancedTable({ data, tHeads }) {
|
||||
onClick={() => {}}
|
||||
>
|
||||
Dashboard
|
||||
</MDButton>
|
||||
<Menu
|
||||
</MDButton> */}
|
||||
{/* <Menu
|
||||
id="fade-menu"
|
||||
MenuListProps={{
|
||||
'aria-labelledby': 'fade-button'
|
||||
@@ -158,7 +182,7 @@ function EnhancedTable({ data, tHeads }) {
|
||||
<MenuItem>Profile</MenuItem>
|
||||
<MenuItem>My account</MenuItem>
|
||||
<MenuItem>Logout</MenuItem>
|
||||
</Menu>
|
||||
</Menu> */}
|
||||
</Box>
|
||||
</Box>
|
||||
{/* Table-row- */}
|
||||
@@ -174,7 +198,14 @@ function EnhancedTable({ data, tHeads }) {
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{data &&
|
||||
data.map((rowData) => <Row key={rowData._id} rowData={rowData} tHeads={tHeads} />)}
|
||||
data.map((rowData) => (
|
||||
<Row
|
||||
key={rowData._id}
|
||||
editHandler={editHandler}
|
||||
rowData={rowData}
|
||||
tHeads={tHeads}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
@@ -265,10 +296,29 @@ function EnhancedTable({ data, tHeads }) {
|
||||
</Box>
|
||||
</Box> */}
|
||||
{/*---- pagination- */}
|
||||
<Box>
|
||||
<TablePagination />
|
||||
<Box sx={{ fontSize: '14px', color: '#000' }}>
|
||||
Per page:{' '}
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={perPage}
|
||||
label="Age"
|
||||
onChange={(e) => {
|
||||
setPerPage(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={5}>5</MenuItem>
|
||||
<MenuItem value={10}>10</MenuItem>
|
||||
<MenuItem value={20}>20</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
<Box>
|
||||
<TablePagination count={Math.ceil(count / perPage)} page={page} setPage={setPage} />
|
||||
</Box>
|
||||
<Box sx={{ fontSize: '14px', color: '#000' }}>
|
||||
[{(page - 1) * perPage + 1} to {perPage * page > count ? count : perPage * page} of{' '}
|
||||
{count}]
|
||||
</Box>
|
||||
<Box sx={{ fontSize: '14px', color: '#000' }}>[1 to 10 of 92]</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
@@ -276,8 +326,16 @@ function EnhancedTable({ data, tHeads }) {
|
||||
}
|
||||
|
||||
EnhancedTable.propTypes = {
|
||||
count: PropTypes.number,
|
||||
page: PropTypes.number,
|
||||
setPage: PropTypes.any,
|
||||
perPage: PropTypes.number,
|
||||
setPerPage: PropTypes.any,
|
||||
data: PropTypes.array,
|
||||
tHeads: PropTypes.array
|
||||
tHeads: PropTypes.array,
|
||||
editHandler: PropTypes.any,
|
||||
filtersControl: PropTypes.any,
|
||||
resetFilters: PropTypes.any
|
||||
};
|
||||
|
||||
export default EnhancedTable;
|
||||
|
||||
@@ -39,6 +39,7 @@ function ImageUpload({ heading, accept, multiple, images, setImages, type, pageI
|
||||
const addNewImageToImages = (image) => {
|
||||
setImages([...images, image]);
|
||||
};
|
||||
|
||||
const addImage = (e) => {
|
||||
addNewImage(type, pageId, e.target.files[0], addNewImageToImages);
|
||||
setImages([
|
||||
@@ -46,8 +47,9 @@ function ImageUpload({ heading, accept, multiple, images, setImages, type, pageI
|
||||
{ src: URL.createObjectURL(e.target.files[0]), file: e.target.files[0] }
|
||||
]);
|
||||
};
|
||||
|
||||
const removeImage = (index) => {
|
||||
deleteImage(type, pageId, images._id);
|
||||
multiple && deleteImage(type, pageId, images._id);
|
||||
setImages(images.filter((_val, idx) => idx !== index));
|
||||
};
|
||||
|
||||
|
||||
128
src/components/ImageUploadMultiple/index.js
Normal file
128
src/components/ImageUploadMultiple/index.js
Normal file
@@ -0,0 +1,128 @@
|
||||
/* eslint-disable no-case-declarations */
|
||||
import MDBox from 'components/MDBox';
|
||||
import PropTypes from 'prop-types';
|
||||
import UploadIcon from 'assets/images/UploadIcon';
|
||||
import MDTypography from 'components/MDTypography';
|
||||
import pxToRem from 'assets/theme-dark/functions/pxToRem';
|
||||
import { Button } from '@mui/material';
|
||||
import Close from 'assets/images/Close';
|
||||
|
||||
function ImageUpload({ heading, accept, multiple, images, setImages }) {
|
||||
const addImage = (e) => {
|
||||
setImages([
|
||||
...images,
|
||||
{ src: URL.createObjectURL(e.target.files[0]), file: e.target.files[0] }
|
||||
]);
|
||||
};
|
||||
|
||||
const removeImage = (index) => {
|
||||
setImages(images.filter((_val, idx) => idx !== index));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<MDBox
|
||||
sx={{
|
||||
border: '1px solid #c4c4c4',
|
||||
borderRadius: pxToRem(8),
|
||||
padding: pxToRem(16)
|
||||
}}
|
||||
>
|
||||
<MDBox
|
||||
sx={{
|
||||
border: '1px dashed #C4C4C4',
|
||||
borderRadius: pxToRem(6),
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
textAlign: 'center',
|
||||
minHeight: pxToRem(200),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: '16px'
|
||||
}}
|
||||
>
|
||||
<MDBox
|
||||
component="input"
|
||||
name="file"
|
||||
disabled={!multiple && images.length}
|
||||
accept={accept}
|
||||
type="file"
|
||||
sx={{
|
||||
width: '100%',
|
||||
opacity: '0',
|
||||
cursor: 'pointer',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
right: '0',
|
||||
bottom: '0'
|
||||
}}
|
||||
onChange={addImage}
|
||||
/>
|
||||
<MDBox component="span">
|
||||
{!multiple && images.length ? null : <UploadIcon />}
|
||||
<MDTypography
|
||||
component="span"
|
||||
sx={{ color: '#000', letterSpacing: '0.01em', display: 'block' }}
|
||||
>
|
||||
{!multiple && images.length ? 'Cannot add more images' : heading}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
{/* -----------img-preview----------- */}
|
||||
<MDBox sx={{ marginBottom: '-10px' }}>
|
||||
{images &&
|
||||
images.map((item, idx) => {
|
||||
return (
|
||||
<MDBox
|
||||
key={idx}
|
||||
component="span"
|
||||
sx={{
|
||||
width: '80px',
|
||||
height: '63px',
|
||||
marginRight: '16px',
|
||||
display: 'inline-block',
|
||||
borderRadius: '4px',
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
<img src={item.src} alt="placeholder" width="100%" />
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: '#fff !important',
|
||||
boxShadow: '0px 1px 1px rgb(0 0 0 / 25%)',
|
||||
padding: '0',
|
||||
minWidth: '20px',
|
||||
minHeight: '20px',
|
||||
borderRadius: '100%',
|
||||
position: 'absolute',
|
||||
right: '4px',
|
||||
top: '4px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'red !important'
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
removeImage(idx);
|
||||
}}
|
||||
>
|
||||
<Close />
|
||||
</Button>
|
||||
</MDBox>
|
||||
);
|
||||
})}
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ImageUpload;
|
||||
ImageUpload.propTypes = {
|
||||
images: PropTypes.array,
|
||||
heading: PropTypes.string,
|
||||
multiple: PropTypes.bool,
|
||||
accept: PropTypes.string,
|
||||
setImages: PropTypes.func
|
||||
};
|
||||
119
src/components/ImageUploadSingle/index.js
Normal file
119
src/components/ImageUploadSingle/index.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/* eslint-disable no-case-declarations */
|
||||
import MDBox from 'components/MDBox';
|
||||
import PropTypes from 'prop-types';
|
||||
import UploadIcon from 'assets/images/UploadIcon';
|
||||
import MDTypography from 'components/MDTypography';
|
||||
import pxToRem from 'assets/theme-dark/functions/pxToRem';
|
||||
import { Button } from '@mui/material';
|
||||
import Close from 'assets/images/Close';
|
||||
|
||||
function ImageUploadSingle({ heading, accept, multiple, images, setImages }) {
|
||||
return (
|
||||
<>
|
||||
<MDBox
|
||||
sx={{
|
||||
border: '1px solid #c4c4c4',
|
||||
borderRadius: pxToRem(8),
|
||||
padding: pxToRem(16)
|
||||
}}
|
||||
>
|
||||
{!images.length ? (
|
||||
<MDBox
|
||||
sx={{
|
||||
border: '1px dashed #C4C4C4',
|
||||
borderRadius: pxToRem(6),
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
textAlign: 'center',
|
||||
minHeight: pxToRem(200),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: '16px'
|
||||
}}
|
||||
>
|
||||
<MDBox
|
||||
component="input"
|
||||
name="file"
|
||||
disabled={!multiple && images.length}
|
||||
accept={accept}
|
||||
type="file"
|
||||
sx={{
|
||||
width: '100%',
|
||||
opacity: '0',
|
||||
cursor: 'pointer',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
right: '0',
|
||||
bottom: '0'
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setImages([
|
||||
{ src: URL.createObjectURL(e.target.files[0]), file: e.target.files[0] }
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
<MDBox component="span">
|
||||
{!multiple && images.length ? null : <UploadIcon />}
|
||||
<MDTypography
|
||||
component="span"
|
||||
sx={{ color: '#000', letterSpacing: '0.01em', display: 'block' }}
|
||||
>
|
||||
{!multiple && images.length ? 'Cannot add more images' : heading}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
</MDBox>
|
||||
) : (
|
||||
<MDBox
|
||||
sx={{
|
||||
border: '1px dashed #C4C4C4',
|
||||
borderRadius: pxToRem(6),
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
textAlign: 'center',
|
||||
minHeight: pxToRem(200),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: '16px'
|
||||
}}
|
||||
>
|
||||
<img src={images[0].src} alt="" width="100%" height="100%" />
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: '#fff !important',
|
||||
boxShadow: '0px 1px 1px rgb(0 0 0 / 25%)',
|
||||
padding: '0',
|
||||
minWidth: '20px',
|
||||
minHeight: '20px',
|
||||
borderRadius: '100%',
|
||||
position: 'absolute',
|
||||
right: '4px',
|
||||
top: '4px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'red !important'
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
setImages([]);
|
||||
}}
|
||||
>
|
||||
<Close />
|
||||
</Button>
|
||||
</MDBox>
|
||||
)}
|
||||
</MDBox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
ImageUploadSingle.propTypes = {
|
||||
images: PropTypes.array,
|
||||
heading: PropTypes.string,
|
||||
multiple: PropTypes.bool,
|
||||
accept: PropTypes.string,
|
||||
setImages: PropTypes.func
|
||||
};
|
||||
|
||||
export default ImageUploadSingle;
|
||||
@@ -1,33 +1,43 @@
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { PaginationItem } from '@mui/material';
|
||||
import NextIcon from 'assets/images/NextIcon';
|
||||
import PreviousIcon from 'assets/images/PreviousIcon';
|
||||
|
||||
function TablePagination() {
|
||||
function TablePagination({ count, page, setPage }) {
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
<Pagination
|
||||
count={10}
|
||||
shape="rounded"
|
||||
color="primary"
|
||||
size="large"
|
||||
<Pagination
|
||||
count={count}
|
||||
page={page}
|
||||
shape="rounded"
|
||||
color="primary"
|
||||
size="large"
|
||||
renderItem={(item) => (
|
||||
<PaginationItem
|
||||
components={{ previous: PreviousIcon, next: NextIcon }}
|
||||
{...item}
|
||||
sx={{
|
||||
minWidth:'20px',
|
||||
fontWeight:'500',
|
||||
minWidth: '20px',
|
||||
fontWeight: '500',
|
||||
height: '30px'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
onChange={(event, value) => {
|
||||
setPage(value);
|
||||
}}
|
||||
/>
|
||||
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
TablePagination.propTypes = {
|
||||
page: PropTypes.number,
|
||||
count: PropTypes.number,
|
||||
setPage: PropTypes.any
|
||||
};
|
||||
|
||||
export default TablePagination;
|
||||
|
||||
@@ -67,13 +67,30 @@ export default function TileBasic({ tiles }) {
|
||||
<Grid container spacing={2}>
|
||||
{tiles &&
|
||||
tiles.map((item) => (
|
||||
<>
|
||||
<Grid item xs={12} sm={6} md={tiles.length > 4 ? 4 : 6}>
|
||||
{item.disabled ? (
|
||||
<Grid item key={item.name} xs={12} sm={6} md={tiles.length > 4 ? 4 : 6}>
|
||||
{item.disabled ? (
|
||||
<MDBox
|
||||
key={item.name + item.path}
|
||||
data={{ name: item.name, path: item.path }}
|
||||
className={classes.disabledTileContent}
|
||||
sx={{
|
||||
height: 230,
|
||||
backgroundColor: ({ palette: { white } }) => white.main,
|
||||
padding: '32px 40px'
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
{item.name}
|
||||
</MDBox>
|
||||
) : (
|
||||
<Link
|
||||
to={item.path}
|
||||
state={{ name: item.name, address: item.address, id: item._id }}
|
||||
>
|
||||
<MDBox
|
||||
key={item.name + item.path}
|
||||
data={{ name: item.name, path: item.path }}
|
||||
className={classes.disabledTileContent}
|
||||
className={classes.tileContent}
|
||||
sx={{
|
||||
height: 230,
|
||||
backgroundColor: ({ palette: { white } }) => white.main,
|
||||
@@ -83,28 +100,9 @@ export default function TileBasic({ tiles }) {
|
||||
{item.icon}
|
||||
{item.name}
|
||||
</MDBox>
|
||||
) : (
|
||||
<Link
|
||||
to={item.path}
|
||||
state={{ name: item.name, address: item.address, id: item._id }}
|
||||
>
|
||||
<MDBox
|
||||
key={item.name + item.path}
|
||||
data={{ name: item.name, path: item.path }}
|
||||
className={classes.tileContent}
|
||||
sx={{
|
||||
height: 230,
|
||||
backgroundColor: ({ palette: { white } }) => white.main,
|
||||
padding: '32px 40px'
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
{item.name}
|
||||
</MDBox>
|
||||
</Link>
|
||||
)}
|
||||
</Grid>
|
||||
</>
|
||||
</Link>
|
||||
)}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</MDBox>
|
||||
|
||||
@@ -16,7 +16,8 @@ export default {
|
||||
ADD_NEW_BAY: '/bay',
|
||||
ADD_NEW_LEVEL: '/level',
|
||||
ADD_NEW_SUBLEVEL: '/sublevel',
|
||||
ADD_PRODUCT: '/item/',
|
||||
ADD_ITEM: '/item/',
|
||||
EDIT_ITEM: '/item/',
|
||||
ADD_INVENTORY: '/inventory',
|
||||
GET_INVENTORY: '/inventory/all?page=0&perPage=50',
|
||||
GET_INVENTORY_TYPES: '/inventory/types',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable complexity */
|
||||
import * as React from 'react';
|
||||
import { Grid, TextField, Box, FormHelperText, TextareaAutosize } from '@mui/material';
|
||||
@@ -7,7 +8,7 @@ import DashboardLayout from 'layouts/DashboardLayout';
|
||||
import Select from '@mui/material/Select';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import ImageUpload from 'components/ImageUpload';
|
||||
import ImageUploadMultiple from 'components/ImageUploadMultiple';
|
||||
import MDButton from 'components/Button';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
@@ -16,13 +17,15 @@ import { useFormik } from 'formik';
|
||||
import schema from 'services/ValidationServices';
|
||||
import MDInput from 'components/MDInput';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import ProductActions from 'redux/ProductsRedux';
|
||||
import { API } from 'constant';
|
||||
import LOGGER from 'services/Logger';
|
||||
import Breadcrumbs from 'components/Breadcrumbs';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||
import WidgetActions from 'redux/WidgetRedux';
|
||||
import ItemActions from 'redux/ItemRedux';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ItemSelectors } from 'redux/ItemRedux';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
labelSize: {
|
||||
@@ -48,11 +51,68 @@ const useStyles = makeStyles({
|
||||
|
||||
function AddNewItem() {
|
||||
const classes = useStyles();
|
||||
const { widgetName, inventoryId } = useParams();
|
||||
const { widgetName, inventoryId, itemId } = useParams();
|
||||
const getInitialFormValues = (data) => {
|
||||
return data && data._id === itemId
|
||||
? {
|
||||
commonName: data.commonName,
|
||||
formalName: data.formalName,
|
||||
description: data.description,
|
||||
manufacturer: data.manufacturer,
|
||||
size: data.size,
|
||||
color: data.color,
|
||||
type: data.type,
|
||||
unitOfMaterial: data.unitOfMaterial,
|
||||
unitCost: data.unitCost,
|
||||
packageCount: data.packageCount,
|
||||
countPerPallet: data.countPerPallet,
|
||||
countPerPalletPackage: data.countPerPalletPackage,
|
||||
primaryWidgetFamilyId: data.widgetFamily.parent
|
||||
? data.widgetFamily.parent
|
||||
: data.widgetFamily._id,
|
||||
secondaryWidgetFamilyId: data.widgetFamily.parent ? data.widgetFamily._id : '',
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: data.policiesMetadata.underStockLevelCount,
|
||||
overStockLevelCount: data.policiesMetadata.overStockLevelCount,
|
||||
alertStockLevelCount: data.policiesMetadata.alertStockLevelCount,
|
||||
reorderStockLevelCount: data.policiesMetadata.reorderStockLevelCount
|
||||
},
|
||||
images: data.images.map((img) => ({ ...img, src: img.url }))
|
||||
}
|
||||
: {
|
||||
commonName: '',
|
||||
formalName: '',
|
||||
description: '',
|
||||
manufacturer: '',
|
||||
size: '',
|
||||
color: '',
|
||||
type: '',
|
||||
unitOfMaterial: '',
|
||||
unitCost: 0,
|
||||
packageCount: 0,
|
||||
countPerPallet: 0,
|
||||
countPerPalletPackage: 0,
|
||||
primaryWidgetFamilyId: '',
|
||||
secondaryWidgetFamilyId: '',
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: 0,
|
||||
overStockLevelCount: 0,
|
||||
alertStockLevelCount: 0,
|
||||
reorderStockLevelCount: 0
|
||||
},
|
||||
images: []
|
||||
};
|
||||
};
|
||||
const itemData = getInitialFormValues(useSelector(ItemSelectors.getFormItem(itemId)));
|
||||
const dispatch = useDispatch();
|
||||
const [Manufacturer, setManufacturer] = React.useState('');
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const navigateTo = (path) => {
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(
|
||||
WidgetActions.widgetRequest({
|
||||
@@ -61,74 +121,99 @@ function AddNewItem() {
|
||||
method: 'get'
|
||||
})
|
||||
);
|
||||
|
||||
itemId &&
|
||||
dispatch(
|
||||
ItemActions.oneItemRequest({
|
||||
loader: 'location-request',
|
||||
slug: API.EDIT_ITEM,
|
||||
method: 'get',
|
||||
widgetName,
|
||||
inventoryId,
|
||||
itemId
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
const [pFam, setPFam] = React.useState(null);
|
||||
const primaryFamily = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||
const secondaryFamily = useSelector(WidgetSelectors.getWidgetsByParentId(pFam));
|
||||
LOGGER.log({ primaryFamily, secondaryFamily });
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
commonName: '',
|
||||
formalName: '',
|
||||
description: '',
|
||||
manufacturer: '',
|
||||
size: '',
|
||||
color: '',
|
||||
type: '',
|
||||
unitOfMaterial: '',
|
||||
unitCost: 0,
|
||||
packageCount: 0,
|
||||
countPerPallet: 0,
|
||||
countPerPalletPackage: 0,
|
||||
primaryWidgetFamilyId: '',
|
||||
secondaryWidgetFamilyId: '',
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: 0,
|
||||
overStockLevelCount: 0,
|
||||
alertStockLevelCount: 0,
|
||||
reorderStockLevelCount: 0
|
||||
},
|
||||
images: []
|
||||
},
|
||||
enableReinitialize: true,
|
||||
initialValues: itemData,
|
||||
validationSchema: schema.addNewItem,
|
||||
onSubmit: (values, onSubmitProps) => {
|
||||
onSubmit: (values) => {
|
||||
LOGGER.log('values', values);
|
||||
dispatch(
|
||||
ProductActions.addProductAction({
|
||||
loader: 'loading-request',
|
||||
slug: API.ADD_PRODUCT,
|
||||
method: 'post',
|
||||
data: {
|
||||
commonName: values.commonName,
|
||||
formalName: values.formalName,
|
||||
description: values.description,
|
||||
manufacturer: values.manufacturer,
|
||||
size: values.size,
|
||||
color: values.color,
|
||||
type: values.type,
|
||||
unitOfMaterial: values.unitOfMaterial,
|
||||
unitCost: values.unitCost,
|
||||
packageCount: values.packageCount,
|
||||
countPerPallet: values.countPerPallet,
|
||||
countPerPalletPackage: values.countPerPalletPackage,
|
||||
customAttributes: [],
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: values.policiesMetadata.underStockLevelCount,
|
||||
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();
|
||||
itemId
|
||||
? dispatch(
|
||||
ItemActions.editItemRequest({
|
||||
loader: 'loading-request',
|
||||
slug: `${API.EDIT_ITEM}${itemId}`,
|
||||
method: 'patch',
|
||||
navigateTo,
|
||||
data: {
|
||||
commonName: values.commonName,
|
||||
formalName: values.formalName,
|
||||
description: values.description,
|
||||
manufacturer: values.manufacturer,
|
||||
size: values.size,
|
||||
color: values.color,
|
||||
type: values.type,
|
||||
unitOfMaterial: values.unitOfMaterial,
|
||||
unitCost: values.unitCost,
|
||||
packageCount: values.packageCount,
|
||||
countPerPallet: values.countPerPallet,
|
||||
countPerPalletPackage: values.countPerPalletPackage,
|
||||
customAttributes: [], // TBD
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: values.policiesMetadata.underStockLevelCount,
|
||||
overStockLevelCount: values.policiesMetadata.overStockLevelCount,
|
||||
alertStockLevelCount: values.policiesMetadata.alertStockLevelCount,
|
||||
reorderStockLevelCount: values.policiesMetadata.reorderStockLevelCount
|
||||
},
|
||||
widgetFamilyId:
|
||||
values.secondaryWidgetFamilyId === ''
|
||||
? values.primaryWidgetFamilyId
|
||||
: values.secondaryWidgetFamilyId,
|
||||
images: values.images
|
||||
}
|
||||
})
|
||||
)
|
||||
: dispatch(
|
||||
ItemActions.addItemRequest({
|
||||
loader: 'loading-request',
|
||||
slug: API.ADD_ITEM,
|
||||
method: 'post',
|
||||
navigateTo,
|
||||
data: {
|
||||
commonName: values.commonName,
|
||||
formalName: values.formalName,
|
||||
description: values.description,
|
||||
manufacturer: values.manufacturer,
|
||||
size: values.size,
|
||||
color: values.color,
|
||||
type: values.type,
|
||||
unitOfMaterial: values.unitOfMaterial,
|
||||
unitCost: values.unitCost,
|
||||
packageCount: values.packageCount,
|
||||
countPerPallet: values.countPerPallet,
|
||||
countPerPalletPackage: values.countPerPalletPackage,
|
||||
customAttributes: [], // TBD
|
||||
policiesMetadata: {
|
||||
underStockLevelCount: values.policiesMetadata.underStockLevelCount,
|
||||
overStockLevelCount: values.policiesMetadata.overStockLevelCount,
|
||||
alertStockLevelCount: values.policiesMetadata.alertStockLevelCount,
|
||||
reorderStockLevelCount: values.policiesMetadata.reorderStockLevelCount
|
||||
},
|
||||
widgetFamilyId:
|
||||
values.secondaryWidgetFamilyId === ''
|
||||
? values.primaryWidgetFamilyId
|
||||
: values.secondaryWidgetFamilyId,
|
||||
images: values.images
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -409,14 +494,27 @@ function AddNewItem() {
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box>
|
||||
<ImageUpload
|
||||
heading="Upload Product Image"
|
||||
accept="image/*"
|
||||
images={formik.values.images}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('images', images);
|
||||
}}
|
||||
/>
|
||||
{itemId ? (
|
||||
<ImageUploadMultiple
|
||||
multiple
|
||||
heading="Upload Product Image"
|
||||
accept="image/*"
|
||||
images={formik.values.images}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('images', images);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ImageUploadMultiple
|
||||
multiple
|
||||
heading="Upload Product Image"
|
||||
accept="image/*"
|
||||
images={formik.values.images}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('images', images);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
@@ -16,13 +16,12 @@ import {
|
||||
} from '@mui/material';
|
||||
import DashboardNavbar from 'components/DashboardNavbar';
|
||||
import DashboardLayout from 'layouts/DashboardLayout';
|
||||
import ImageUpload from 'components/ImageUpload';
|
||||
import ImageUploadSingle from 'components/ImageUploadSingle';
|
||||
import MDButton from 'components/Button';
|
||||
import { useFormik } from 'formik';
|
||||
import schema from 'services/ValidationServices';
|
||||
// import schema from 'services/ValidationServices';
|
||||
import MDInput from 'components/MDInput';
|
||||
import WarehouseActions from 'redux/WarehouseRedux';
|
||||
import SnackBar from 'components/SnackBar';
|
||||
import { getChildLocationType } from 'utils/nestedTableTools';
|
||||
import { getPropertiesOfLocationType } from 'utils/nestedTableTools';
|
||||
import { getInitialvaluesFromParentData } from 'utils/nestedTableTools';
|
||||
@@ -36,6 +35,8 @@ import { API } from 'constant';
|
||||
import NestedDataTable from 'components/NestedTable';
|
||||
import Breadcrumbs from 'components/Breadcrumbs';
|
||||
import { WarehouseSelectors } from 'redux/WarehouseRedux';
|
||||
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||
import InventoryActions from 'redux/InventoryRedux';
|
||||
|
||||
const bottomButtonStyling = {
|
||||
width: '100%',
|
||||
@@ -314,13 +315,22 @@ const WarehouseNestedDetails = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const inventoryTypes = ['Perishable', 'Material', 'Product', 'Inventory', 'Fleet'];
|
||||
|
||||
function EditWarehouseDetails() {
|
||||
const { warehouseId } = useParams();
|
||||
const warehouseData = useSelector(WarehouseSelectors.getWarehouseDetailById(warehouseId));
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const inventoryTypes = useSelector(InventorySelectors.getInventoryDetail);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(
|
||||
InventoryActions.getInventoryAction({
|
||||
loader: 'loading-request',
|
||||
slug: API.GET_INVENTORY,
|
||||
method: 'get'
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
const MenuProps = {
|
||||
@@ -336,13 +346,13 @@ function EditWarehouseDetails() {
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
warehousename: warehouseData.name,
|
||||
address: warehouseData.address,
|
||||
inventorytype: [],
|
||||
attributes: '',
|
||||
images: warehouseData.images
|
||||
address: warehouseData.address || '',
|
||||
preferredInventories: warehouseData.preferredInventories || [],
|
||||
specs: warehouseData.specs || '',
|
||||
image: warehouseData.image_url ? [{ src: warehouseData.image_url }] : []
|
||||
},
|
||||
validationSchema: schema.warehouseForm,
|
||||
onSubmit: (values, onSubmitProps) => {
|
||||
// validationSchema: schema.warehouseForm,
|
||||
onSubmit: (values) => {
|
||||
dispatch(
|
||||
WarehouseActions.editWarehouseAction({
|
||||
loader: 'loading-request',
|
||||
@@ -351,21 +361,14 @@ function EditWarehouseDetails() {
|
||||
data: {
|
||||
name: values.warehousename,
|
||||
address: values.address,
|
||||
specs: '',
|
||||
company_id: ''
|
||||
specs: values.specs,
|
||||
preferredInventories: values.preferredInventories,
|
||||
image: values.image
|
||||
}
|
||||
})
|
||||
);
|
||||
onSubmitProps.resetForm();
|
||||
setOpen(true);
|
||||
}
|
||||
});
|
||||
const handleClose = (event, reason) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -456,40 +459,45 @@ function EditWarehouseDetails() {
|
||||
<Select
|
||||
multiple
|
||||
select
|
||||
disabled
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
name="inventorytype"
|
||||
name="preferredInventories"
|
||||
input={<OutlinedInput />}
|
||||
value={formik.values.inventorytype}
|
||||
error={formik.touched.inventorytype && Boolean(formik.errors.inventorytype)}
|
||||
helperText={formik.touched.inventorytype && formik.errors.inventorytype}
|
||||
value={formik.values.preferredInventories}
|
||||
error={
|
||||
formik.touched.preferredInventories &&
|
||||
Boolean(formik.errors.preferredInventories)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.preferredInventories && formik.errors.preferredInventories
|
||||
}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||
{selected.map((value) => (
|
||||
<Chip key={value} label={value} />
|
||||
<Chip
|
||||
key={value}
|
||||
label={inventoryTypes.find((x) => x._id === value)?.name || 'unknown'}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
onChange={(event) => {
|
||||
const {
|
||||
target: { value }
|
||||
} = event;
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
formik.setFieldValue(
|
||||
'inventorytype',
|
||||
'preferredInventories',
|
||||
// On autofill we get a stringified value.
|
||||
typeof value === 'string' ? value.split(',') : value
|
||||
);
|
||||
}}
|
||||
>
|
||||
<MenuItem key={''} value={''}>
|
||||
None Selected
|
||||
</MenuItem>
|
||||
{inventoryTypes.map((name) => (
|
||||
<MenuItem key={name} value={name}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
{inventoryTypes &&
|
||||
inventoryTypes.map((inventory) => (
|
||||
<MenuItem key={inventory._id} value={inventory._id}>
|
||||
{inventory.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</Box>
|
||||
<Box component="div" sx={{ marginBottom: '15px' }}>
|
||||
@@ -508,23 +516,22 @@ function EditWarehouseDetails() {
|
||||
fullWidth
|
||||
type="text"
|
||||
variant="outlined"
|
||||
name="attributes"
|
||||
value={formik.values.attributes}
|
||||
error={formik.touched.attributes && Boolean(formik.errors.attributes)}
|
||||
helperText={formik.touched.attributes && formik.errors.attributes}
|
||||
name="specs"
|
||||
value={formik.values.specs}
|
||||
error={formik.touched.specs && Boolean(formik.errors.specs)}
|
||||
helperText={formik.touched.specs && formik.errors.specs}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={6}>
|
||||
<Box sx={{ marginTop: '30px' }}>
|
||||
<ImageUpload
|
||||
multiple
|
||||
<ImageUploadSingle
|
||||
heading="Upload Warehouse Image"
|
||||
accept="image/*"
|
||||
images={formik.values.images}
|
||||
images={formik.values.image}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('images', images);
|
||||
formik.setFieldValue('image', images);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -558,7 +565,6 @@ function EditWarehouseDetails() {
|
||||
<WarehouseNestedDetails />
|
||||
</Box>
|
||||
</DashboardLayout>
|
||||
<SnackBar open={open} message="warehouse edit successful" handleClose={handleClose} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import DashboardNavbar from 'components/DashboardNavbar';
|
||||
import DashboardLayout from 'layouts/DashboardLayout';
|
||||
import { Box, Grid, MenuItem, Select } from '@mui/material';
|
||||
import MDInput from 'components/MDInput';
|
||||
import ImageUpload from 'components/ImageUpload';
|
||||
import Switch from 'components/Switch';
|
||||
import MDTypography from 'components/MDTypography';
|
||||
import MDBox from 'components/MDBox';
|
||||
@@ -76,6 +75,10 @@ function InventoryScreen() {
|
||||
const navigate = useNavigate();
|
||||
const { inventoryId } = useParams();
|
||||
|
||||
const navigateTo = () => {
|
||||
navigate('/setup/inventory');
|
||||
};
|
||||
|
||||
const currentInventoryData = useSelector(InventorySelectors.getInventoryDetailById(inventoryId));
|
||||
LOGGER.log({ currentInventoryData });
|
||||
// const [inventoryAllData, setInventoryAllData] = useState([]);
|
||||
@@ -102,8 +105,7 @@ function InventoryScreen() {
|
||||
replenishment: currentInventoryData.policies.replenishment,
|
||||
preferredLocations: false, // TODO: change later when implemented on BE
|
||||
inventory_process: currentInventoryData.policies.inventory_process
|
||||
},
|
||||
image: [{ src: currentInventoryData.image_url }]
|
||||
}
|
||||
}
|
||||
: {
|
||||
name: '',
|
||||
@@ -114,8 +116,7 @@ function InventoryScreen() {
|
||||
replenishment: false,
|
||||
preferredLocations: false,
|
||||
inventory_process: 'CCR'
|
||||
},
|
||||
image: []
|
||||
}
|
||||
},
|
||||
validationSchema: schema.addInventory,
|
||||
onSubmit: (values) => {
|
||||
@@ -126,9 +127,10 @@ function InventoryScreen() {
|
||||
loader: 'loading-request',
|
||||
slug: `${API.ADD_INVENTORY}/${inventoryId}`,
|
||||
method: 'patch',
|
||||
navigateTo,
|
||||
data: {
|
||||
...values,
|
||||
image: values.image[0]?.file || null
|
||||
icon_slug: 'testslug'
|
||||
}
|
||||
})
|
||||
)
|
||||
@@ -137,14 +139,13 @@ function InventoryScreen() {
|
||||
loader: 'loading-request',
|
||||
slug: API.ADD_INVENTORY,
|
||||
method: 'post',
|
||||
navigateTo,
|
||||
data: {
|
||||
...values,
|
||||
image: values.image[0]?.file || null
|
||||
icon_slug: 'testslug'
|
||||
}
|
||||
})
|
||||
);
|
||||
// navigate to edit inventory page
|
||||
// onSubmitProps.resetForm();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -257,14 +258,7 @@ function InventoryScreen() {
|
||||
</MDBox>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={6}>
|
||||
<ImageUpload
|
||||
heading="Upload Inventory Image"
|
||||
accept="image/*"
|
||||
images={formik.values.image}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('image', images);
|
||||
}}
|
||||
/>
|
||||
icon slugs selector
|
||||
</Grid>
|
||||
<MDBox sx={{ ml: 'auto', mr: 'auto', mt: 3 }}>
|
||||
<MDButton
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable indent */
|
||||
import React from 'react';
|
||||
import MDBox from 'components/MDBox';
|
||||
import DashboardNavbar from 'components/DashboardNavbar';
|
||||
@@ -10,41 +11,70 @@ import { useParams } from 'react-router-dom';
|
||||
import LOGGER from 'services/Logger';
|
||||
import { ItemSelectors } from 'redux/ItemRedux';
|
||||
import EnhancedTable from 'components/EnhancedTable';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import WidgetActions from 'redux/WidgetRedux';
|
||||
import { WidgetSelectors } from 'redux/WidgetRedux';
|
||||
import { DialogContent, DialogContentText, DialogTitle, MenuItem, Select } from '@mui/material';
|
||||
|
||||
const tHeads = [
|
||||
{ key: 'name', name: '' },
|
||||
{ key: 'commonName', name: 'Common Name' },
|
||||
{ key: 'formalName', name: 'Formal Name' },
|
||||
{ key: 'description', name: 'Description' },
|
||||
{ key: 'manufacturer', name: 'Manufacturer' }
|
||||
{ key: 'manufacturer', name: 'Manufacturer' },
|
||||
{ key: 'size', name: 'Size' },
|
||||
{ key: 'color', name: 'Color' },
|
||||
{ key: 'type', name: 'Type' },
|
||||
{ key: 'unitOfMaterial', name: 'Unit of Material' },
|
||||
{ key: 'unitCost', name: 'Unit Cost' },
|
||||
{ key: 'packageCount', name: 'Package Count' },
|
||||
{ key: 'countPerPallet', name: 'Count Per Pallet' },
|
||||
{ key: 'countPerPalletPackage', name: 'Count Per Pallet Package' }
|
||||
];
|
||||
|
||||
function ItemListing() {
|
||||
const dispatch = useDispatch();
|
||||
const { widgetName, inventoryId } = useParams();
|
||||
const [page /*, setPage*/] = React.useState(0);
|
||||
const [perPage /*, setPerPage*/] = React.useState(10);
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [perPage, setPerPage] = React.useState(10);
|
||||
LOGGER.log({ widgetName, inventoryId });
|
||||
|
||||
const data = useSelector(ItemSelectors.getItemsByInventoryId(inventoryId));
|
||||
const navigate = useNavigate();
|
||||
const navigateTo = (path) => {
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
React.useEffect(
|
||||
() => {
|
||||
dispatch(
|
||||
ItemActions.itemRequest({
|
||||
loader: 'loading-request',
|
||||
slug: API.GET_ITEMS_BY_INVENTORY,
|
||||
method: 'get',
|
||||
page,
|
||||
perPage,
|
||||
inventoryId
|
||||
})
|
||||
);
|
||||
},
|
||||
[
|
||||
/* page, perPage */
|
||||
]
|
||||
);
|
||||
const data = useSelector(ItemSelectors.getItems);
|
||||
const count = useSelector(ItemSelectors.getItemsCount);
|
||||
|
||||
const [pFam, setPFam] = React.useState('');
|
||||
const [sFam, setSFam] = React.useState('');
|
||||
const primaryFamilies = useSelector(WidgetSelectors.getWidgetFamiliesByInventoryId(inventoryId));
|
||||
const secondaryFamilies = useSelector(WidgetSelectors.getWidgetsByParentId(pFam));
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(
|
||||
ItemActions.itemRequest({
|
||||
loader: 'loading-request',
|
||||
slug: API.GET_ITEMS_BY_INVENTORY,
|
||||
method: 'get',
|
||||
page: page - 1,
|
||||
perPage,
|
||||
inventoryId,
|
||||
family: sFam || pFam || null
|
||||
})
|
||||
);
|
||||
}, [page, perPage, pFam, sFam]);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(
|
||||
WidgetActions.widgetRequest({
|
||||
loader: 'location-request',
|
||||
slug: `${API.GET_WIDGET_FAMILY_BY_INVENTORY}${inventoryId}`,
|
||||
method: 'get'
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DashboardLayout>
|
||||
@@ -60,7 +90,89 @@ function ItemListing() {
|
||||
|
||||
<MDBox px={2} py={3}>
|
||||
List of {widgetName}s{/* <pre>{JSON.stringify(data, null, 4)}</pre> */}
|
||||
<EnhancedTable data={data} tHeads={tHeads} />
|
||||
<EnhancedTable
|
||||
count={count}
|
||||
page={page}
|
||||
setPage={setPage}
|
||||
perPage={perPage}
|
||||
setPerPage={setPerPage}
|
||||
editHandler={(id) => {
|
||||
navigateTo(`/setup/inventory/browse/${widgetName}/${inventoryId}/edit/${id}`);
|
||||
}}
|
||||
resetFilters={() => {
|
||||
setPFam('');
|
||||
setSFam('');
|
||||
}}
|
||||
filtersControl={
|
||||
<>
|
||||
<DialogTitle>Add filters</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>Filter by family</DialogContentText>
|
||||
<Select
|
||||
select
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={pFam}
|
||||
onChange={(e) => {
|
||||
setSFam('');
|
||||
setPFam(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem key={'none'} value={''}>
|
||||
None Selected
|
||||
</MenuItem>
|
||||
{primaryFamilies &&
|
||||
primaryFamilies.map((fam) => (
|
||||
<MenuItem key={fam._id} value={fam._id}>
|
||||
{fam.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
<Select
|
||||
select
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={sFam}
|
||||
onChange={(e) => {
|
||||
setSFam(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem key={'none'} value={''}>
|
||||
None Selected
|
||||
</MenuItem>
|
||||
{secondaryFamilies &&
|
||||
secondaryFamilies.map((fam) => (
|
||||
<MenuItem key={fam._id} value={fam._id}>
|
||||
{fam.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</DialogContent>
|
||||
</>
|
||||
}
|
||||
data={
|
||||
data
|
||||
? data.map((item) => {
|
||||
return {
|
||||
name: item._id,
|
||||
commonName: item.commonName,
|
||||
formalName: item.formalName,
|
||||
description: item.description,
|
||||
manufacturer: item.manufacturer,
|
||||
size: item.size,
|
||||
color: item.color,
|
||||
type: item.type,
|
||||
unitOfMaterial: item.unitOfMaterial,
|
||||
unitCost: item.unitCost,
|
||||
packageCount: item.packageCount,
|
||||
countPerPallet: item.countPerPallet,
|
||||
countPerPalletPackage: item.countPerPalletPackage
|
||||
};
|
||||
})
|
||||
: []
|
||||
}
|
||||
tHeads={tHeads}
|
||||
/>
|
||||
</MDBox>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { Box, Grid, MenuItem, OutlinedInput, Chip, Select } from '@mui/material';
|
||||
import DashboardNavbar from 'components/DashboardNavbar';
|
||||
import DashboardLayout from 'layouts/DashboardLayout';
|
||||
import ImageUpload from 'components/ImageUpload';
|
||||
import ImageUploadSingle from 'components/ImageUploadSingle';
|
||||
import MDButton from 'components/Button';
|
||||
import { useFormik } from 'formik';
|
||||
import schema from 'services/ValidationServices';
|
||||
// import schema from 'services/ValidationServices';
|
||||
import MDInput from 'components/MDInput';
|
||||
import WarehouseActions from 'redux/WarehouseRedux';
|
||||
import { API } from 'constant';
|
||||
import SnackBar from 'components/SnackBar';
|
||||
import Breadcrumbs from 'components/Breadcrumbs';
|
||||
|
||||
const inventoryTypes = ['Perishable', 'Material', 'Product', 'Inventory', 'Fleet'];
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { InventorySelectors } from 'redux/InventoryRedux';
|
||||
import InventoryActions from 'redux/InventoryRedux';
|
||||
|
||||
function NewWarehouseDetails() {
|
||||
const dispatch = useDispatch();
|
||||
const [open, setOpen] = useState(false);
|
||||
const inventoryTypes = useSelector(InventorySelectors.getInventoryDetail);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(
|
||||
InventoryActions.getInventoryAction({
|
||||
loader: 'loading-request',
|
||||
slug: API.GET_INVENTORY,
|
||||
method: 'get'
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const navigateTo = (id) => {
|
||||
navigate(`/setup/warehouse/edit-warehouse/${id}`);
|
||||
};
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
@@ -33,37 +50,31 @@ function NewWarehouseDetails() {
|
||||
initialValues: {
|
||||
warehousename: '',
|
||||
address: '',
|
||||
inventorytype: [],
|
||||
attributes: '',
|
||||
images: []
|
||||
preferredInventories: [],
|
||||
specs: '',
|
||||
image: []
|
||||
},
|
||||
validationSchema: schema.warehouseForm,
|
||||
onSubmit: (values, onSubmitProps) => {
|
||||
// validationSchema: schema.warehouseForm,
|
||||
onSubmit: (values) => {
|
||||
dispatch(
|
||||
WarehouseActions.createWarehouseAction({
|
||||
loader: 'loading-request',
|
||||
slug: API.CREATE_WAREHOUSE,
|
||||
method: 'post',
|
||||
navigateTo: navigateTo,
|
||||
data: {
|
||||
name: values.warehousename,
|
||||
address: values.address,
|
||||
specs: '',
|
||||
preferredInventories: values.preferredInventories,
|
||||
specs: values.specs,
|
||||
image: values.image,
|
||||
company_id: '61cea5fd028432700a7f8601'
|
||||
}
|
||||
})
|
||||
);
|
||||
onSubmitProps.resetForm();
|
||||
setOpen(true);
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = (event, reason) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DashboardLayout>
|
||||
@@ -155,25 +166,31 @@ function NewWarehouseDetails() {
|
||||
select
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
name="inventorytype"
|
||||
name="preferredInventories"
|
||||
input={<OutlinedInput />}
|
||||
value={formik.values.inventorytype}
|
||||
error={formik.touched.inventorytype && Boolean(formik.errors.inventorytype)}
|
||||
helperText={formik.touched.inventorytype && formik.errors.inventorytype}
|
||||
value={formik.values.preferredInventories}
|
||||
error={
|
||||
formik.touched.preferredInventories &&
|
||||
Boolean(formik.errors.preferredInventories)
|
||||
}
|
||||
helperText={
|
||||
formik.touched.preferredInventories && formik.errors.preferredInventories
|
||||
}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||
{selected.map((value) => (
|
||||
<Chip key={value} label={value} />
|
||||
<Chip
|
||||
key={value}
|
||||
label={inventoryTypes.find((x) => x._id === value)?.name || 'unknown'}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
onChange={(event) => {
|
||||
const {
|
||||
target: { value }
|
||||
} = event;
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
formik.setFieldValue(
|
||||
'inventorytype',
|
||||
'preferredInventories',
|
||||
// On autofill we get a stringified value.
|
||||
typeof value === 'string' ? value.split(',') : value
|
||||
);
|
||||
@@ -182,11 +199,12 @@ function NewWarehouseDetails() {
|
||||
<MenuItem key={''} value={''}>
|
||||
None Selected
|
||||
</MenuItem>
|
||||
{inventoryTypes.map((name) => (
|
||||
<MenuItem key={name} value={name}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
{inventoryTypes &&
|
||||
inventoryTypes.map((inventory) => (
|
||||
<MenuItem key={inventory._id} value={inventory._id}>
|
||||
{inventory.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</Box>
|
||||
<Box component="div" sx={{ marginBottom: '15px' }}>
|
||||
@@ -205,23 +223,23 @@ function NewWarehouseDetails() {
|
||||
fullWidth
|
||||
type="text"
|
||||
variant="outlined"
|
||||
name="attributes"
|
||||
value={formik.values.attributes}
|
||||
error={formik.touched.attributes && Boolean(formik.errors.attributes)}
|
||||
helperText={formik.touched.attributes && formik.errors.attributes}
|
||||
name="specs"
|
||||
value={formik.values.specs}
|
||||
error={formik.touched.specs && Boolean(formik.errors.specs)}
|
||||
helperText={formik.touched.specs && formik.errors.specs}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={6}>
|
||||
<Box sx={{ marginTop: '30px' }}>
|
||||
<ImageUpload
|
||||
<ImageUploadSingle
|
||||
multiple
|
||||
heading="Upload Warehouse Image"
|
||||
accept="image/*"
|
||||
images={formik.values.images}
|
||||
setImages={(images) => {
|
||||
formik.setFieldValue('images', images);
|
||||
images={formik.values.image}
|
||||
setImages={(image) => {
|
||||
formik.setFieldValue('image', image);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -235,7 +253,14 @@ function NewWarehouseDetails() {
|
||||
columnGap: '20px'
|
||||
}}
|
||||
>
|
||||
<MDButton size="medium" color="error" variant="outlined">
|
||||
<MDButton
|
||||
size="medium"
|
||||
color="error"
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
navigate('/setup/warehouse');
|
||||
}}
|
||||
>
|
||||
CANCEL
|
||||
</MDButton>
|
||||
<MDButton size="medium" color="primary" variant="outlined" type="submit">
|
||||
@@ -249,11 +274,6 @@ function NewWarehouseDetails() {
|
||||
</form>
|
||||
</Box>
|
||||
</DashboardLayout>
|
||||
<SnackBar
|
||||
open={open}
|
||||
message="new warehouse created successfully"
|
||||
handleClose={handleClose}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ import { getFetchingValue, getErrorValue } from '../services/Utils';
|
||||
const { Types, Creators } = createActions({
|
||||
itemRequest: ['payload'],
|
||||
itemSuccess: ['data'],
|
||||
itemFailure: ['error'],
|
||||
addItemRequest: ['payload'],
|
||||
addItemSuccess: ['data'],
|
||||
editItemRequest: ['payload'],
|
||||
editItemSuccess: ['data'],
|
||||
itemFailure: ['error'],
|
||||
logout: null
|
||||
oneItemRequest: ['payload'],
|
||||
oneItemSuccess: ['data']
|
||||
});
|
||||
|
||||
export const ItemTypes = Types;
|
||||
@@ -20,6 +23,8 @@ export default ItemActions;
|
||||
/* ------------- Initial State ------------- */
|
||||
export const INITIAL_STATE = Immutable({
|
||||
list: [],
|
||||
item: null,
|
||||
count: 0,
|
||||
fetching: [],
|
||||
error: {}
|
||||
});
|
||||
@@ -27,9 +32,9 @@ export const INITIAL_STATE = Immutable({
|
||||
/* ------------- Selectors ------------- */
|
||||
export const ItemSelectors = {
|
||||
getItems: (state) => state.items.list,
|
||||
getItemById: (id) => (state) => state.items.list.find((x) => x._id === id),
|
||||
getItemsByInventoryId: (id) => (state) =>
|
||||
state.items.list.filter((x) => x.widgetFamily?.inventory === id)
|
||||
getFormItem: (itemId) => (state) => state.items.item?._id === itemId ? state.items.item : null,
|
||||
getItemsCount: (state) => state.items.count,
|
||||
getItemById: (id) => (state) => state.items.list.find((x) => x._id === id)
|
||||
};
|
||||
|
||||
/* ------------- Reducers ------------- */
|
||||
@@ -39,49 +44,51 @@ export const onItemRequest = (state, { payload }) =>
|
||||
error: getErrorValue(state?.error, payload?.loader)
|
||||
});
|
||||
|
||||
export const onItemSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
list: data.items,
|
||||
count: data.count
|
||||
});
|
||||
|
||||
export const onOneItemRequest = (state, { payload }) =>
|
||||
state.merge({
|
||||
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||
error: getErrorValue(state?.error, payload?.loader)
|
||||
});
|
||||
|
||||
export const onOneItemSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
item: data.item
|
||||
});
|
||||
|
||||
export const onAddItemRequest = (state, { payload }) =>
|
||||
state.merge({
|
||||
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||
error: getErrorValue(state?.error, payload?.loader)
|
||||
});
|
||||
|
||||
export const onAddItemSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
item: null
|
||||
});
|
||||
|
||||
export const onEditItemRequest = (state, { payload }) =>
|
||||
state.merge({
|
||||
fetching: _.uniq([...state.fetching, payload?.loader]),
|
||||
error: getErrorValue(state?.error, payload?.loader)
|
||||
});
|
||||
|
||||
const mergeItemStates = (stateData, items) => {
|
||||
if (!items) return stateData; // undefined check
|
||||
|
||||
const idsInNewItems = items.map((x) => x._id);
|
||||
|
||||
const newState = stateData.filter((x) => !idsInNewItems.includes(x._id));
|
||||
|
||||
return [...newState, ...items];
|
||||
};
|
||||
|
||||
export const onItemSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
list: mergeItemStates(state.list, data.items)
|
||||
});
|
||||
|
||||
const mergeEditItemStates = (stateList, item, type) => {
|
||||
if (!item) return stateList; // undefined check
|
||||
|
||||
if (type === 'add') {
|
||||
return [...stateList, item];
|
||||
} else if (type === 'edit') {
|
||||
const newState = stateList.filter((x) => x._id !== item._id);
|
||||
return [...newState, item];
|
||||
// } else if (type === 'delete') {
|
||||
// return stateList.filter((x) => x._id !== item._id);
|
||||
} else {
|
||||
return stateList;
|
||||
}
|
||||
};
|
||||
|
||||
export const onEditItemSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
list: mergeEditItemStates(state.list, data.item, data.type)
|
||||
item: null
|
||||
});
|
||||
|
||||
export const onItemFailure = (state, { error }) =>
|
||||
@@ -93,8 +100,12 @@ export const onItemFailure = (state, { error }) =>
|
||||
/* ------------- Hookup Reducers To Types ------------- */
|
||||
export const itemReducer = createReducer(INITIAL_STATE, {
|
||||
[Types.ITEM_REQUEST]: onItemRequest,
|
||||
[Types.EDIT_ITEM_REQUEST]: onEditItemRequest,
|
||||
[Types.ITEM_SUCCESS]: onItemSuccess,
|
||||
[Types.ITEM_FAILURE]: onItemFailure,
|
||||
[Types.ADD_ITEM_REQUEST]: onAddItemRequest,
|
||||
[Types.ADD_ITEM_SUCCESS]: onAddItemSuccess,
|
||||
[Types.EDIT_ITEM_REQUEST]: onEditItemRequest,
|
||||
[Types.EDIT_ITEM_SUCCESS]: onEditItemSuccess,
|
||||
[Types.ITEM_FAILURE]: onItemFailure
|
||||
[Types.ONE_ITEM_REQUEST]: onOneItemRequest,
|
||||
[Types.ONE_ITEM_SUCCESS]: onOneItemSuccess
|
||||
});
|
||||
|
||||
@@ -26,12 +26,8 @@ export default WarehouseActions;
|
||||
export const INITIAL_STATE = Immutable({
|
||||
warehouseDetail: [],
|
||||
error: {},
|
||||
|
||||
createWarehouse: [],
|
||||
createWarehouseLoading: false,
|
||||
createWarehouseError: {},
|
||||
|
||||
editWarehouse: [],
|
||||
editWarehouseLoading: false,
|
||||
editWarehouseError: {}
|
||||
});
|
||||
@@ -75,7 +71,7 @@ export const onCreateWarehouseSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
createWarehouse: data.createWarehouse
|
||||
warehouseDetail: [...state.warehouseDetail, data.createdWarehouse]
|
||||
});
|
||||
|
||||
export const onCreateWarehouseFailure = (state, { error }) =>
|
||||
@@ -94,7 +90,10 @@ export const onEditWarehouseSuccess = (state, { data }) =>
|
||||
state.merge({
|
||||
fetching: getFetchingValue(state.fetching, data?.loader),
|
||||
error: getErrorValue(state?.error, data?.loader),
|
||||
editWarehouse: data.editWarehouse
|
||||
warehouseDetail: [
|
||||
...state.warehouseDetail.filter((x) => x._id !== data?.editedWarehouse?._id),
|
||||
data.editedWarehouse
|
||||
]
|
||||
});
|
||||
|
||||
export const onEditWarehouseFailure = (state, { error }) =>
|
||||
|
||||
@@ -117,6 +117,14 @@ const protectedRoutes = [
|
||||
route: '/setup/inventory/new-item/:widgetName/:inventoryId',
|
||||
component: <AddNewItem />
|
||||
},
|
||||
{
|
||||
name: 'Update Item',
|
||||
key: 'udpate-item',
|
||||
hide: true,
|
||||
route: '/setup/inventory/browse/:widgetName/:inventoryId/edit/:itemId',
|
||||
component: <AddNewItem />
|
||||
},
|
||||
// /setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${payload?.id}
|
||||
{
|
||||
name: 'View Items',
|
||||
key: 'view-items',
|
||||
|
||||
@@ -55,35 +55,24 @@ export function* onRequestGetInventoryTypesData({ payload }) {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
payload?.data
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
toast('New inventory added');
|
||||
yield put(
|
||||
InventoryActions.addInventorySuccess({
|
||||
loader: payload?.loader,
|
||||
newInventory: response?.data?.data?.inventoryData
|
||||
})
|
||||
);
|
||||
payload.navigateTo();
|
||||
} else {
|
||||
toast('Failed to add inventory');
|
||||
payload.onFailedAddInventoryData(response.data.error);
|
||||
yield put(
|
||||
InventoryActions.addInventoryFailure({
|
||||
@@ -109,8 +98,9 @@ export function* onRequestUpdateInventoryData({ payload }) {
|
||||
updateInventory: response?.data?.data
|
||||
})
|
||||
);
|
||||
payload.navigateTo();
|
||||
} else {
|
||||
payload.onFailedUpdateInventoryData(response.data.error);
|
||||
toast('Failed to update inventory');
|
||||
yield put(
|
||||
InventoryActions.updateInventoryFailure({
|
||||
loader: payload?.loader,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { AuthorizedAPI } from 'config';
|
||||
import { toast } from 'react-toastify';
|
||||
import { call, put, takeEvery } from 'redux-saga/effects';
|
||||
import ApiServices from 'services/API/ApiServices';
|
||||
import ItemActions, { ItemTypes } from '../redux/ItemRedux';
|
||||
@@ -7,14 +8,17 @@ export function* onRequestItem({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
`${payload?.slug}${payload?.inventoryId}&page=${payload?.page}&perPage=${payload?.perPage}`,
|
||||
`${payload?.slug}${payload?.inventoryId}&page=${payload?.page}&perPage=${payload?.perPage}${
|
||||
payload?.family ? '&family=' + payload?.family : ''
|
||||
}`,
|
||||
payload?.data
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
yield put(
|
||||
ItemActions.itemSuccess({
|
||||
loader: payload?.loader,
|
||||
items: response?.data?.data,
|
||||
items: response?.data?.data.result,
|
||||
count: response?.data?.data.count,
|
||||
page: payload?.page,
|
||||
reset: !payload.page
|
||||
})
|
||||
@@ -29,22 +33,24 @@ export function* onRequestItem({ payload }) {
|
||||
}
|
||||
}
|
||||
|
||||
export function* onEditRequestItem({ payload }) {
|
||||
export function* onRequestOneItem({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
payload?.data
|
||||
`${payload.slug}${payload?.itemId}`
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
yield put(
|
||||
ItemActions.editItemSuccess({
|
||||
ItemActions.oneItemSuccess({
|
||||
loader: payload?.loader,
|
||||
item: response?.data?.data,
|
||||
type: payload?.type
|
||||
item: response?.data?.data
|
||||
})
|
||||
);
|
||||
// payload.navigateTo(
|
||||
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${payload?.itemId}`
|
||||
// );
|
||||
} else {
|
||||
toast('Failed to get item details');
|
||||
yield put(
|
||||
ItemActions.itemFailure({
|
||||
loader: payload?.loader,
|
||||
@@ -54,7 +60,98 @@ export function* onEditRequestItem({ payload }) {
|
||||
}
|
||||
}
|
||||
|
||||
function addImagesToFormData(formData, images) {
|
||||
let imgIdx = 0;
|
||||
let preImgIdx = 0;
|
||||
images.forEach((image) => {
|
||||
if (image.file) formData.append(`images[${imgIdx++}]`, image.file);
|
||||
else formData.append(`imageIds[${preImgIdx++}]`, image._id);
|
||||
});
|
||||
}
|
||||
|
||||
function buildFormData(formData, data, parentKey) {
|
||||
if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (key !== 'images')
|
||||
buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key);
|
||||
else addImagesToFormData(formData, data['images']);
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const value = data == null ? '' : data;
|
||||
|
||||
formData.append(parentKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
const createFormData = (data) => {
|
||||
const formData = new FormData();
|
||||
|
||||
buildFormData(formData, data);
|
||||
|
||||
return formData;
|
||||
};
|
||||
|
||||
export function* onAddRequestItem({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
createFormData(payload?.data)
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
toast(`Added item: ${payload.data.commonName}`);
|
||||
// payload.navigateTo(
|
||||
// `/setup/inventory/browse/${payload?.widgetName}/${payload?.inventoryId}/edit/${response?.data?.data?._id}`
|
||||
// );
|
||||
payload.navigateTo('/setup/inventory');
|
||||
yield put(
|
||||
ItemActions.addItemSuccess({
|
||||
loader: payload?.loader,
|
||||
item: response?.data?.data
|
||||
})
|
||||
);
|
||||
} else {
|
||||
toast('Failed to add item');
|
||||
yield put(
|
||||
ItemActions.itemFailure({
|
||||
loader: payload?.loader,
|
||||
error: response?.data
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function* onEditRequestItem({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
createFormData(payload?.data)
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
toast(`Successfully edited item: ${payload.data.commonName}`);
|
||||
payload.navigateTo('/setup/inventory');
|
||||
yield put(
|
||||
ItemActions.addItemSuccess({
|
||||
loader: payload?.loader,
|
||||
item: response?.data?.data
|
||||
})
|
||||
);
|
||||
} else {
|
||||
toast('Failed to edit item');
|
||||
yield put(
|
||||
ItemActions.itemFailure({
|
||||
loader: payload?.loader,
|
||||
error: response?.data
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default [
|
||||
takeEvery(ItemTypes.ITEM_REQUEST, onRequestItem),
|
||||
takeEvery(ItemTypes.ONE_ITEM_REQUEST, onRequestOneItem),
|
||||
takeEvery(ItemTypes.ADD_ITEM_REQUEST, onAddRequestItem),
|
||||
takeEvery(ItemTypes.EDIT_ITEM_REQUEST, onEditRequestItem)
|
||||
];
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AuthorizedAPI } from 'config';
|
||||
import { takeLatest, call, put } from 'redux-saga/effects';
|
||||
import WarehouseActions, { WarehouseTypes } from '../redux/WarehouseRedux';
|
||||
import ApiServices from 'services/API/ApiServices';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
export function* onRequestWarehouseData({ payload }) {
|
||||
const response = yield call(
|
||||
@@ -28,22 +29,42 @@ export function* onRequestWarehouseData({ payload }) {
|
||||
}
|
||||
}
|
||||
|
||||
const makeFormData = (data) => {
|
||||
const formData = new FormData();
|
||||
if (data.name) formData.append('name', data.name);
|
||||
if (data.address) formData.append('address', data.address);
|
||||
if (data.specs) formData.append('specs', data.specs);
|
||||
if (data.company_id) formData.append('company_id', data.company_id);
|
||||
if (data.preferredInventories)
|
||||
data.preferredInventories.forEach((prefInv, idx) => {
|
||||
formData.append(`preferredInventories[${idx}]`, prefInv);
|
||||
});
|
||||
if (data.image[0].file) formData.append('image', data.image[0].file);
|
||||
return formData;
|
||||
};
|
||||
|
||||
export function* onRequestCreateWarehouse({ payload }) {
|
||||
const response = yield call(
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
payload?.data
|
||||
makeFormData(payload?.data)
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
if (response?.status === 200 && response?.data?.message) {
|
||||
const warehouse = response?.data?.message;
|
||||
toast('Warehouse created successfully');
|
||||
yield put(
|
||||
WarehouseActions.createWarehouseSuccess({
|
||||
loader: payload?.loader,
|
||||
createWarehouse: response?.data?.data
|
||||
createdWarehouse: {
|
||||
...warehouse,
|
||||
preferredInventories: warehouse.preferredInventories.map((z) => z._id)
|
||||
}
|
||||
})
|
||||
);
|
||||
payload.navigateTo(response?.data?.message?._id);
|
||||
} else {
|
||||
payload.onFailedCreateWarehouse(response.data.error);
|
||||
toast('Failed to create warehouse');
|
||||
yield put(
|
||||
WarehouseActions.createWarehouseFailure({
|
||||
loader: payload?.loader,
|
||||
@@ -58,17 +79,22 @@ export function* onRequestEditWarehouse({ payload }) {
|
||||
ApiServices[payload?.method],
|
||||
AuthorizedAPI,
|
||||
payload?.slug,
|
||||
payload?.data
|
||||
makeFormData(payload?.data)
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
if (response?.status === 200 && response?.data?.data) {
|
||||
toast('Warehouse edited successfully');
|
||||
const warehouse = response?.data?.data;
|
||||
yield put(
|
||||
WarehouseActions.editWarehouseSuccess({
|
||||
loader: payload?.loader,
|
||||
createWarehouse: response?.data?.data
|
||||
editedWarehouse: {
|
||||
...warehouse,
|
||||
preferredInventories: warehouse.preferredInventories.map((z) => z._id)
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
payload.onFailedEditWarehouse(response.data.error);
|
||||
toast('Failed to edit warehouse');
|
||||
yield put(
|
||||
WarehouseActions.editWarehouseFailure({
|
||||
loader: payload?.loader,
|
||||
|
||||
@@ -22,10 +22,11 @@ const schema = {
|
||||
warehouseForm: Yup.object({
|
||||
warehousename: Yup.string('Enter warehouse name').required('warehouse name is required'),
|
||||
address: Yup.string('Enter address').required('address is required'),
|
||||
inventorytype: Yup.array('Enter inventory Type')
|
||||
preferredInventories: Yup.array('Enter inventory Type')
|
||||
.of(Yup.string())
|
||||
.required('inventory Type is required'),
|
||||
attributes: Yup.string('Enter other attributes')
|
||||
specs: Yup.string('Enter other attributes'),
|
||||
image: Yup.array()
|
||||
}),
|
||||
|
||||
addNewItem: Yup.object({
|
||||
|
||||
Reference in New Issue
Block a user