Skip to content

Commit eec43ea

Browse files
author
WebDeveloperGuide
committed
Add/Update/Delete Product, Get Products functionality added, Front end basic setup added.
1 parent 26f1869 commit eec43ea

29 files changed

+28191
-26
lines changed

web_admin/package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web_admin/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"jquery": "^3.6.0",
1111
"react": "^17.0.2",
1212
"react-dom": "^17.0.2",
13+
"react-paginate": "^8.1.2",
1314
"react-redux": "^7.2.6",
1415
"react-router-dom": "^5.3.0",
1516
"react-scripts": "5.0.0",

web_admin/public/assets/js/dashboard.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,7 @@
185185
legendCallback: function (chart) {
186186
var text = [];
187187
text.push('<div class="chartjs-legend"><ul>');
188-
for (var i = 0; i < chart.data.datasets.length; i++) {
189-
console.log(chart.data.datasets[i]); // see what's inside the obj.
188+
for (var i = 0; i < chart.data.datasets.length; i++) {
190189
text.push('<li>');
191190
text.push('<span style="background-color:' + chart.data.datasets[i].borderColor + '">' + '</span>');
192191
text.push(chart.data.datasets[i].label);
@@ -431,7 +430,6 @@
431430
var text = [];
432431
text.push('<div class="chartjs-legend"><ul>');
433432
for (var i = 0; i < chart.data.datasets.length; i++) {
434-
console.log(chart.data.datasets[i]); // see what's inside the obj.
435433
text.push('<li class="text-muted text-small">');
436434
text.push('<span style="background-color:' + chart.data.datasets[i].borderColor + '">' + '</span>');
437435
text.push(chart.data.datasets[i].label);

web_admin/src/App.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Register from "./components/pages/Register";
44
import Dashboard from "./components/pages/Dashboard";
55
import Products from "./components/pages/product/Products";
66
import AddProduct from "./components/pages/product/AddProduct";
7+
import EditProduct from "./components/pages/product/EditProduct";
78
import Categories from "./components/pages/category/Categories";
89
import Orders from "./components/pages/order/Orders";
910
import Users from "./components/pages/user/Users";
@@ -25,7 +26,8 @@ function App() {
2526
<AuthRoute path="/register" component={Register} />
2627
<PrivateRouter path="/dashboard" component={Dashboard} />
2728
<PrivateRouter path="/products" component={Products} />
28-
<PrivateRouter path="/add/product" component={AddProduct} />
29+
<PrivateRouter path="/product/add" component={AddProduct} />
30+
<PrivateRouter path="/product/edit/:id" component={EditProduct} />
2931
<PrivateRouter path="/categories" component={Categories} />
3032
<PrivateRouter path="/orders" component={Orders} />
3133
<PrivateRouter path="/users" component={Users} />

web_admin/src/PrivateRouter.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ function PrivateRouter({ component: Component, ...rest }) {
1515
{...rest}
1616
component={(props) => {
1717
if (isAdmin === 1) {
18-
return <Component {...props} />;
18+
//If page is on home page with only / then redirect to dashboard route
19+
return (props.location.pathname === '/') ?
20+
<Redirect to={`/dashboard`} /> :
21+
<Component {...props} />;
1922
} else {
2023
return <Redirect to={`/login`} />;
2124
}

web_admin/src/components/pages/product/AddProduct.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {useState} from 'react';
22
import {useDispatch,useSelector} from 'react-redux';
3+
import {Link} from 'react-router-dom';
34
import Header from '../../Header';
45
import Sidebar from '../../Sidebar';
56
import Footer from '../../Footer';
@@ -185,7 +186,7 @@ const AddProduct = () => {
185186
</div>
186187
<div className="text-center">
187188
<button type="submit" className="btn btn-primary me-2">Submit</button>
188-
<button className="btn btn-light">Cancel</button>
189+
<Link to="/products"><button className="btn btn-light">Cancel</button></Link>
189190
</div>
190191
</form>
191192
</div>
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import {useState, useEffect} from 'react';
2+
import {useDispatch,useSelector} from 'react-redux';
3+
import {Link} from 'react-router-dom';
4+
import Header from '../../Header';
5+
import Sidebar from '../../Sidebar';
6+
import Footer from '../../Footer';
7+
import {editProduct} from '../../../redux/actions/ProductActions';
8+
import {updateProduct} from '../../../redux/actions/ProductActions';
9+
import { PRODUCT_UPDATE_RESET } from "../../../redux/constants/ProductConstants";
10+
import { toast } from "react-toastify";
11+
import {ToastObjects} from '../../../redux/actions/toastObject';
12+
13+
const EditProduct = ({match}) => {
14+
const productId = match.params.id;
15+
const [submitted, setSubmitted] = useState(false);
16+
const dispatch = useDispatch();
17+
18+
const productEdit = useSelector((state) => state.productEdit);
19+
const { loading, error, product } = productEdit;
20+
21+
const productUpdate = useSelector((state) => state.productUpdate);
22+
const {
23+
loading: loadingUpdate,
24+
error: errorUpdate,
25+
success: successUpdate,
26+
} = productUpdate;
27+
28+
const [formState,setFormState] = useState({
29+
values:{}
30+
});
31+
32+
useEffect(() => {
33+
setFormState({values:{}})
34+
if (successUpdate) {
35+
dispatch({ type: PRODUCT_UPDATE_RESET });
36+
toast.success("Product updated successfully", ToastObjects);
37+
} else {
38+
if (!product.title || product._id !== productId) {
39+
dispatch(editProduct(productId));
40+
} else {
41+
setFormState({values:product})
42+
}
43+
}
44+
45+
}, [product, dispatch, productId, successUpdate]);
46+
47+
48+
const handleChange = (event) => {
49+
setFormState(formState =>({
50+
...formState,
51+
values:{
52+
...formState.values,
53+
[event.target.name]:
54+
event.target.type === 'checkbox'
55+
? event.target.checked
56+
: event.target.value
57+
}
58+
59+
}));
60+
}
61+
62+
const handleSubmit = (e) => {
63+
e.preventDefault();
64+
setSubmitted(true);
65+
const { title, description, image } = formState.values;
66+
if (title && description && image) {
67+
dispatch(updateProduct(formState.values));
68+
setSubmitted(false);
69+
}
70+
}
71+
72+
return(
73+
<>
74+
<div className="container-scroller">
75+
<Header/>
76+
<div className="container-fluid page-body-wrapper">
77+
<Sidebar/>
78+
<div className="main-panel">
79+
<div className="content-wrapper">
80+
<div className="row">
81+
<div className="col-12 grid-margin">
82+
<div className="card">
83+
<div className="card-body">
84+
<h4 className="card-title">Edit Product</h4>
85+
<form className="form-sample" onSubmit={handleSubmit}>
86+
<p className="card-description">
87+
</p>
88+
<div className="row">
89+
<div className="col-md-6">
90+
<div className="form-group row">
91+
<label className="col-sm-3 col-form-label">Title</label>
92+
<div className="col-sm-9">
93+
<input type="text" className={'form-control form-control-lg' + (submitted && !formState.values.title ? ' is-invalid' : '')}
94+
name="title"
95+
onChange={handleChange}
96+
value={formState.values.title || ''}
97+
/>
98+
{submitted && !formState.values.title &&
99+
<div className="inline-errormsg">Title is required</div>
100+
}
101+
</div>
102+
</div>
103+
</div>
104+
</div>
105+
<div className="row">
106+
<div className="col-md-6">
107+
<div className="form-group row">
108+
<label className="col-sm-3 col-form-label">Description</label>
109+
<div className="col-sm-9">
110+
<textarea rows={5} cols={5} className={'form-control form-control-lg' + (submitted && !formState.values.title ? ' is-invalid' : '')}
111+
name="description"
112+
onChange={handleChange}
113+
value={formState.values.description || ''}
114+
/>
115+
{submitted && !formState.values.description &&
116+
<div className="inline-errormsg">Description is required</div>
117+
}
118+
</div>
119+
</div>
120+
</div>
121+
</div>
122+
<div className="row">
123+
<div className="col-md-6">
124+
<div className="form-group row">
125+
<label className="col-sm-3 col-form-label">Image URL</label>
126+
<div className="col-sm-9">
127+
<input type="text" className={'form-control form-control-lg' + (submitted && !formState.values.image ? ' is-invalid' : '')}
128+
name="image"
129+
onChange={handleChange}
130+
value={formState.values.image || ''}
131+
/>
132+
{submitted && !formState.values.image &&
133+
<div className="inline-errormsg">Image is required</div>
134+
}
135+
</div>
136+
</div>
137+
</div>
138+
</div>
139+
<div className="row">
140+
<div className="col-md-6">
141+
<div className="form-group row">
142+
<label className="col-sm-3 col-form-label">Size</label>
143+
<div className="col-sm-9">
144+
<input type="text" className="form-control form-control-lg"
145+
name="size"
146+
onChange={handleChange}
147+
value={formState.values.size || ''}
148+
/>
149+
</div>
150+
</div>
151+
</div>
152+
</div>
153+
<div className="row">
154+
<div className="col-md-6">
155+
<div className="form-group row">
156+
<label className="col-sm-3 col-form-label">Color</label>
157+
<div className="col-sm-9">
158+
<input type="text" className="form-control form-control-lg"
159+
name="color"
160+
onChange={handleChange}
161+
value={formState.values.color || ''}
162+
/>
163+
</div>
164+
</div>
165+
</div>
166+
</div>
167+
<div className="row">
168+
<div className="col-md-6">
169+
<div className="form-group row">
170+
<label className="col-sm-3 col-form-label">Price</label>
171+
<div className="col-sm-9">
172+
<input type="number" className="form-control form-control-lg"
173+
name="price"
174+
onChange={handleChange}
175+
value={formState.values.price || ''}
176+
/>
177+
</div>
178+
</div>
179+
</div>
180+
</div>
181+
182+
<div className="row">
183+
<div className="col-md-6">
184+
<div className="form-group row">
185+
<label className="col-sm-3 col-form-label">Category</label>
186+
<div className="col-sm-9">
187+
<select className="form-control" name="category" multiple>
188+
<option value="man">Man</option>
189+
<option value="woman">Woman</option>
190+
</select>
191+
</div>
192+
</div>
193+
</div>
194+
</div>
195+
<div className="row">
196+
<div className="col-md-6">
197+
<div className="form-group row">
198+
<label className="col-sm-3 col-form-label">Stock</label>
199+
<div className="col-sm-9">
200+
<input type="text" className={'form-control form-control-lg' + (submitted && !formState.values.stock ? ' is-invalid' : '')}
201+
name="stock"
202+
onChange={handleChange}
203+
value={formState.values.stock || ''}
204+
/>
205+
{submitted && !formState.values.stock &&
206+
<div className="inline-errormsg">Stock is required</div>
207+
}
208+
</div>
209+
</div>
210+
</div>
211+
</div>
212+
<div className="text-center">
213+
<button type="submit" className="btn btn-primary me-2">Update</button>
214+
<Link to="/products"><button className="btn btn-light">Cancel</button></Link>
215+
</div>
216+
</form>
217+
</div>
218+
</div>
219+
</div>
220+
</div>
221+
</div>
222+
<Footer/>
223+
</div>
224+
</div>
225+
</div>
226+
</>
227+
)
228+
}
229+
230+
export default EditProduct;

web_admin/src/components/pages/product/Product.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,38 @@ import {Link} from 'react-router-dom';
22
import Header from '../../Header';
33
import Sidebar from '../../Sidebar';
44
import Footer from '../../Footer';
5+
import { useDispatch } from "react-redux";
6+
import { deleteProduct } from "../../../redux/actions/ProductActions";
57

68

79
const Product = (props) => {
8-
let {title,image,price,stock} = props.product;
10+
let {_id, title,image,price,stock} = props.product;
11+
const dispatch = useDispatch();
12+
13+
const deletehandler = (id) => {
14+
if (window.confirm("Are you sure want to delete product?")) {
15+
dispatch(deleteProduct(id));
16+
}
17+
};
918
return(
1019
<>
1120
<tr>
1221
<td>{title}</td>
1322
<td><img src={image} /></td>
1423
<td>{price}</td>
1524
<td>{stock}</td>
16-
<td><i class="fa fa-edit"></i><i class="fa fa-trash"></i></td>
25+
<td><Link
26+
to={`/product/edit/${_id}`}
27+
>
28+
<i className="fa fa-edit"></i>
29+
</Link>
30+
<Link
31+
to="#"
32+
onClick={() => deletehandler(_id)}
33+
>
34+
<i className="fa fa-trash"></i>
35+
</Link>
36+
</td>
1737
</tr>
1838
</>
1939
)

0 commit comments

Comments
 (0)