Skip to content

Commit 20ab6f2

Browse files
authored
Merge pull request #5 from Soliman3/develop
Pull develop
2 parents 1ed709a + 16208cb commit 20ab6f2

23 files changed

+451
-148
lines changed

admin/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/node_modules
55
/.pnp
66
.pnp.js
7-
7+
firebase.js
88
# testing
99
/coverage
1010

admin/src/components/TopBar.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919

2020
// import required image from images library...
2121
import profilePhoto from '../images/1.jpg'
22+
import { deleteAll } from '../redux/productSlice';
2223

2324
// Styling...
2425
const Container = styled.div`
@@ -101,6 +102,10 @@ export default function TopBar() {
101102
} catch (error) {
102103
}
103104
}
105+
// emty redux products...
106+
const handleClick = () => {
107+
dispatch(deleteAll())
108+
}
104109
return (
105110
<Container>
106111
<Wrapper>
@@ -112,7 +117,7 @@ export default function TopBar() {
112117
<PowerSettingsNewOutlined onClick={handleLogOut} style={{ fontSize: '20px' }} />
113118
</TopBarRightIcons>
114119
<TopBarRightIcons>
115-
<SettingsOutlined style={{ fontSize: '20px' }} />
120+
<SettingsOutlined style={{ fontSize: '20px' }} onClick={handleClick} />
116121
</TopBarRightIcons>
117122
<TopBarRightIcons>
118123
<NotificationsNone style={{ fontSize: '20px' }} />

admin/src/pages/NewProduct.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ export default function NewProduct() {
138138
);
139139

140140
}
141-
console.log(file);
142141
return (
143142
<Container>
144143
<NewProductTitle>Add New Product</NewProductTitle>

admin/src/pages/ProductList.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const ProductContainer = styled.div`
3434
const ProductImage = styled.img`
3535
width: 35px;
3636
height: 35px;
37-
border-radius: 50%;
37+
3838
object-fit: cover;
3939
`
4040
const EditButton = styled.button`
@@ -102,7 +102,7 @@ export default function ProductList() {
102102
field: 'product', headerName: 'Product ', width: 300, renderCell: (params) => {
103103
return (
104104
<ProductContainer>
105-
<ProductImage src={params.row.productImage} alt="" />
105+
<ProductImage src={params.row.image} alt="" />
106106
{params.row.title}
107107
</ProductContainer>
108108
)

admin/src/pages/ProductSinglePage.jsx

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@ import React, { useEffect, useMemo, useState } from 'react'
44
import styled from 'styled-components'
55

66
// import React Router Dom Library for Routing..
7-
import { Link, useLocation } from 'react-router-dom'
7+
import { Link, useLocation, useNavigate } from 'react-router-dom'
88

99
// import required components...
1010
import Charts from '../components/Charts'
1111

1212
// import produts data from dummyData.js file...
1313
import { productsData } from '../Data/dummyData'
1414
import { AddOutlined, Publish } from '@mui/icons-material'
15-
import { useSelector } from 'react-redux'
15+
import { useDispatch, useSelector } from 'react-redux'
1616
import { userRequest } from '../requestAxiosMethod'
1717

18+
// firebase requires functions from firebase library...
19+
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
20+
import app from '../firebase'
21+
import { updateProductFailure, updateProductStart, updateProductSuccess } from '../redux/productSlice'
22+
1823
// Styling...
1924
const Container = styled.div`
2025
flex: 4;
@@ -197,7 +202,82 @@ export default function ProductSinglePage() {
197202
}
198203
getOrderedProductInfo()
199204
}, [months, productId])
200-
console.log(product)
205+
// #################################################
206+
// handle update product...
207+
const [inputs, setInputs] = useState({})
208+
const [categories, setCategories] = useState([])
209+
const [file, setFile] = useState()
210+
const dispatch = useDispatch()
211+
const navigate = useNavigate()
212+
213+
// handleChange of inputs in group in onetime...
214+
const handleChange = (e) => {
215+
setInputs((previous) => {
216+
return { ...previous, [e.target.name]: e.target.value}
217+
})
218+
}
219+
220+
// handle state of categories and split categories by split method...
221+
const handleCategories = (e) => {
222+
setCategories(e.target.value.split(','))
223+
}
224+
225+
// send payload to server by axios post method...
226+
const handleClick = (e) => {
227+
// prevent default event (reloading page) when click create...
228+
e.preventDefault()
229+
// upload image & inputs to database throght api post request ...
230+
const fileName = new Date().getTime + file?.name;
231+
const storage = getStorage(app);
232+
const storageRef = ref(storage, fileName);
233+
234+
const uploadTask = uploadBytesResumable(storageRef, file);
235+
236+
// Register three observers:
237+
// 1. 'state_changed' observer, called any time the state changes
238+
// 2. Error observer, called on failure
239+
// 3. Completion observer, called on successful completion
240+
uploadTask.on('state_changed',
241+
(snapshot) => {
242+
// Observe state change events such as progress, pause, and resume
243+
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
244+
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
245+
console.log('Upload is ' + progress + '% done');
246+
switch (snapshot.state) {
247+
case 'paused':
248+
console.log('Upload is paused');
249+
break;
250+
case 'running':
251+
console.log('Upload is running');
252+
break;
253+
}
254+
},
255+
(error) => {
256+
// Handle unsuccessful uploads
257+
},
258+
() => {
259+
// Handle successful uploads on complete
260+
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
261+
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
262+
const product = { ...inputs, image: downloadURL, category: categories }
263+
console.log(product);
264+
const updateProducts = async () => {
265+
dispatch(updateProductStart())
266+
try {
267+
const response = await userRequest.put(`/products/${productId}`, product )
268+
dispatch(updateProductSuccess(response.data))
269+
.then(navigate('/products'))
270+
} catch (error) {
271+
dispatch(updateProductFailure())
272+
}
273+
}
274+
275+
updateProducts();
276+
});
277+
}
278+
);
279+
}
280+
201281
return (
202282
<Container>
203283
<ProductTitleContainer>
@@ -239,20 +319,23 @@ export default function ProductSinglePage() {
239319
<ProductFormLeft>
240320
<ProductFormLeftItem>
241321
<ProductItemLabel>Product Name</ProductItemLabel>
242-
<ProductItemInput type="text" placeholder={product.title} />
322+
<ProductItemInput name="title" type="text" placeholder={product.title} onChange={handleChange}/>
243323
</ProductFormLeftItem>
244324
<ProductFormLeftItem>
245325
<ProductItemLabel>Product Description</ProductItemLabel>
246-
<ProductItemInput type="text" placeholder={product.description} />
326+
<ProductItemInput type="text" placeholder={product.description} name="description" onChange={handleChange}/>
247327
</ProductFormLeftItem>
248328
<ProductFormLeftItem>
249329
<ProductItemLabel>Price</ProductItemLabel>
250-
<ProductItemInput type="text" placeholder={product.price} />
330+
<ProductItemInput type="number" placeholder={product.price} name="price" onChange={handleChange}/>
331+
</ProductFormLeftItem>
332+
<ProductFormLeftItem>
333+
<ProductItemLabel>Categories</ProductItemLabel>
334+
<ProductItemInput type="text" placeholder={product.category} name="category" onChange={handleCategories}/>
251335
</ProductFormLeftItem>
252-
253336
<ProductFormLeftItem>
254337
<ProductItemLabel>In Stock</ProductItemLabel>
255-
<ProductItemSelect name="inStock" id="inStock">
338+
<ProductItemSelect name="inStock" id="inStock" onChange={handleChange}>
256339
<ProductItemOption value="true">Yes</ProductItemOption>
257340
<ProductItemOption value="false">No</ProductItemOption>
258341
</ProductItemSelect>
@@ -262,9 +345,9 @@ export default function ProductSinglePage() {
262345
<ProductFormImageUpload>
263346
<ProductImage src={product.image} alt="" />
264347
<ProductImageUploadLabel for="file"><Publish /></ProductImageUploadLabel>
265-
<ProductImageUploadInput type="file" id="file" style={{display: 'none'}} />
348+
<ProductImageUploadInput type="file" id="file" style={{display: 'none'}} onChange={(e)=> setFile(e.target.files[0])} />
266349
</ProductFormImageUpload>
267-
<ProductUpdateButton>Update</ProductUpdateButton>
350+
<ProductUpdateButton onClick={handleClick}>Update</ProductUpdateButton>
268351
</ProductFormRight>
269352
</ProductBottomForm>
270353
</ProductBottom>

admin/src/redux/productSlice.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,18 @@ export const productSlice = createSlice({
7474
addProductFailure: (state) => {
7575
state.loading = false
7676
state.error = true
77-
}
77+
},
78+
deleteAll: (state) => {
79+
state.products = []
80+
state.loading = false
81+
state.error = false
82+
},
7883
},
7984
});
8085

8186
export const { getProductStart, getProductSuccess, getProductFailure,
8287
deleteProductStart, deleteProductSuccess, deleteProductFailure,
8388
updateProductStart, updateProductSuccess, updateProductFailure,
84-
addProductStart, addProductSuccess, addProductFailure
89+
addProductStart, addProductSuccess, addProductFailure, deleteAll
8590
} = productSlice.actions;
8691
export default productSlice.reducer;

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"web-vitals": "^2.1.4"
2727
},
2828
"scripts": {
29-
"start": "react-scripts start",
29+
"start": "set PORT=3002 && react-scripts start",
3030
"build": "react-scripts build",
3131
"test": "react-scripts test",
3232
"eject": "react-scripts eject"

client/src/Data/categoriesData.js

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,68 @@
1-
import OfferFirstSlide from '../images/2.png'
2-
import OfferSecondSlide from '../images/2.png'
3-
import OfferThirdSlide from '../images/2.png'
1+
import Mobiles from '../images/mobiles.jpg'
2+
import accessories from '../images/airpod.png'
3+
import appliances from '../images/homeAppliances.jpg'
4+
import Men from '../images/menWear.jpg'
5+
import Grocery from '../images/grocery.jpg'
6+
import Beauty from '../images/beauty.jpg'
7+
import Baby from '../images/baby.jpg'
8+
import Vega from '../images/veg.jpg'
9+
import KidsWear from '../images/kidsWear.jpg'
410

511
export const categories = [
612
{
713
id: 1,
8-
img: OfferFirstSlide,
9-
title: "MOBILE",
14+
img: Mobiles,
15+
title: "mobile",
1016
category: "mobile",
1117
},
1218
{
1319
id: 2,
14-
img: OfferSecondSlide,
15-
title: "Accessories",
20+
img: accessories,
21+
title: "accessories",
1622
category: "accessories",
1723
},
1824
{
1925
id: 3,
20-
img: OfferThirdSlide,
21-
title: "HOME APPLIANCE",
26+
img: appliances,
27+
title: "appliances",
2228
category: "appliances",
23-
}
29+
},
30+
{
31+
id: 4,
32+
img: Men,
33+
title: "Men",
34+
category: "Men",
35+
},
36+
{
37+
id: 5,
38+
img: Grocery,
39+
title: "grocery",
40+
category: "grocery",
41+
},
42+
{
43+
id: 6,
44+
img: Beauty,
45+
title: "beauty",
46+
category: "beauty",
47+
},
48+
{
49+
id: 7,
50+
img: Baby,
51+
title: "baby",
52+
category: "baby",
53+
},
54+
{
55+
id: 8,
56+
img: Vega,
57+
title: "fruits & veg",
58+
category: "fruits & veg",
59+
},
60+
{
61+
id: 9,
62+
img: KidsWear,
63+
title: "Kids Wear",
64+
category: "Kids Wear",
65+
},
66+
67+
2468
]

client/src/components/CategoryBar.jsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
// import icons from muiv5 library...
5+
import {ArrowDropDown} from '@mui/icons-material';
6+
7+
// Styling...
8+
const Container = styled.div`
9+
height: 50px;
10+
border-top: 0.25px solid #bee4f4;
11+
border-bottom: 0.25px solid #bee4f4;
12+
`
13+
const Wrapper = styled.div`
14+
height: 100%;
15+
display: flex;
16+
17+
`
18+
const LeftContainer = styled.div`
19+
flex: 1;
20+
align-items: center;
21+
padding: 15px;
22+
display: flex;
23+
justify-content: space-between;
24+
border-right: 0.25px solid #bee4f4;
25+
`
26+
const LeftContainerLabel = styled.span`
27+
font-size: 16px;
28+
font-weight: bold;
29+
`
30+
const LeftContainerIcon = styled.div`
31+
32+
`
33+
const RightContainer = styled.div`
34+
flex: 4;
35+
align-items: center;
36+
padding: 15px;
37+
display: flex;
38+
`
39+
const RightContainerItem = styled.span`
40+
font-size: 16px;
41+
margin-right: 25px;
42+
font-weight: bold;
43+
color: ${(props)=> props.type === 'vip' && 'red'};
44+
`
45+
46+
47+
export default function CategoryBar() {
48+
return (
49+
<Container>
50+
<Wrapper>
51+
<LeftContainer>
52+
<LeftContainerLabel>All Category</LeftContainerLabel>
53+
<LeftContainerIcon><ArrowDropDown style={{color: 'blue'}}/></LeftContainerIcon>
54+
</LeftContainer>
55+
<RightContainer>
56+
<RightContainerItem>Electronics</RightContainerItem>
57+
<RightContainerItem>Mobiles</RightContainerItem>
58+
<RightContainerItem>Men</RightContainerItem>
59+
<RightContainerItem>Women</RightContainerItem>
60+
<RightContainerItem>Home</RightContainerItem>
61+
<RightContainerItem>Beauty</RightContainerItem>
62+
<RightContainerItem>Babay & Toys</RightContainerItem>
63+
<RightContainerItem>Electronics</RightContainerItem>
64+
<RightContainerItem>Supermarket</RightContainerItem>
65+
<RightContainerItem type="vip">DEALS</RightContainerItem>
66+
67+
</RightContainer>
68+
</Wrapper>
69+
</Container>
70+
)
71+
}

0 commit comments

Comments
 (0)