Skip to content

Commit b1ccdde

Browse files
committed
Update product info
- upload image by firebase and get the downloadURL - intialize state onchange one time for product info - Add deleteAll action for products from redux to fix issue
1 parent 1ed709a commit b1ccdde

File tree

5 files changed

+108
-16
lines changed

5 files changed

+108
-16
lines changed

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="" 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;

0 commit comments

Comments
 (0)