feat/delete-item-warehouse (#78)

Delete item
Delete warehouse
Delete confirmation messages
Bonus: Full cover image

Co-authored-by: Llewellyn Dsouza <lledsouza2209@gmail.com>
This commit is contained in:
bluestreamlds
2022-03-04 16:27:53 +05:30
committed by GitHub
parent 5381f7d727
commit 8cccf1f034
11 changed files with 258 additions and 13 deletions

2
.gitignore vendored
View File

@@ -1,7 +1,7 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
node_modules
.DS_Store
# testing

View File

@@ -41,10 +41,11 @@ const StyledTableRow = styled(TableRow)(({ theme }) => ({
Row.propTypes = {
rowData: PropTypes.array,
tHeads: PropTypes.array,
editHandler: PropTypes.any
editHandler: PropTypes.any,
deleteHandler: PropTypes.any
};
function Row({ tHeads, rowData, editHandler }) {
function Row({ tHeads, rowData, editHandler, deleteHandler }) {
return (
<React.Fragment>
<StyledTableRow sx={{ '&odd > *': { borderBottom: 'unset' } }}>
@@ -68,6 +69,25 @@ function Row({ tHeads, rowData, editHandler }) {
>
EDIT
</MDButton>
<MDButton
size="small"
variant="contained"
color="error"
sx={{
textTransform: 'capitalize',
minWidth: '45px',
minHeight: '28px',
marginLeft: '10px',
boxShadow: 'none',
fontWeight: '500',
padding: '0'
}}
onClick={() => {
deleteHandler(rowData._id);
}}
>
DELETE
</MDButton>
</StyledTableCell>
{tHeads &&
tHeads
@@ -87,6 +107,7 @@ function EnhancedTable({
data,
tHeads,
editHandler,
deleteHandler,
filtersControl,
resetFilters
}) {
@@ -172,6 +193,7 @@ function EnhancedTable({
<Row
key={rowData._id}
editHandler={editHandler}
deleteHandler={deleteHandler}
rowData={rowData}
tHeads={tHeads}
/>
@@ -304,6 +326,7 @@ EnhancedTable.propTypes = {
data: PropTypes.array,
tHeads: PropTypes.array,
editHandler: PropTypes.any,
deleteHandler: PropTypes.any,
filtersControl: PropTypes.any,
resetFilters: PropTypes.any
};

View File

@@ -38,6 +38,7 @@ function AuthLayout({ header, title, description, illustration, children }) {
mt={2}
sx={{
backgroundImage: `url(${illustration})`,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center'
}}

View File

@@ -12,7 +12,9 @@ import {
DialogTitle,
DialogContent,
TextField,
DialogActions
DialogActions,
Button,
DialogContentText
} from '@mui/material';
import DashboardNavbar from 'components/DashboardNavbar';
import DashboardLayout from 'layouts/DashboardLayout';
@@ -319,6 +321,9 @@ const WarehouseNestedDetails = () => {
function EditWarehouseDetails() {
const { warehouseId } = useParams();
const navigate = useNavigate();
const navigateTo = (to) => {
navigate(to);
};
const warehouseData = useSelector(WarehouseSelectors.getWarehouseDetailById(warehouseId));
const inventoryTypes = useSelector(InventorySelectors.getInventoryDetail);
@@ -372,6 +377,14 @@ function EditWarehouseDetails() {
}
});
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
const handleDeleteAlertClose = () => {
setDeleteAlertOpen(false);
};
const handleDeleteAlertOpen = () => {
setDeleteAlertOpen(true);
};
return (
<>
<DashboardLayout>
@@ -516,7 +529,49 @@ function EditWarehouseDetails() {
/>
</Box>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<Grid item sx={{ textAlign: 'end' }} xs={12} sm={6} md={6}>
<MDButton
size="large"
color="error"
variant="outlined"
onClick={handleDeleteAlertOpen}
>
Delete Warehouse
</MDButton>
<Dialog
open={deleteAlertOpen}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
onClose={handleDeleteAlertClose}
>
<DialogTitle id="alert-dialog-title">Confirm Warehouse Delete</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete this warehouse?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleDeleteAlertClose}>
No
</Button>
<Button
onClick={() => {
dispatch(
WarehouseActions.deleteWarehouseAction({
loader: 'loading-request',
slug: '/warehouse/',
method: 'delete',
warehouseId: warehouseData._id,
navigateTo
})
);
handleDeleteAlertClose();
}}
>
Yes
</Button>
</DialogActions>
</Dialog>
<Box sx={{ marginTop: '30px' }}>
<ImageUploadSingle
heading="Upload Warehouse Image"

View File

@@ -14,7 +14,17 @@ import EnhancedTable from 'components/EnhancedTable';
import { useNavigate } from 'react-router-dom';
import WidgetActions from 'redux/WidgetRedux';
import { WidgetSelectors } from 'redux/WidgetRedux';
import { Grid, MenuItem, Select } from '@mui/material';
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Grid,
MenuItem,
Select
} from '@mui/material';
const tHeads = [
{ key: 'name', name: '' },
@@ -76,6 +86,14 @@ function ItemListing() {
);
}, []);
const [deleteAlertOpen, setDeleteAlertOpen] = React.useState(null);
const handleDeleteAlertClose = () => {
setDeleteAlertOpen(null);
};
const handleDeleteAlertOpen = (id) => {
setDeleteAlertOpen(id);
};
return (
<DashboardLayout>
<DashboardNavbar />
@@ -90,6 +108,53 @@ function ItemListing() {
/>
<MDBox px={5} py={3}>
<Dialog
open={deleteAlertOpen}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
onClose={handleDeleteAlertClose}
>
<DialogTitle id="alert-dialog-title">Confirm Delete</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete this item?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleDeleteAlertClose}>
No
</Button>
<Button
onClick={() => {
const refreshDispatch = () => {
dispatch(
ItemActions.itemRequest({
loader: 'loading-request',
slug: API.GET_ITEMS_BY_INVENTORY,
method: 'get',
page: page - 1,
perPage,
inventoryId,
family: sFam || pFam || null
})
);
};
dispatch(
ItemActions.deleteItemRequest({
loader: 'loading-request',
slug: '/item/',
method: 'delete',
itemId: deleteAlertOpen,
refreshDispatch
})
);
handleDeleteAlertClose();
}}
>
Yes
</Button>
</DialogActions>
</Dialog>
<EnhancedTable
count={count}
page={page}
@@ -99,6 +164,9 @@ function ItemListing() {
editHandler={(id) => {
navigateTo(`/setup/inventory/browse/${widgetName}/${inventoryId}/edit/${id}`);
}}
deleteHandler={(id) => {
handleDeleteAlertOpen(id);
}}
resetFilters={() => {
setPFam('');
setSFam('');

View File

@@ -20,7 +20,7 @@ function SetupHome() {
icon: <InventoryIcon width={96} height={96} color="#007AFF" />
},
{
name: 'User & Access',
name: 'User Access',
path: '/setup/users-access',
icon: <ProfileCircleIcon width={96} height={96} color="#007AFF" />
},
@@ -33,7 +33,7 @@ function SetupHome() {
return (
<DashboardLayout>
<DashboardNavbar />
<Breadcrumbs title="Setup Warehouse, Inventory, Users" route={[{ name: 'Home', path: '/home' }, { name: 'Setup' }]} />
<Breadcrumbs title="Warehouse Management System Setup" route={[{ name: 'Home', path: '/home' }, { name: 'Setup' }]} />
<TileBasic tiles={data} />
</DashboardLayout>
);

View File

@@ -221,7 +221,7 @@ function UserAccessScreen() {
route={[
{ name: 'Home', path: '/home' },
{ name: 'Setup', path: '/setup' },
{ name: 'Users and Access', path: '/setup/users-access' }
{ name: 'Users Access' }
]}
/>
<MDBox px={5} py={3}>

View File

@@ -12,6 +12,8 @@ const { Types, Creators } = createActions({
addItemSuccess: ['data'],
editItemRequest: ['payload'],
editItemSuccess: ['data'],
deleteItemRequest: ['payload'],
deleteItemSuccess: ['data'],
oneItemRequest: ['payload'],
oneItemSuccess: ['data']
});
@@ -91,6 +93,18 @@ export const onEditItemSuccess = (state, { data }) =>
item: null
});
export const onDeleteItemRequest = (state, { payload }) =>
state.merge({
fetching: _.uniq([...state.fetching, payload?.loader]),
error: getErrorValue(state?.error, payload?.loader)
});
export const onDeleteItemSuccess = (state, { data }) =>
state.merge({
fetching: getFetchingValue(state.fetching, data?.loader),
error: getErrorValue(state?.error, data?.loader)
});
export const onItemFailure = (state, { error }) =>
state.merge({
fetching: _.without(state.fetching, error?.loader),
@@ -106,6 +120,8 @@ export const itemReducer = createReducer(INITIAL_STATE, {
[Types.ADD_ITEM_SUCCESS]: onAddItemSuccess,
[Types.EDIT_ITEM_REQUEST]: onEditItemRequest,
[Types.EDIT_ITEM_SUCCESS]: onEditItemSuccess,
[Types.DELETE_ITEM_REQUEST]: onDeleteItemRequest,
[Types.DELETE_ITEM_SUCCESS]: onDeleteItemSuccess,
[Types.ONE_ITEM_REQUEST]: onOneItemRequest,
[Types.ONE_ITEM_SUCCESS]: onOneItemSuccess
});

View File

@@ -15,7 +15,10 @@ const { Types, Creators } = createActions({
editWarehouseAction: ['payload'],
editWarehouseSuccess: ['data'],
editWarehouseFailure: ['error']
editWarehouseFailure: ['error'],
deleteWarehouseAction: ['payload'],
deleteWarehouseSuccess: ['data']
});
export const WarehouseTypes = Types;
@@ -96,6 +99,21 @@ export const onEditWarehouseSuccess = (state, { data }) =>
]
});
export const onDeleteWarehouseAction = (state, { payload }) =>
state.merge({
fetching: _.uniq([state.fetching, payload?.loader]),
error: getErrorValue(state?.error, payload?.loader)
});
export const onDeleteWarehouseSuccess = (state, { data }) =>
state.merge({
fetching: getFetchingValue(state.fetching, data?.loader),
error: getErrorValue(state?.error, data?.loader),
warehouseDetail: data?.deletedWarehouseID
? [...state.warehouseDetail.filter((x) => x._id !== data?.deletedWarehouseID)]
: state.warehouseDetail
});
export const onEditWarehouseFailure = (state, { error }) =>
state.merge({
fetching: _.without(state.fetching, error?.loader),
@@ -113,5 +131,7 @@ export const warehouseReducer = createReducer(INITIAL_STATE, {
[Types.EDIT_WAREHOUSE_ACTION]: onEditWarehouseAction,
[Types.EDIT_WAREHOUSE_SUCCESS]: onEditWarehouseSuccess,
[Types.EDIT_WAREHOUSE_FAILURE]: onEditWarehouseFailure
[Types.EDIT_WAREHOUSE_FAILURE]: onEditWarehouseFailure,
[Types.DELETE_WAREHOUSE_ACTION]: onDeleteWarehouseAction,
[Types.DELETE_WAREHOUSE_SUCCESS]: onDeleteWarehouseSuccess
});

View File

@@ -159,9 +159,40 @@ export function* onEditRequestItem({ payload }) {
}
}
export function* onDeleteRequestItem({ payload }) {
const response = yield call(
ApiServices[payload?.method],
AuthorizedAPI,
payload?.slug + payload?.itemId
);
if (response?.status === 200) {
toast.success(`Successfully deleted item`, {
theme: 'colored'
});
payload.refreshDispatch();
yield put(
ItemActions.deleteItemSuccess({
loader: payload?.loader,
item: response?.data?.data
})
);
} else {
toast.error('Failed to delete item', {
theme: 'colored'
});
yield put(
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)
takeEvery(ItemTypes.EDIT_ITEM_REQUEST, onEditRequestItem),
takeEvery(ItemTypes.DELETE_ITEM_REQUEST, onDeleteRequestItem)
];

View File

@@ -112,8 +112,39 @@ export function* onRequestEditWarehouse({ payload }) {
}
}
export function* onRequestDeleteWarehouse({ payload }) {
const response = yield call(
ApiServices[payload?.method],
AuthorizedAPI,
payload?.slug + payload?.warehouseId
);
if (response?.status === 200) {
toast.success('Warehouse deleted successfully', {
theme: 'colored'
});
payload.navigateTo('/setup/warehouse');
yield put(
WarehouseActions.deleteWarehouseSuccess({
loader: payload?.loader,
deletedWarehouseID: payload?.warehouseId
})
);
} else {
toast.error('Failed to delete warehouse', {
theme: 'colored'
});
yield put(
WarehouseActions.editWarehouseFailure({
loader: payload?.loader,
error: response?.data
})
);
}
}
export default [
takeLatest(WarehouseTypes.WAREHOUSE_DATA_ACTION, onRequestWarehouseData),
takeLatest(WarehouseTypes.CREATE_WAREHOUSE_ACTION, onRequestCreateWarehouse),
takeLatest(WarehouseTypes.EDIT_WAREHOUSE_ACTION, onRequestEditWarehouse)
takeLatest(WarehouseTypes.EDIT_WAREHOUSE_ACTION, onRequestEditWarehouse),
takeLatest(WarehouseTypes.DELETE_WAREHOUSE_ACTION, onRequestDeleteWarehouse)
];