Feature/wms 53 (#53)

* create warehouse
* edit warehouse changes
* Update: linted and formatted
* add warehouse button
* user access changes
* basic table component changes
* Updated: eslint errors
* basic table component changes
* update: linted

Co-authored-by: [Diksha] <[diksha39511@gmail.com]>
Co-authored-by: Llewellyn Dsouza <lledsouza2209@gmail.com>
This commit is contained in:
Dikshajain39511
2022-02-11 14:53:22 +05:30
committed by GitHub
parent 97b7d5a85e
commit a4198afc1d
11 changed files with 415 additions and 343 deletions

View File

@@ -0,0 +1,43 @@
import React from 'react';
import { Table } from '@mui/material';
import { makeStyles } from '@mui/styles';
import PropTypes from 'prop-types';
export default function TblContainer({ children, backgroundColor, color }) {
const useStyles = makeStyles({
headDisplay: {
display: 'revert'
},
table: {
'& thead th': {
fontWeight: '600',
color: color,
backgroundColor: backgroundColor
},
'& tbody td': {
borderRadius: '2px',
fontWeight: 300,
borderRight: '1px solid #EBEBEB',
borderBottom: '1px solid #EBEBEB',
borderLeft: '1px solid #EBEBEB',
textAlign: 'left',
whiteSpace: 'nowrap'
},
'& tbody tr:hover': {
cursor: 'pointer'
}
}
});
const classes = useStyles();
return (
<>
<Table className={classes.table}>{children}</Table>
</>
);
}
TblContainer.propTypes = {
children: PropTypes.node.isRequired,
backgroundColor: PropTypes.string.isRequired,
color: PropTypes.string.isRequired
};

View File

@@ -1,69 +1,40 @@
import React from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import TblContainer from './TblContainer';
import { makeStyles } from '@mui/styles';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import { TableCell, TableHead, TableRow } from '@mui/material';
const useStyles = makeStyles({
headColor: {
const useStyles = makeStyles(() => ({
headDisplay: {
display: 'revert'
},
rowStyle: {
color: '#007aff'
},
tablebody: {
fontSize: '13px',
color: '#7F7F7F'
}
});
}));
const row = (x, i, header) => (
<TableRow key={`tr-${i}`}>
{header.map((y, k) => (
<TableCell key={`tc-${k}`}>{x[y.prop]}</TableCell>
))}
</TableRow>
);
export default function BasicTable({ data, header, backgroundColor }) {
export default function BasicTable({ children, headCells, backgroundColor, color }) {
const classes = useStyles();
const TableContainer = styled('div')(
() => `
td,
th {
border-right: 1px solid #EBEBEB;
border-bottom: 1px solid #EBEBEB;
border-left: 1px solid #EBEBEB;
text-align: left;
white-space: nowrap;
background-color: white;
}
th {
background-color: ${backgroundColor};,
color: #9B9B9B;
}
`
);
return (
<TableContainer sx={{ width: 200, maxWidth: '100%' }}>
<Table sx={{ minWidth: 700 }} style={{ width: 1200 }}>
<TableHead className={classes.headColor}>
<TableRow className={classes.tableRowContainer}>
{header && header.map((x, i) => <TableCell key={`thc-${i}`}>{x.name}</TableCell>)}
<>
<TblContainer backgroundColor={backgroundColor} color={color}>
<TableHead className={classes.headDisplay}>
<TableRow>
{headCells.map((headCell) => (
<TableCell key={headCell.id}>{headCell.label}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>{data.map((x, i) => row(x, i, header))}</TableBody>
</Table>
</TableContainer>
{children}
</TblContainer>
</>
);
}
BasicTable.propTypes = {
data: PropTypes.array,
header: PropTypes.array,
backgroundColor: PropTypes.string
children: PropTypes.node.isRequired,
headCells: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired
})
).isRequired,
backgroundColor: PropTypes.string,
color: PropTypes.string
};

View File

@@ -45,7 +45,7 @@ UnauthorizedAPI.addMonitor(APIMonitor);
AuthorizedAPI.addAsyncRequestTransform(async (request) => {
LOGGER.log('request', request);
let token = localStorage.getItem('token');
request.headers.Authorization = `Bearer ${token}`;
request.headers.Authorization = token;
});
export { AuthorizedAPI, UnauthorizedAPI };

View File

@@ -1,5 +1,6 @@
export default {
LOGIN_USER: '/user/login',
GET_WAREHOUSE_DATA: '/warehouse/all?page=0&perPage=50',
CREATE_WAREHOUSE:'/warehouse/'
CREATE_WAREHOUSE: '/warehouse/',
GET_USERS_DATA: '/user/all?page=0&perPage=10'
};

View File

@@ -1,7 +1,7 @@
import DashboardNavbar from 'components/DashboardNavbar';
import Footer from 'components/Footer';
import DashboardLayout from 'layouts/DashboardLayout';
import { Grid, InputLabel } from '@mui/material';
import { Grid, InputLabel, TableBody, TableCell, TableRow } from '@mui/material';
import MDInput from 'components/MDInput';
import ImageUpload from 'components/ImageUpload';
import Switch from 'components/Switch';
@@ -38,81 +38,82 @@ const useStyles = makeStyles({
}
});
const stockBox = [
{
text: 'Stock Tracking'
},
{
text: 'Replenishment'
},
{
text: 'Alerting'
},
{
text: 'Check In/Out'
},
{
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 dataInventory = [
{
placeholder: 'Lorem Ipsum',
label: 'Inventory Type'
}
];
const dataLevel = [
{
placeholder: 'Lorem Ipsum',
label: 'Level 1'
},
{
placeholder: 'Lorem Ipsum',
label: 'Level 2'
}
];
function InventoryScreen() {
const stockBox = [
{
text: 'Stock Tracking'
},
{
text: 'Replenishment'
},
{
text: 'Alerting'
},
{
text: 'Check In/Out'
},
{
text: 'Maintenance'
},
{
text: 'Location'
}
];
const tableData = [
{
level1: 'Ipsum',
level2: 'Vivera'
},
{
level1: 'Ipsum',
level2: 'Vivera'
}
];
const header = [
{
name: 'Level 1',
prop: 'level1'
},
{
name: 'Level 2',
prop: 'level2'
}
];
const dropdownData = [
{
ID: '1',
displayname: 'Regular, full time'
},
{
ID: '2',
displayname: 'Regular, part time'
},
{
ID: '3',
displayname: 'Contractor- Arise Max'
}
];
const dataInventory = [
{
placeholder: 'Lorem Ipsum',
label: 'Inventory Type'
}
];
const dataLevel = [
{
placeholder: 'Lorem Ipsum',
label: 'Level 1'
},
{
placeholder: 'Lorem Ipsum',
label: 'Level 2'
}
];
const previewImg = [1, 2, 3];
const classes = useStyles();
return (
@@ -203,18 +204,36 @@ function InventoryScreen() {
<Grid item xs={12} sm={12} md={12}>
<MDBox
sx={{
backgroundColor: '#E5E5E5',
width: '98%',
// backgroundColor: '#E5E5E5',
width: '100%',
padding: '9px'
}}
>
<MDTypography>Widget hierarchy</MDTypography>
<MDTypography
sx={{
backgroundColor: '#E5E5E5',
width: '100%',
padding: '9px'
}}
>
Widget hierarchy
</MDTypography>
<BasicTable
className={classes.margin}
data={tableData}
header={header}
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 }}>

View File

@@ -4,7 +4,7 @@ import Footer from 'components/Footer';
import DashboardLayout from 'layouts/DashboardLayout';
import { makeStyles } from '@mui/styles';
import Dropdown from 'components/Dropdown';
import { Grid } from '@mui/material';
import { Grid, TableBody, TableCell, TableRow } from '@mui/material';
import BasicTable from 'components/BasicTable';
import MDButton from 'components/Button';
@@ -25,6 +25,60 @@ const useStyles = makeStyles({
}
});
const records = [
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
},
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
},
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
}
];
const headCells = [
{
id: 'warehouse',
label: 'warehouse'
},
{
id: 'zone',
label: 'Zone'
},
{
id: 'area',
label: 'Area'
},
{
id: 'row',
label: 'Row'
},
{
id: 'Label',
label: 'label'
},
{
id: 'Bay',
label: 'bay'
}
];
function LabelingScreen() {
const classes = useStyles();
@@ -71,59 +125,6 @@ function LabelingScreen() {
}
];
const tableData = [
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
},
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
},
{
warehouse: 'Ipsum',
zone: 'Vivera',
area: 'Nisi',
row: 'Nulla',
label: 'Mauris',
bay: ''
}
];
const header = [
{
name: 'Warehouse',
prop: 'warehouse'
},
{
name: 'Zone',
prop: 'zone'
},
{
name: 'Area',
prop: 'area'
},
{
name: 'Row',
prop: 'row'
},
{
name: 'Label',
prop: 'label'
},
{
name: 'Bay',
prop: 'bay'
}
];
return (
<DashboardLayout>
<DashboardNavbar />
@@ -138,11 +139,25 @@ function LabelingScreen() {
</Grid>
<br />
<BasicTable
className={classes.margin}
data={tableData}
header={header}
backgroundColor="gray"
/>
headCells={headCells}
records={records}
backgroundColor="#F4F4F4"
color="#8D8D8D"
>
<TableBody>
{records &&
records.map((item) => (
<TableRow key={item.id}>
<TableCell>{item.warehouse}</TableCell>
<TableCell>{item.zone}</TableCell>
<TableCell>{item.area}</TableCell>
<TableCell>{item.row}</TableCell>
<TableCell>{item.label}</TableCell>
<TableCell>{item.Bay}</TableCell>
</TableRow>
))}
</TableBody>
</BasicTable>
<Grid container spacing={2}>
{data2 &&
data2.map((item, index) => (

View File

@@ -1,22 +1,30 @@
import React, { useEffect } from 'react';
import MDBox from 'components/MDBox';
import DashboardNavbar from 'components/DashboardNavbar';
import Footer from 'components/Footer';
import DashboardLayout from 'layouts/DashboardLayout';
import { styled } from '@mui/material/styles';
import { makeStyles } from '@mui/styles';
import BasicTable from 'components/BasicTable';
import { Grid } from '@mui/material';
import { Grid, TableBody, TableCell, TableRow } from '@mui/material';
import SearchBar from 'components/SearchBar';
import EditIcon from '@mui/icons-material/Edit';
import MDButton from 'components/Button';
import { useState } from 'react';
import EditIcon from '@mui/icons-material/Edit';
import { Tabs, Tab } from '@mui/material';
import TabPanel from 'components/Tabs';
import UsersActions from 'redux/UsersRedux';
import { API } from 'constant';
import { useDispatch, useSelector } from 'react-redux';
import { UsersSelectors } from 'redux/UsersRedux';
const useStyles = makeStyles({
const useStyles = makeStyles((theme) => ({
iconSize: {
width: '50%',
height: '50%',
marginBottom: '10px'
width: '2%',
height: '2%',
marginBottom: '10px',
color: theme.palette.primary.light,
marginRight: '8px'
},
margin: {
marginBottom: '20px'
@@ -27,152 +35,63 @@ const useStyles = makeStyles({
marginTable: {
marginTop: '20px'
},
iconwrap: {
display: 'flex',
alignItems: 'center'
},
tabs: {
'& .MuiButtonBase-root.MuiTab-root': {
padding: '12px 0px',
borderRadius: '0px'
},
'& .Mui-selected': {
textDecoration: 'underline',
backgroundColor: '#017AFF'
backgroundColor: '#017AFF',
color: 'white'
}
}
});
}));
const headCells = [
{ id: 'fullName', label: 'Name' },
{ id: 'role_name', label: 'Roles' }
];
function UserAccessScreen() {
const classes = useStyles();
const dispatch = useDispatch();
const [value, setValue] = useState(0);
const usersData = useSelector(UsersSelectors.getUsersDetail);
const [records, setRecords] = useState([]);
useEffect(() => {
if (usersData.length) {
let users = JSON.parse(JSON.stringify(usersData));
users = users.map((item) => {
item.role_name = item.roles.map((role) => role.name).join(',');
return item;
});
setRecords(users);
}
}, [usersData]);
const handleTabs = (e, val) => {
setValue(val);
};
const header = [
{
name: '',
prop: 'icon'
},
{
name: 'User Name',
prop: 'username'
},
{
name: 'Phone Number',
prop: 'phonenumber'
},
{
name: 'Roles',
prop: 'roles'
},
{
name: 'Last Updated by & Date',
prop: 'lastupdated'
},
{
name: 'Created by & Date',
prop: 'Createdby'
},
{
name: 'Last Login',
prop: 'lastlogin'
},
{
name: 'Access',
prop: 'access'
const usersHandler = () => {
dispatch(
UsersActions.getUsersAction({
loader: 'loading-request',
slug: API.GET_USERS_DATA,
method: 'get'
})
);
};
const StyledTableRow = styled(TableRow)(({ theme }) => ({
'&:nth-of-type(even)': {
backgroundColor: theme.palette.action.hover
}
];
const data = [
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
},
{
icon: <EditIcon />,
username: 'Floyd Miles',
phonenumber: '(704)555-0127',
roles: 'Administrator',
lastupdated: 'System| 1/1/2022 11:23:00 AM',
Createdby: 'System| 1/1/2022 11:23:00 AM',
lastlogin: 'System| 1/1/2022 11:23:00 AM',
access: 'Active'
}
];
}));
return (
<DashboardLayout>
@@ -182,16 +101,8 @@ function UserAccessScreen() {
<Grid item xs={12} sm={4} md={4}>
<Tabs value={value} className={classes.tabs} onChange={handleTabs}>
<Tab label="Roles" />
<Tab label="Users" />
<Tab label="Users" onClick={() => usersHandler()} />
</Tabs>
<TabPanel value={value} index={0}>
<div className={classes.marginTable}>
<BasicTable data={data} header={header} backgroundColor="#017AFF" />
</div>
</TabPanel>
<TabPanel value={value} index={1}>
Item2 Detail
</TabPanel>
</Grid>
<Grid item xs={12} sm={4} md={6}>
<SearchBar />
@@ -202,6 +113,32 @@ function UserAccessScreen() {
</MDButton>
</Grid>
</Grid>
<TabPanel value={value} index={0}>
<div className={classes.marginTable}>Item2 Detail</div>
</TabPanel>
<TabPanel value={value} index={1}>
<BasicTable
headCells={headCells}
records={records}
backgroundColor="#007AFF"
color="#fff"
>
<TableBody>
{records &&
records.map((item) => (
<StyledTableRow key={item.id}>
<TableCell>
<div className={classes.iconwrap}>
<EditIcon className={classes.iconSize} />
{item.fullName}
</div>
</TableCell>
<TableCell>{item.role_name}</TableCell>
</StyledTableRow>
))}
</TableBody>
</BasicTable>
</TabPanel>
</MDBox>
<Footer />
</DashboardLayout>

54
src/redux/UsersRedux.js Normal file
View File

@@ -0,0 +1,54 @@
import { createActions, createReducer } from 'reduxsauce';
import Immutable from 'seamless-immutable';
import _ from 'underscore';
import { getFetchingValue, getErrorValue } from '../services/Utils';
/* ------------- Types and Action Creators ------------- */
const { Types, Creators } = createActions({
getUsersAction: ['payload'],
getUsersSuccess: ['data'],
getUsersFailure: ['error']
});
export const UsersTypes = Types;
const UsersActions = Creators;
export default UsersActions;
/* ------------- Initial State ------------- */
export const INITIAL_STATE = Immutable({
usersDetail: [],
usersLoading: false,
userserror: {}
});
/* ------------- Selectors ------------- */
export const UsersSelectors = {
getUsersDetail: (state) => state.users.usersDetail
};
/* ------------- Reducers ------------- */
export const onGetUsersAction = (state, { payload }) =>
state.merge({
fetching: _.uniq([state.fetching, payload?.loader]),
error: getErrorValue(state?.error, payload?.loader)
});
export const onGetUsersSuccess = (state, { data }) =>
state.merge({
fetching: getFetchingValue(state.fetching, data?.loader),
error: getErrorValue(state?.error, data?.loader),
usersDetail: data.usersDetail
});
export const onGetUsersFailure = (state, { error }) =>
state.merge({
fetching: _.without(state.fetching, error?.loader),
error: { ...state.error, [error?.loader]: error?.error }
});
/* ------------- Hookup Reducers To Types ------------- */
export const usersReducer = createReducer(INITIAL_STATE, {
[Types.GET_USERS_ACTION]: onGetUsersAction,
[Types.GET_USERS_SUCCESS]: onGetUsersSuccess,
[Types.GET_USERS_FAILURE]: onGetUsersFailure
});

View File

@@ -1,11 +1,13 @@
import { combineReducers } from 'redux';
import { authReducer } from './AuthRedux';
import { warehouseReducer } from './WarehouseRedux';
import { usersReducer } from './UsersRedux';
// Combine all reducers.
const appReducer = combineReducers({
auth: authReducer,
warehouse: warehouseReducer
warehouse: warehouseReducer,
users: usersReducer
});
const rootReducer = (state, action) => {

30
src/sagas/Users.js Normal file
View File

@@ -0,0 +1,30 @@
import { AuthorizedAPI } from 'config';
import { takeLatest, call, put } from 'redux-saga/effects';
import UsersActions, { UsersTypes } from '../redux/UsersRedux';
import ApiServices from 'services/API/ApiServices';
export function* onRequestUsersData({ payload }) {
const response = yield call(
ApiServices[payload?.method],
AuthorizedAPI,
payload?.slug,
payload?.data
);
if (response?.status === 200) {
yield put(
UsersActions.getUsersSuccess({
loader: payload?.loader,
usersDetail: response?.data?.data
})
);
} else {
payload.onFailedUsersData(response.data.error);
yield put(
UsersActions.getUsersFailure({
loader: payload?.loader,
error: response?.data
})
);
}
}
export default [takeLatest(UsersTypes.GET_USERS_ACTION, onRequestUsersData)];

View File

@@ -1,10 +1,10 @@
import { all } from 'redux-saga/effects';
import AuthSaga from './Auth';
import WarehouseSaga from './Warehouse';
import UsersSaga from './Users';
export default function* rootSaga() {
yield all([...AuthSaga]);
yield all([...WarehouseSaga]);
yield all([...UsersSaga]);
}