Skip to content

Commit

Permalink
admin can now update/create a product
Browse files Browse the repository at this point in the history
  • Loading branch information
JaberHPranto committed Jul 12, 2021
1 parent d751b14 commit f161c91
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 16 deletions.
142 changes: 142 additions & 0 deletions client/src/components/Ecommerce/Screen/ProductEditScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { useEffect, useState } from 'react'
import { Button, Form } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { PRODUCT_UPDATE_RESET } from '../../../constants/productConstants'
import { fetchProductById, updateProduct } from '../../../redux/actions/productActions'
import FormContainer from '../FormContainer'
import Loader from '../Loader'
import Message from '../Message'
import { toastSuccessMessage } from '../ToastMessage'

const ProductEditScreen = ({ match, history }) => {
const productId = match.params.id

const [name, setName] = useState('')
const [description, setDescription] = useState('')
const [category, setCategory] = useState('')
const [price, setPrice] = useState(0)
const [countInStock, setCountInStock] = useState(0)
const [image, setImage] = useState('')

const dispatch = useDispatch()

const productDetails = useSelector((state) => state.productDetails)
const { loading, error, product } = productDetails
const productUpdate = useSelector((state) => state.productUpdate)
const { loading:loadingUpdate, error:errorUpdate, success:successUpdate } = productUpdate


useEffect(() => {
if (successUpdate) {
dispatch({ type: PRODUCT_UPDATE_RESET })
toastSuccessMessage("Product Updated")
history.push("/admin/productlist")

} else {
if (!product.name || product._id !== productId) {
dispatch(fetchProductById(productId))
} else {
setName(product.name)
setDescription(product.description)
setCategory(product.category)
setImage(product.image)
setPrice(product.price)
setCountInStock(product.countInStock)
}
}

}, [dispatch,product,productId,successUpdate,history])

const submitHandler = (e) => {
e.preventDefault()
dispatch(updateProduct({
_id: product._id,name,description,image,category,price,countInStock
}))
}

return (
<>
<Link to='/admin/productlist' className='btn btn-light my-3'>
Go Back
</Link>
<FormContainer>
<h1>Edit Product</h1>
{loadingUpdate && <Loader />}
{errorUpdate && <Message variant='danger'>{errorUpdate}</Message>}
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<Form onSubmit={submitHandler}>
<Form.Group controlId='name'>
<Form.Label>Name</Form.Label>
<Form.Control
type='name'
placeholder='Enter name'
value={name}
onChange={(e) => setName(e.target.value)}
></Form.Control>
</Form.Group>

<Form.Group controlId='description'>
<Form.Label>Description</Form.Label>
<Form.Control
type='text'
placeholder='Write Description'
value={description}
onChange={(e) => setDescription(e.target.value)}
></Form.Control>
</Form.Group>

<Form.Group controlId='category'>
<Form.Label>Category</Form.Label>
<Form.Control
type='text'
placeholder='Enter Category'
value={category}
onChange={(e) => setCategory(e.target.value)}
></Form.Control>
</Form.Group>

<Form.Group controlId='image'>
<Form.Label>Image</Form.Label>
<Form.Control
type='text'
placeholder='Enter image url'
value={image}
onChange={(e) => setImage(e.target.value)}
></Form.Control>
</Form.Group>

<Form.Group controlId='price'>
<Form.Label>Price</Form.Label>
<Form.Control
type='number'
placeholder='Enter Price'
value={price}
onChange={(e) => setPrice(e.target.value)}
></Form.Control>
</Form.Group>

<Form.Group controlId='countInStock'>
<Form.Label>Count In Stock</Form.Label>
<Form.Control
type='number'
placeholder='Enter Stock'
value={countInStock}
onChange={(e) => setCountInStock(e.target.value)}
></Form.Control>
</Form.Group>
<Button type='submit' variant='primary'>
Update
</Button>
</Form>
)}
</FormContainer>
</>
)
}

export default ProductEditScreen
37 changes: 26 additions & 11 deletions client/src/components/Ecommerce/Screen/ProductListScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ 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 { PRODUCT_CREATE_RESET } from '../../../constants/productConstants'
import { createProduct, deleteProduct, fetchProducts } from '../../../redux/actions/productActions'
import Loader from '../Loader'
import Message from '../Message'
import { toastErrorMessage } from '../ToastMessage'
Expand All @@ -15,25 +16,37 @@ function UserList({history}) {

const productList = useSelector(state => state.productList)
const { loading, error, products } = productList

const productCreate = useSelector(state => state.productCreate)
const { loading: loadingCreate, error: errorCreate, success: successCreate, product:createdProduct } = productCreate
const productDelete = useSelector(state => state.productDelete)
const { loading:loadingDelete, error:errorDelete, success:successDelete } = productDelete


useEffect(() => {
if (user && user.isAdmin) {
dispatch({ type: PRODUCT_CREATE_RESET })

if (!user.isAdmin)
history.push('/login')

if (successCreate) {
history.push(`/admin/product/${createdProduct._id}/edit`)
}
else {
dispatch(fetchProducts())
} else {
history.push("/login")
}
}, [dispatch,history,user,successDelete])
}, [dispatch,history,user,successDelete,successCreate,createdProduct])

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

return (
<>
Expand All @@ -42,10 +55,12 @@ function UserList({history}) {
<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>
<Button className="my-3 block" style={{float: 'right'}} onClick={handleCreateProduct}><i className="fas fa-plus" onClick={handleCreateProduct}></i> Create Product</Button>
</Col>
</Row>

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

Expand All @@ -58,7 +73,7 @@ function UserList({history}) {
<th>Name</th>
<th>Price</th>
<th>Category</th>
<th>Count In Stock</th>
<th>In Stock</th>
</tr>
</thead>
<tbody>
Expand All @@ -70,7 +85,7 @@ function UserList({history}) {
<td>{product.category}</td>
<td>{product.countInStock}</td>
<td>
<LinkContainer to={`users/${product._id}/edit`}>
<LinkContainer to={`/admin/product/${product._id}/edit`}>
<Button ><i className='fas fa-edit'></i></Button>
</LinkContainer>
</td>
Expand Down
12 changes: 11 additions & 1 deletion client/src/constants/productConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@ 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"
export const PRODUCT_DELETE_FAIL = "PRODUCT_DELETE_FAIL"

export const PRODUCT_CREATE_REQUEST = "PRODUCT_CREATE_REQUEST"
export const PRODUCT_CREATE_SUCCESS = "PRODUCT_CREATE_SUCCESS"
export const PRODUCT_CREATE_FAIL = "PRODUCT_CREATE_FAIL"
export const PRODUCT_CREATE_RESET = "PRODUCT_CREATE_RESET"

export const PRODUCT_UPDATE_REQUEST = "PRODUCT_UPDATE_REQUEST"
export const PRODUCT_UPDATE_SUCCESS = "PRODUCT_UPDATE_SUCCESS"
export const PRODUCT_UPDATE_FAIL = "PRODUCT_UPDATE_FAIL"
export const PRODUCT_UPDATE_RESET = "PRODUCT_UPDATE_RESET"
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 ProductEditScreen from "../components/Ecommerce/Screen/ProductEditScreen";
import ProductListScreen from "../components/Ecommerce/Screen/ProductListScreen";
import ProductScreen from '../components/Ecommerce/Screen/ProductScreen';
import ProfileScreen from '../components/Ecommerce/Screen/ProfileScreen';
Expand All @@ -35,6 +36,7 @@ function EcommercePage() {
<Route path="/profile" component={ProfileScreen} />
<Route path="/admin/userlist" component={UserList} />
<Route path="/admin/productlist" component={ProductListScreen} />
<Route path="/admin/product/:id/edit" component={ProductEditScreen} />
<Route path="/product/:id" component={ProductScreen} />
<Route path="/cart/:id?" component={CartScreen} />
<Route path="/shipping" component={ShippingScreen} />
Expand Down
76 changes: 75 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_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';
import { PRODUCT_CREATE_FAIL, PRODUCT_CREATE_REQUEST, PRODUCT_CREATE_REVIEW_FAIL, PRODUCT_CREATE_REVIEW_REQUEST, PRODUCT_CREATE_REVIEW_SUCCESS, PRODUCT_CREATE_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, PRODUCT_UPDATE_FAIL, PRODUCT_UPDATE_REQUEST, PRODUCT_UPDATE_SUCCESS } from '../../constants/productConstants';

// @ GET products
export const fetchProducts = (keyword='',pageNumber='') => async (dispatch) => {
Expand Down Expand Up @@ -109,4 +109,78 @@ export const deleteProduct = (id) => async (dispatch,getState) => {

}

}

// Create products
export const createProduct = () => async (dispatch,getState) => {

try {
dispatch({
type:PRODUCT_CREATE_REQUEST
})

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


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

const { data } = await axios.post(`/api/products`,{},config)

dispatch({
type: PRODUCT_CREATE_SUCCESS,
payload:data
})

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

})

}

}

// Update Products
export const updateProduct = (product) => async (dispatch,getState) => {

try {
dispatch({
type:PRODUCT_UPDATE_REQUEST
})

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


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

const { data } = await axios.put(`/api/products/${product._id}`,product,config)

dispatch({
type: PRODUCT_UPDATE_SUCCESS,
payload:data
})

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

})

}

}
Loading

0 comments on commit f161c91

Please sign in to comment.