Skip to content

Commit

Permalink
admin can delete a product
Browse files Browse the repository at this point in the history
  • Loading branch information
JaberHPranto committed Jul 12, 2021
1 parent 5789299 commit f19048d
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 17 deletions.
90 changes: 90 additions & 0 deletions client/src/components/Ecommerce/Screen/ProductListScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, { useEffect } from 'react'
import { Button, Col, Row, Table } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import { LinkContainer } from 'react-router-bootstrap'
import { deleteProduct, fetchProducts } from '../../../redux/actions/productActions'
import Loader from '../Loader'
import Message from '../Message'
import { toastErrorMessage } from '../ToastMessage'

function UserList({history}) {

const dispatch = useDispatch()

const { userInfo: { user } } = useSelector(state => state.userLogin)

const productList = useSelector(state => state.productList)
const { loading, error, products } = productList
const productDelete = useSelector(state => state.productDelete)
const { loading:loadingDelete, error:errorDelete, success:successDelete } = productDelete

useEffect(() => {
if (user && user.isAdmin) {
dispatch(fetchProducts())
} else {
history.push("/login")
}
}, [dispatch,history,user,successDelete])

const handleDelete = (id) => {
if (window.confirm('Are you sure you want to delete this user ?')) {
dispatch(deleteProduct(id))
if(!errorDelete)
toastErrorMessage("User deleted")
}
}
const handleCreateProduct= () => {}

return (
<>
<Row className="align-items-center">
<Col>
<h1>Products</h1>
</Col>
<Col className="text-right">
<Button className="my-3 block" style={{float: 'right'}}><i className="fas fa-plus" onClick={handleCreateProduct}></i> Create Product</Button>
</Col>
</Row>

{loadingDelete && <Loader />}
{errorDelete && <Message variant='danger'>{errorDelete}</Message>}

{loading ? <Loader /> : error ? <Message variant='danger'>{error}</Message> : (
<>
<Table striped bordered hover>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Category</th>
<th>Count In Stock</th>
</tr>
</thead>
<tbody>
{products.map(product=>(
<tr key={product._id}>
<td>{product._id}</td>
<td>{product.name}</td>
<td><span style={{fontSize:'1.5rem',marginRight:'0.1rem'}}></span>&nbsp;{product.price}</td>
<td>{product.category}</td>
<td>{product.countInStock}</td>
<td>
<LinkContainer to={`users/${product._id}/edit`}>
<Button ><i className='fas fa-edit'></i></Button>
</LinkContainer>
</td>
<td>
<Button variant='light' onClick={()=>handleDelete(product._id)}><i className='fas fa-trash'></i></Button>
</td>
</tr>
))}
</tbody>
</Table>
</>
)}
</>
)
}

export default UserList
6 changes: 5 additions & 1 deletion client/src/constants/productConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ export const PRODUCT_DETAILS_FAIL = "PRODUCT_DETAILS_FAIL"
export const PRODUCT_CREATE_REVIEW_REQUEST = "PRODUCT_CREATE_REVIEW_REQUEST"
export const PRODUCT_CREATE_REVIEW_SUCCESS = "PRODUCT_CREATE_REVIEW_SUCCESS"
export const PRODUCT_CREATE_REVIEW_FAIL = "PRODUCT_CREATE_REVIEW_FAIL"
export const PRODUCT_CREATE_REVIEW_RESET = "PRODUCT_CREATE_REVIEW_RESET"
export const PRODUCT_CREATE_REVIEW_RESET = "PRODUCT_CREATE_REVIEW_RESET"

export const PRODUCT_DELETE_REQUEST = "PRODUCT_DELETE_REQUEST"
export const PRODUCT_DELETE_SUCCESS = "PRODUCT_DELETE_SUCCESS"
export const PRODUCT_DELETE_FAIL = "PRODUCT_DELETE_FAIL"
2 changes: 2 additions & 0 deletions client/src/pages/EcommercePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import LoginScreen from '../components/Ecommerce/Screen/LoginScreen';
import PasswordResetScreen from '../components/Ecommerce/Screen/PasswordResetScreen';
import PaymentScreen from "../components/Ecommerce/Screen/PaymentScreen";
import PlaceOrderScreen from "../components/Ecommerce/Screen/PlaceOrderScreen";
import ProductListScreen from "../components/Ecommerce/Screen/ProductListScreen";
import ProductScreen from '../components/Ecommerce/Screen/ProductScreen';
import ProfileScreen from '../components/Ecommerce/Screen/ProfileScreen';
import RegisterScreen from '../components/Ecommerce/Screen/RegisterScreen';
Expand All @@ -33,6 +34,7 @@ function EcommercePage() {
<Route path="/reset-password/:resetToken" component={PasswordResetScreen} />
<Route path="/profile" component={ProfileScreen} />
<Route path="/admin/userlist" component={UserList} />
<Route path="/admin/productlist" component={ProductListScreen} />
<Route path="/product/:id" component={ProductScreen} />
<Route path="/cart/:id?" component={CartScreen} />
<Route path="/shipping" component={ShippingScreen} />
Expand Down
38 changes: 37 additions & 1 deletion client/src/redux/actions/productActions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from 'axios';
import { PRODUCT_CREATE_REVIEW_FAIL, PRODUCT_CREATE_REVIEW_REQUEST, PRODUCT_CREATE_REVIEW_SUCCESS, PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from '../../constants/productConstants';
import { PRODUCT_CREATE_REVIEW_FAIL, PRODUCT_CREATE_REVIEW_REQUEST, PRODUCT_CREATE_REVIEW_SUCCESS, PRODUCT_DELETE_FAIL, PRODUCT_DELETE_REQUEST, PRODUCT_DELETE_SUCCESS, PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from '../../constants/productConstants';

// @ GET products
export const fetchProducts = (keyword='',pageNumber='') => async (dispatch) => {
Expand Down Expand Up @@ -73,4 +73,40 @@ export const createProductReview = (productId,review) => async (dispatch,getStat
})
}

}

// Delete products
export const deleteProduct = (id) => async (dispatch,getState) => {

try {
dispatch({
type:PRODUCT_DELETE_REQUEST
})

const { userLogin: { userInfo } } = getState()


const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}

await axios.delete(`/api/products/${id}`,config)

dispatch({
type: PRODUCT_DELETE_SUCCESS,
})

} catch (error) {
console.log(error);
dispatch({
type: PRODUCT_DELETE_FAIL,
payload: error.response && error.response.data.message ? error.response.data.message : error.message

})

}

}
18 changes: 17 additions & 1 deletion client/src/redux/reducers/productReducers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PRODUCT_CREATE_REVIEW_FAIL, PRODUCT_CREATE_REVIEW_REQUEST, PRODUCT_CREATE_REVIEW_RESET, PRODUCT_CREATE_REVIEW_SUCCESS, PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from '../../constants/productConstants'
import { PRODUCT_CREATE_REVIEW_FAIL, PRODUCT_CREATE_REVIEW_REQUEST, PRODUCT_CREATE_REVIEW_RESET, PRODUCT_CREATE_REVIEW_SUCCESS, PRODUCT_DELETE_FAIL, PRODUCT_DELETE_REQUEST, PRODUCT_DELETE_SUCCESS, PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from '../../constants/productConstants'

export const productListReducer = (state = { products: [] }, action) => {
switch (action.type) {
Expand Down Expand Up @@ -46,6 +46,22 @@ export const productCreateReviewReducer = (state = {}, action) => {
case PRODUCT_CREATE_REVIEW_RESET:
return {}

default:
return state
}
}

export const productDeleteReducer = (state = {}, action) => {
switch (action.type) {
case PRODUCT_DELETE_REQUEST:
return { loading: true }

case PRODUCT_DELETE_SUCCESS:
return { loading: false,success:true}

case PRODUCT_DELETE_FAIL:
return { loading: false, error: action.payload }

default:
return state
}
Expand Down
2 changes: 0 additions & 2 deletions client/src/redux/reducers/userReducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const userLoginReducer = (state = {}, action) => {
}
}


export const userRegisterReducer = (state = {}, action) => {
switch (action.type) {
case USER_REGISTER_REQUEST:
Expand All @@ -37,7 +36,6 @@ export const userRegisterReducer = (state = {}, action) => {
}
}


export const userDetailsReducer = (state = {user:{}}, action) => {
switch (action.type) {
case USER_DETAILS_REQUEST:
Expand Down
8 changes: 4 additions & 4 deletions client/src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import thunk from "redux-thunk";
import { cartReducer } from "./redux/reducers/cartReducers";
import { orderCreateReducer } from "./redux/reducers/orderReducers";
import {
productCreateReviewReducer,
productDetailsReducer,
productCreateReviewReducer, productDeleteReducer, productDetailsReducer,
productListReducer
} from "./redux/reducers/productReducers";
import {
Expand All @@ -17,14 +16,15 @@ import {
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
productCreateReview: productCreateReviewReducer,
productDelete: productDeleteReducer,
userLogin: userLoginReducer,
userRegister: userRegisterReducer,
userDetails: userDetailsReducer,
userProfileUpdate: userProfileUpdateReducer,
userList: userListReducer,
userDelete: userDeleteReducer,
productCreateReview: productCreateReviewReducer,
cart: cartReducer,
orderCreate: orderCreateReducer,
});

Expand Down
12 changes: 12 additions & 0 deletions server/controller/productController.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,16 @@ export const createProductReview = asyncHandler(async (req, res) => {
res.status(404)
throw new Error("Product not found")
}
})


// getting a product @route -> api/products/:id
export const deleteProductById = (async (req, res) => {
try {
const product = await Product.findById(req.params.id)
await product.remove()
res.status(200).json({message:'Product deleted successfully'})
} catch(err){
res.status(404).json({message:"No product found"})
}
})
5 changes: 3 additions & 2 deletions server/routes/productRoutes.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import express from 'express'
import { createProductReview, getProductById, getProducts } from '../controller/productController.js'
import { isLoggedIn } from '../middlewares/authMiddleware.js'
import { createProductReview, deleteProductById, getProductById, getProducts } from '../controller/productController.js'
import { isAdmin, isLoggedIn } from '../middlewares/authMiddleware.js'

const router = express.Router()

router.get("/",getProducts)
router.get("/:id", getProductById)
router.post("/:id/reviews",isLoggedIn,createProductReview)
router.delete("/:id",isLoggedIn, isAdmin,deleteProductById)

export default router
16 changes: 10 additions & 6 deletions server/routes/userRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { isAdmin, isLoggedIn } from '../middlewares/authMiddleware.js'

const router = express.Router()

router.get("/", isLoggedIn, isAdmin, getUsers)
router.delete("/:id",isLoggedIn, isAdmin, deleteUser)
router.get("/:id",isLoggedIn, isAdmin, getUserById)
router.put("/:id",isLoggedIn,isAdmin,updateUser)

router.post("/login", authUser)
router.post("/register",registerUser)
router.post("/forget-password", forgetPassword)
router.put("/reset-password/:resetToken",resetPassword)
router.put("/reset-password/:resetToken", resetPassword)

router.route("/profile").get(isLoggedIn, getUserProfile).put(isLoggedIn, updateUserProfile)

router.get("/", isLoggedIn, isAdmin, getUsers)
// router.delete("/:id",isLoggedIn, isAdmin, deleteUser)
// router.get("/:id",isLoggedIn, isAdmin, getUserById)
// router.put("/:id", isLoggedIn, isAdmin, updateUser)
router.route("/:id").get(isLoggedIn,isAdmin,getUserById).put(isLoggedIn,isAdmin,updateUser).delete(isLoggedIn,isAdmin,deleteUser)





export default router

0 comments on commit f19048d

Please sign in to comment.