Kaynağa Gözat

fix product history and suggestion

master
azri 1 gün önce
ebeveyn
işleme
6290aa38dd

+ 1
- 1
src/components/Loader/Loader.jsx Dosyayı Görüntüle

@@ -38,7 +38,7 @@ const Loader = () => {
38 38
             height: 25,
39 39
           }} />
40 40
 
41
-        <div class="loader" style={{marginLeft:"20px"}}></div>
41
+        <div className="loader" style={{marginLeft:"20px"}}></div>
42 42
       </Box>
43 43
     </Box>
44 44
   );

+ 94
- 50
src/components/ProductHistoryList/ProductHistoryList.jsx Dosyayı Görüntüle

@@ -1,63 +1,105 @@
1 1
 import { useState, useEffect } from 'react';
2
-import { Box, Typography, IconButton, Pagination } from '@mui/material';
2
+import { Box, Typography, IconButton, Pagination, Button } from '@mui/material';
3 3
 import { useSelector, useDispatch } from 'react-redux';
4
-import { fetchProductsHistory } from '../../redux/slices/productSlice';
5 4
 
6 5
 import Grid from '@mui/material/Grid2';
7 6
 
8 7
 const ProductHistoryList = () => {
9 8
 
10
-  const products = useSelector((state) => state.products.productsHistory.data) // state.store.initialState.data
11
-  const dispatch = useDispatch()
9
+  const products = useSelector((state) => state.products.products.data); // only used as referenced
10
+  const [filterProducts, setFilterProducts] = useState([])
12 11
 
13
-  useEffect(() => {
12
+  useEffect(()=>{ 
14 13
 
15
-    if (localStorage.getItem('amber-product-history')) {
14
+    if (products.length > 0 && localStorage.getItem('amber-product-history')) {
16 15
 
17
-      let productIDList = JSON.parse(localStorage.getItem('amber-product-history'))
16
+      const productHandleList = JSON.parse(localStorage.getItem('amber-product-history')) || []
17
+      const selectedProducts = products.filter(({ handle }) => productHandleList.includes(handle) ) || []
18 18
 
19
-      dispatch(fetchProductsHistory(productIDList))
19
+      setFilterProducts(selectedProducts)
20 20
 
21 21
     }
22 22
 
23
-  }, [])
23
+  }, [products])
24 24
 
25
-  // useEffect(()=>{ 
26
-  //   console.log(products) 
27
-  // }, [products])
28
-
29
-  const renderProduct = (id, img_url, title, price, currency) => {
25
+  const renderProduct = (handle, img_url, title, collection_name, minPrice, minPriceCurrency, maxPrice, maxPriceCurrency, extra_desc, selected = false) => {
30 26
 
31 27
     return (
32
-      <Grid item size={{ xs: 12, md: 2 }}>
33
-        <Box
34
-          onClick={()=>{ window.location.href = `/products/${id}` }}
35
-          sx={{
36
-            overflow: 'hidden',
37
-            position: 'relative',
38
-            cursor: 'pointer'
39
-          }}
40
-        >
41
-          <img
42
-            src={img_url}
43
-            alt={title}
44
-            style={{
45
-              width: '100%',
46
-              aspectRatio: '4 / 4',
47
-              objectPosition:"top center",
48
-              objectFit: 'cover',
28
+      <Grid className="animate__animated animate__fadeIn" item size={{ xs: 6, sm: 6, md: 3 }}>
29
+
30
+        <a href={`/products/${handle}`} style={{ textDecoration: "none", color: "#000" }}>
31
+          <Box
32
+            sx={{
33
+              overflow: 'hidden',
34
+              position: 'relative',
35
+              cursor: 'pointer'
49 36
             }}
50
-          />
51
-
52
-          <Box sx={{ py: 5 }}>
53
-            <Typography variant="h5" sx={{ fontWeight: "bolder" }}>
54
-              {title}
55
-            </Typography>
56
-            <Typography variant="h6" >
57
-              {`${currency} ${parseFloat(price).toFixed(2)}`}
58
-            </Typography>
37
+
38
+          >
39
+            <img
40
+              src={img_url}
41
+              alt={title}
42
+              style={{
43
+                width: '100%',
44
+                aspectRatio: '3 / 4',
45
+                objectFit: 'cover',
46
+                objectPosition: 'top center'
47
+              }}
48
+            />
49
+
50
+            {(selected) && <Button
51
+              sx={{
52
+                position: "absolute",
53
+                top: {
54
+                  xs: 0,
55
+                  sm: 0,
56
+                  md: 10,
57
+                  lg: 20
58
+                },
59
+                left: {
60
+                  xs: 0,
61
+                  sm: 0,
62
+                  md: 10,
63
+                  lg: 20
64
+                },
65
+                boxShadow: 0,
66
+                fontSize: 10
67
+              }}
68
+              variant="contained">
69
+              NEW
70
+            </Button>}
71
+
72
+            <Box sx={{ pb: 3, pt: 1, width: "90%" }}>
73
+              <Typography variant="body2" sx={{
74
+                fontWeight: "100", fontSize: {
75
+                  xs: "0.875rem",
76
+                  sm: "0.875rem",
77
+                  md: "1.1rem",
78
+                }
79
+              }}>
80
+                {collection_name}
81
+              </Typography>
82
+              <Typography variant="body2" sx={{
83
+                fontWeight: "400", fontSize: {
84
+                  xs: "0.875rem",
85
+                  sm: "0.875rem",
86
+                  md: "1.1rem",
87
+                }
88
+              }}>
89
+                {title}
90
+              </Typography>
91
+              <Typography variant="body2" sx={{
92
+                fontWeight: "100", fontSize: {
93
+                  xs: "0.875rem",
94
+                  sm: "0.875rem",
95
+                  md: "1.1rem",
96
+                }
97
+              }}>
98
+                {`${minPriceCurrency} ${parseFloat(minPrice).toFixed(2)}`}
99
+              </Typography>
100
+            </Box>
59 101
           </Box>
60
-        </Box>
102
+        </a>
61 103
       </Grid>
62 104
     )
63 105
 
@@ -67,18 +109,20 @@ const ProductHistoryList = () => {
67 109
   return (
68 110
     <Box sx={{ mb: 5 }}>
69 111
       <Grid container spacing={1} columns={12}>
70
-        {products.map(( product, index) => {
112
+        {filterProducts.map((product, index) => {
71 113
 
72
-            let {id, title, compareAtPriceRange, images, collections} = product
73
-            let price = compareAtPriceRange.maxVariantPrice.amount
74
-            let currency = compareAtPriceRange.maxVariantPrice.currencyCode
75
-            let img_url = images.nodes[0]?.url
114
+          let { handle, title, images, collections, minVariantPrice, maxVariantPrice, productType, variants, selected } = product
76 115
 
77
-            // ID
78
-            const parts = id.split('/');
79
-            let prodID = parts[parts.length - 1];
116
+          let minPrice = minVariantPrice.amount
117
+          let minPriceCurrency = minVariantPrice.currencyCode
118
+          let maxPrice = maxVariantPrice.amount
119
+          let maxPriceCurrency = maxVariantPrice.currencyCode
120
+          let img_url = images[0]?.url
121
+          let collection_name = collections[0]?.title
80 122
 
81
-            return renderProduct(prodID, img_url, title, price, currency)
123
+          if (index < 4) {
124
+            return renderProduct(handle, img_url, title, collection_name, minPrice, minPriceCurrency, maxPrice, maxPriceCurrency, "", selected)
125
+          }
82 126
 
83 127
         })}
84 128
       </Grid>

+ 287
- 206
src/components/ProductList/ProductList.jsx Dosyayı Görüntüle

@@ -1,252 +1,277 @@
1
-import { useEffect, useState } from 'react';
2
-import { Box, Typography, Button, FormControl, Select, MenuItem, InputBase } from '@mui/material';
3
-import Grid from '@mui/material/Grid2';
1
+import { useEffect, useState } from "react";
2
+import {
3
+  Box,
4
+  Typography,
5
+  Button,
6
+  FormControl,
7
+  Select,
8
+  MenuItem,
9
+  InputBase,
10
+} from "@mui/material";
11
+import Grid from "@mui/material/Grid2";
4 12
 import { styled } from "@mui/material";
5 13
 //REDUX
6
-import { useSelector, useDispatch } from 'react-redux';
7
-import { fetchProducts } from '../../redux/slices/productSlice';
14
+import { useSelector, useDispatch } from "react-redux";
15
+import { fetchProducts } from "../../redux/slices/productSlice";
16
+import { useNavigate } from "react-router-dom";
8 17
 
9 18
 //UTIL FUNCTION
10 19
 function getAllTags(data) {
11 20
   const products = data || [];
12
-  const allTags = products.flatMap(product => product.tags);
21
+  const allTags = products.flatMap((product) => product.tags);
13 22
   const uniqueTags = [...new Set(allTags)];
14 23
   return uniqueTags;
15 24
 }
16 25
 
17 26
 function getAllCollection(data) {
18 27
   const products = data || [];
19
-  const allCollection = products.flatMap(product => product.collections);
28
+  const allCollection = products.flatMap((product) => product.collections);
20 29
   const uniqueCollection = Array.from(
21
-    new Map(allCollection.map(item => [item?.title, item])).values()
30
+    new Map(allCollection.map((item) => [item?.title, item])).values()
22 31
   );
23 32
   return uniqueCollection;
24 33
 }
25 34
 
26 35
 const BootstrapInput = styled(InputBase)(({ theme }) => ({
27
-  'label + &': {
36
+  "label + &": {
28 37
     marginTop: theme.spacing(3),
29 38
   },
30
-  '& .MuiInputBase-input': {
31
-    position: 'relative',
39
+  "& .MuiInputBase-input": {
40
+    position: "relative",
32 41
     backgroundColor: "#2E2E2E",
33
-    border: '1px solid #ced4da',
42
+    border: "1px solid #ced4da",
34 43
     color: "#FFF",
35 44
     fontSize: 13,
36
-    padding: '5px 0',
37
-    paddingRight: '50px !important',
45
+    padding: "5px 0",
46
+    paddingRight: "50px !important",
38 47
     paddingLeft: "10px",
39
-    transition: theme.transitions.create(['border-color', 'box-shadow']),
40
-    '&:focus': {
48
+    transition: theme.transitions.create(["border-color", "box-shadow"]),
49
+    "&:focus": {
41 50
       borderRadius: 4,
42
-      borderColor: '#80bdff',
43
-      boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)',
51
+      borderColor: "#80bdff",
52
+      boxShadow: "0 0 0 0.2rem rgba(0,123,255,.25)",
44 53
     },
45 54
   },
46
-  '& .MuiSvgIcon-root': {
47
-    color: "#FFF !important"
55
+  "& .MuiSvgIcon-root": {
56
+    color: "#FFF !important",
48 57
   },
49 58
 }));
50 59
 
51 60
 const ProductList = ({ size = 99999 }) => {
52
-
53
-  const products = useSelector((state) => state.products.products.data) // only used as referenced
54
-  const [filteredProducts, setFilteredProducts] = useState([]) // this one is the actual data to be rendered
55
-  const [tagFilterOption, setTagFilterOption] = useState([])
56
-  const [collectionFilterOption, setCollectionFilterOption] = useState([])
61
+  const products = useSelector((state) => state.products.products.data); // only used as referenced
62
+  const [filteredProducts, setFilteredProducts] = useState([]); // this one is the actual data to be rendered
63
+  const [tagFilterOption, setTagFilterOption] = useState([]);
64
+  const [collectionFilterOption, setCollectionFilterOption] = useState([]);
57 65
   const dispatch = useDispatch();
66
+  const navigate = useNavigate();
58 67
 
59 68
   //filter
60
-  const [tags, setTags] = useState('all');
61
-  const [collection, setCollection] = useState('all');
62
-  const [sort, setSort] = useState('new')
69
+  const [tags, setTags] = useState("all");
70
+  const [collection, setCollection] = useState("all");
71
+  const [sort, setSort] = useState("new");
63 72
 
64 73
   useEffect(() => {
65
-
66
-    dispatch(fetchProducts())
67
-
68
-  }, [])
69
-
74
+    dispatch(fetchProducts());
75
+  }, []);
70 76
 
71 77
   useEffect(() => {
72
-
73
-    console.log("Products: ", products)
78
+    console.log("Products: ", products);
74 79
 
75 80
     if (products.length > 0) {
76
-
77
-      let newFilteredProducts = filterProducts()
78
-      setFilteredProducts([])
81
+      let newFilteredProducts = filterProducts();
82
+      setFilteredProducts([]);
79 83
       setTimeout(() => {
80
-        setFilteredProducts(newFilteredProducts)
84
+        setFilteredProducts(newFilteredProducts);
81 85
       }, 100);
82 86
 
83 87
       const tagList = getAllTags(newFilteredProducts);
84 88
       setTagFilterOption(tagList);
85 89
 
86
-
87 90
       // Filter will only exist if the user haven't click on collection
88
-      if (!sessionStorage.getItem('amber-select-collection')) {
91
+      if (!sessionStorage.getItem("amber-select-collection")) {
89 92
         const collectionList = getAllCollection(newFilteredProducts);
90 93
         setCollectionFilterOption(collectionList);
91 94
       } else {
92
-        const selectedColletion = JSON.parse(sessionStorage.getItem('amber-select-collection'))
93
-        setCollection(selectedColletion?.title)
95
+        const selectedColletion = JSON.parse(
96
+          sessionStorage.getItem("amber-select-collection")
97
+        );
98
+        setCollection(selectedColletion?.title);
94 99
       }
95
-
96 100
     }
97
-
98
-
99
-  }, [products])
100
-
101
+  }, [products]);
101 102
 
102 103
   useEffect(() => {
103
-
104
-    let newFilteredProducts = filterProducts()
105
-    setFilteredProducts([])
104
+    let newFilteredProducts = filterProducts();
105
+    setFilteredProducts([]);
106 106
     setTimeout(() => {
107
-      setFilteredProducts(newFilteredProducts)
107
+      setFilteredProducts(newFilteredProducts);
108 108
     }, 100);
109
-
110
-
111
-  }, [tags, collection, sort])
109
+  }, [tags, collection, sort]);
112 110
 
113 111
   const filterProducts = () => {
114
-
115 112
     if (products?.length > 0) {
116
-
117
-      let productType = sessionStorage.getItem('amber-select-product-type')
113
+      let productType = sessionStorage.getItem("amber-select-product-type");
118 114
 
119 115
       let newFilteredProducts = products.filter(
120 116
         (product) => product.productType === productType
121 117
       );
122 118
 
123 119
       // Tags
124
-      newFilteredProducts = newFilteredProducts.filter(
125
-        (product) => {
126
-          if (tags == 'all') {
127
-            return product.productType === productType
128
-          } else {
129
-            return product.productType === productType && product.tags.includes(tags)
130
-          }
131
-
120
+      newFilteredProducts = newFilteredProducts.filter((product) => {
121
+        if (tags == "all") {
122
+          return product.productType === productType;
123
+        } else {
124
+          return (
125
+            product.productType === productType && product.tags.includes(tags)
126
+          );
132 127
         }
133
-      );
128
+      });
134 129
 
135 130
       // Collection
136
-      newFilteredProducts = newFilteredProducts.filter(
137
-        (product) => {
138
-
139
-          if (collection == 'all') {
140
-            return product.productType === productType
141
-          } else {
142
-            return product.productType === productType && product.collections.some(data => data?.title === collection)
143
-          }
144
-
131
+      newFilteredProducts = newFilteredProducts.filter((product) => {
132
+        if (collection == "all") {
133
+          return product.productType === productType;
134
+        } else {
135
+          return (
136
+            product.productType === productType &&
137
+            product.collections.some((data) => data?.title === collection)
138
+          );
145 139
         }
146
-      );
140
+      });
147 141
 
148 142
       if (sort === "title") {
149
-        newFilteredProducts = newFilteredProducts.sort((a, b) => a.title.localeCompare(b.title));
143
+        newFilteredProducts = newFilteredProducts.sort((a, b) =>
144
+          a.title.localeCompare(b.title)
145
+        );
150 146
       } else if (sort === "new") {
151
-        newFilteredProducts = newFilteredProducts.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
147
+        newFilteredProducts = newFilteredProducts.sort(
148
+          (a, b) => new Date(b.createdAt) - new Date(a.createdAt)
149
+        );
152 150
       } else if (sort === "old") {
153
-        newFilteredProducts = newFilteredProducts.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
151
+        newFilteredProducts = newFilteredProducts.sort(
152
+          (a, b) => new Date(a.createdAt) - new Date(b.createdAt)
153
+        );
154 154
       }
155 155
 
156
-      return newFilteredProducts
157
-
156
+      return newFilteredProducts;
158 157
     }
159 158
 
160
-    return []
161
-
162
-  }
159
+    return [];
160
+  };
163 161
 
164 162
   const handleChange = (event) => {
165 163
     //setInput({ ...input, [event.target.name]: event.target.value });
166 164
   };
167 165
 
168
-  const renderProduct = (handle, img_url, title, collection_name, minPrice, minPriceCurrency, maxPrice, maxPriceCurrency, extra_desc, selected = false) => {
169
-
166
+  const renderProduct = (
167
+    handle,
168
+    img_url,
169
+    title,
170
+    collection_name,
171
+    minPrice,
172
+    minPriceCurrency,
173
+    maxPrice,
174
+    maxPriceCurrency,
175
+    extra_desc,
176
+    selected = false
177
+  ) => {
170 178
     return (
171
-      <Grid className="animate__animated animate__fadeIn" item size={{ xs: 6, sm: 6, md: 3 }}>
172
-
173
-        <a href={`/products/${handle}`} style={{ textDecoration: "none", color: "#000" }}>
174
-          <Box
175
-            sx={{
176
-              overflow: 'hidden',
177
-              position: 'relative',
178
-              cursor: 'pointer'
179
+      <Grid
180
+        className="animate__animated animate__fadeIn"
181
+        item
182
+        size={{ xs: 6, sm: 6, md: 3 }}
183
+      >
184
+        <Box
185
+          sx={{
186
+            overflow: "hidden",
187
+            position: "relative",
188
+            cursor: "pointer",
189
+          }}
190
+          onClick={()=>{
191
+            navigate(`/products/${handle}`)
192
+          }}
193
+        >
194
+          <img
195
+            src={img_url}
196
+            alt={title}
197
+            style={{
198
+              width: "100%",
199
+              aspectRatio: "3 / 4",
200
+              objectFit: "cover",
201
+              objectPosition: "top center",
179 202
             }}
203
+          />
180 204
 
181
-          >
182
-            <img
183
-              src={img_url}
184
-              alt={title}
185
-              style={{
186
-                width: '100%',
187
-                aspectRatio: '3 / 4',
188
-                objectFit: 'cover',
189
-                objectPosition: 'top center'
190
-              }}
191
-            />
192
-
193
-            {(selected) && <Button
205
+          {selected && (
206
+            <Button
194 207
               sx={{
195 208
                 position: "absolute",
196 209
                 top: {
197 210
                   xs: 0,
198 211
                   sm: 0,
199 212
                   md: 10,
200
-                  lg: 20
213
+                  lg: 20,
201 214
                 },
202 215
                 left: {
203 216
                   xs: 0,
204 217
                   sm: 0,
205 218
                   md: 10,
206
-                  lg: 20
219
+                  lg: 20,
207 220
                 },
208 221
                 boxShadow: 0,
209
-                fontSize: 10
222
+                fontSize: 10,
210 223
               }}
211
-              variant="contained">
224
+              variant="contained"
225
+            >
212 226
               NEW
213
-            </Button>}
227
+            </Button>
228
+          )}
214 229
 
215
-            <Box sx={{ pb: 3, pt: 1, width: "90%" }}>
216
-              <Typography variant="body2" sx={{
217
-                fontWeight: "100", fontSize: {
230
+          <Box sx={{ pb: 3, pt: 1, width: "90%" }}>
231
+            <Typography
232
+              variant="body2"
233
+              sx={{
234
+                fontWeight: "100",
235
+                fontSize: {
218 236
                   xs: "0.875rem",
219 237
                   sm: "0.875rem",
220 238
                   md: "1.1rem",
221
-                }
222
-              }}>
223
-                {collection_name}
224
-              </Typography>
225
-              <Typography variant="body2" sx={{
226
-                fontWeight: "400", fontSize: {
239
+                },
240
+              }}
241
+            >
242
+              {collection_name}
243
+            </Typography>
244
+            <Typography
245
+              variant="body2"
246
+              sx={{
247
+                fontWeight: "400",
248
+                fontSize: {
227 249
                   xs: "0.875rem",
228 250
                   sm: "0.875rem",
229 251
                   md: "1.1rem",
230
-                }
231
-              }}>
232
-                {title}
233
-              </Typography>
234
-              <Typography variant="body2" sx={{
235
-                fontWeight: "100", fontSize: {
252
+                },
253
+              }}
254
+            >
255
+              {title}
256
+            </Typography>
257
+            <Typography
258
+              variant="body2"
259
+              sx={{
260
+                fontWeight: "100",
261
+                fontSize: {
236 262
                   xs: "0.875rem",
237 263
                   sm: "0.875rem",
238 264
                   md: "1.1rem",
239
-                }
240
-              }}>
241
-                {`${minPriceCurrency} ${parseFloat(minPrice).toFixed(2)}`}
242
-              </Typography>
243
-            </Box>
265
+                },
266
+              }}
267
+            >
268
+              {`${minPriceCurrency} ${parseFloat(minPrice).toFixed(2)}`}
269
+            </Typography>
244 270
           </Box>
245
-        </a>
271
+        </Box>
246 272
       </Grid>
247
-    )
248
-
249
-  }
273
+    );
274
+  };
250 275
 
251 276
   return (
252 277
     <>
@@ -260,90 +285,127 @@ const ProductList = ({ size = 99999 }) => {
260 285
             xs: "column",
261 286
             sm: "row",
262 287
             md: "row",
263
-            lg: "row"
288
+            lg: "row",
264 289
           },
265 290
           alignItems: "center",
266 291
           backgroundColor: "background.black",
267 292
           color: "white",
268 293
           px: 2, // Add padding around the box
269
-          my: 4
294
+          my: 4,
270 295
         }}
271 296
       >
272 297
         {/* Left Side: Page Title */}
273
-        <Typography variant="body2" sx={{ fontSize: 10, mt: { xs: 1, sm: 1, md: 0 } }}>
298
+        <Typography
299
+          variant="body2"
300
+          sx={{ fontSize: 10, mt: { xs: 1, sm: 1, md: 0 } }}
301
+        >
274 302
           {`${filteredProducts.length} Item`}
275 303
         </Typography>
276 304
 
277 305
         {/* Right Side: Option Inputs */}
278
-        <Box sx={{
279
-          display: "flex", gap: 2, flexDirection: "row", flexWrap: "wrap", justifyContent: "space-between", py: {
280
-            xs: 2,
281
-            sm: 2,
282
-            md: 0
283
-          }
284
-        }}>
285
-
286
-          {(tagFilterOption.length > 0) && <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
287
-            <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Tag</Typography>
288
-            <Select
289
-              value={tags}
290
-              onChange={(event) => {
291
-                setTags(event.target.value);
292
-              }}
293
-              sx={{
294
-                '& .MuiSelect-select': {
295
-                  border: "none"
296
-                }
297
-              }}
298
-              input={<BootstrapInput />}
299
-              name="type"
306
+        <Box
307
+          sx={{
308
+            display: "flex",
309
+            gap: 2,
310
+            flexDirection: "row",
311
+            flexWrap: "wrap",
312
+            justifyContent: "space-between",
313
+            py: {
314
+              xs: 2,
315
+              sm: 2,
316
+              md: 0,
317
+            },
318
+          }}
319
+        >
320
+          {tagFilterOption.length > 0 && (
321
+            <FormControl
322
+              sx={{ m: 1, display: "flex", flexDirection: "row" }}
323
+              variant="standard"
300 324
             >
301
-              <MenuItem value={'all'}>All</MenuItem>
302
-              {tagFilterOption?.map((data) => (<MenuItem value={data}>{data}</MenuItem>))}
303
-            </Select>
304
-          </FormControl>}
305
-
306
-          {(collectionFilterOption.length > 0) && <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
307
-            <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Collection</Typography>
308
-            <Select
309
-              value={collection}
310
-              onChange={(event) => {
311
-                setCollection(event.target.value);
312
-              }}
313
-              sx={{
314
-                '& .MuiSelect-select': {
315
-                  border: "none"
316
-                }
317
-              }}
318
-              input={<BootstrapInput />}
319
-              name="type"
325
+              <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>
326
+                Tag
327
+              </Typography>
328
+              <Select
329
+                value={tags}
330
+                onChange={(event) => {
331
+                  setTags(event.target.value);
332
+                }}
333
+                sx={{
334
+                  "& .MuiSelect-select": {
335
+                    border: "none",
336
+                  },
337
+                }}
338
+                input={<BootstrapInput />}
339
+                name="type"
340
+              >
341
+                <MenuItem value={"all"}>All</MenuItem>
342
+                {tagFilterOption?.map((data) => (
343
+                  <MenuItem value={data}>{data}</MenuItem>
344
+                ))}
345
+              </Select>
346
+            </FormControl>
347
+          )}
348
+
349
+          {collectionFilterOption.length > 0 && (
350
+            <FormControl
351
+              sx={{ m: 1, display: "flex", flexDirection: "row" }}
352
+              variant="standard"
320 353
             >
321
-              <MenuItem value={'all'}>All</MenuItem>
322
-              {collectionFilterOption?.map(({ title }) => (<MenuItem value={title}>{title}</MenuItem>))}
323
-            </Select>
324
-          </FormControl>}
325
-
326
-          <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
327
-            <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Sort</Typography>
354
+              <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>
355
+                Collection
356
+              </Typography>
357
+              <Select
358
+                value={collection}
359
+                onChange={(event) => {
360
+                  setCollection(event.target.value);
361
+                }}
362
+                sx={{
363
+                  "& .MuiSelect-select": {
364
+                    border: "none",
365
+                  },
366
+                }}
367
+                input={<BootstrapInput />}
368
+                name="type"
369
+              >
370
+                <MenuItem value={"all"}>All</MenuItem>
371
+                {collectionFilterOption?.map(({ title }) => (
372
+                  <MenuItem value={title}>{title}</MenuItem>
373
+                ))}
374
+              </Select>
375
+            </FormControl>
376
+          )}
377
+
378
+          <FormControl
379
+            sx={{ m: 1, display: "flex", flexDirection: "row" }}
380
+            variant="standard"
381
+          >
382
+            <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>
383
+              Sort
384
+            </Typography>
328 385
             <Select
329 386
               value={sort}
330 387
               onChange={(event) => {
331 388
                 setSort(event.target.value);
332 389
               }}
333 390
               sx={{
334
-                '& .MuiSelect-select': {
335
-                  border: "none"
336
-                }
391
+                "& .MuiSelect-select": {
392
+                  border: "none",
393
+                },
337 394
               }}
338 395
               input={<BootstrapInput />}
339 396
               name="sort"
340 397
             >
341
-              <MenuItem defaultValue value={'title'}>Title</MenuItem>
342
-              <MenuItem defaultValue value={'new'}>Newest</MenuItem>
343
-              <MenuItem defaultValue value={'old'}>Oldest</MenuItem>
398
+              <MenuItem defaultValue value={"title"}>
399
+                Title
400
+              </MenuItem>
401
+              <MenuItem defaultValue value={"new"}>
402
+                Newest
403
+              </MenuItem>
404
+              <MenuItem defaultValue value={"old"}>
405
+                Oldest
406
+              </MenuItem>
344 407
             </Select>
345 408
           </FormControl>
346
-
347 409
         </Box>
348 410
       </Box>
349 411
 
@@ -351,20 +413,39 @@ const ProductList = ({ size = 99999 }) => {
351 413
       <Box sx={{ mb: 5 }}>
352 414
         <Grid container spacing={0.5} columns={12}>
353 415
           {filteredProducts.map((product, index) => {
354
-
355
-            let { handle, title, images, collections, minVariantPrice, maxVariantPrice, productType, variants, selected } = product
356
-
357
-            let minPrice = minVariantPrice.amount
358
-            let minPriceCurrency = minVariantPrice.currencyCode
359
-            let maxPrice = maxVariantPrice.amount
360
-            let maxPriceCurrency = maxVariantPrice.currencyCode
361
-            let img_url = images[0]?.url
362
-            let collection_name = collections[0]?.title
416
+            let {
417
+              handle,
418
+              title,
419
+              images,
420
+              collections,
421
+              minVariantPrice,
422
+              maxVariantPrice,
423
+              productType,
424
+              variants,
425
+              selected,
426
+            } = product;
427
+
428
+            let minPrice = minVariantPrice.amount;
429
+            let minPriceCurrency = minVariantPrice.currencyCode;
430
+            let maxPrice = maxVariantPrice.amount;
431
+            let maxPriceCurrency = maxVariantPrice.currencyCode;
432
+            let img_url = images[0]?.url;
433
+            let collection_name = collections[0]?.title;
363 434
 
364 435
             if (index < size) {
365
-              return renderProduct(handle, img_url, title, collection_name, minPrice, minPriceCurrency, maxPrice, maxPriceCurrency, "", selected)
436
+              return renderProduct(
437
+                handle,
438
+                img_url,
439
+                title,
440
+                collection_name,
441
+                minPrice,
442
+                minPriceCurrency,
443
+                maxPrice,
444
+                maxPriceCurrency,
445
+                "",
446
+                selected
447
+              );
366 448
             }
367
-
368 449
           })}
369 450
         </Grid>
370 451
       </Box>

+ 127
- 29
src/components/ProductSuggestion/ProductSuggestion.jsx Dosyayı Görüntüle

@@ -1,16 +1,18 @@
1
-import {useState, useEffect} from 'react';
1
+import { useState, useEffect } from 'react';
2 2
 import { Box, Typography, Button } from '@mui/material';
3 3
 import { useSelector } from 'react-redux';
4
-
5 4
 import Grid from '@mui/material/Grid2';
5
+import { useNavigate } from "react-router-dom";
6 6
 
7 7
 const ProductSuggestion = () => {
8 8
 
9 9
   const [suggestProducts, setSuggestProducts] = useState([]);
10
-  const products = useSelector((state) => state.products.productsHistory.data);
10
+  const products = useSelector((state) => state.products.products.data);
11
+
12
+  const navigate = useNavigate();
11 13
 
12 14
   useEffect(() => {
13
-    if (products && products.length > 0) {
15
+    if (products.length > 0) {
14 16
       const getRandomProducts = (arr, num) => {
15 17
         const shuffled = [...arr].sort(() => 0.5 - Math.random());
16 18
         return shuffled.slice(0, num);
@@ -21,57 +23,153 @@ const ProductSuggestion = () => {
21 23
     }
22 24
   }, [products]);
23 25
 
24
-  const renderProduct = (id, img_url, title, price, currency) => {
26
+  const renderProduct = (
27
+    handle,
28
+    img_url,
29
+    title,
30
+    collection_name,
31
+    minPrice,
32
+    minPriceCurrency,
33
+    maxPrice,
34
+    maxPriceCurrency,
35
+    extra_desc,
36
+    selected = false
37
+  ) => {
25 38
     return (
26
-      <Grid item size={{ xs: 12, md: 3 }}>
39
+      <Grid
40
+        className="animate__animated animate__fadeIn"
41
+        item
42
+        size={{ xs: 6, sm: 6, md: 3 }}
43
+      >
27 44
         <Box
28
-          onClick={() => { window.location.href = `/products/${id}` }}
29 45
           sx={{
30
-            overflow: 'hidden',
31
-            position: 'relative',
32
-            cursor: 'pointer'
46
+            overflow: "hidden",
47
+            position: "relative",
48
+            cursor: "pointer",
49
+          }}
50
+          onClick={() => {
51
+            navigate(`/products/${handle}`)
33 52
           }}
34 53
         >
35 54
           <img
36 55
             src={img_url}
37 56
             alt={title}
38 57
             style={{
39
-              width: '100%',
40
-              aspectRatio: '4 / 4',
41
-              objectPosition:"top center",
42
-              objectFit: 'cover',
58
+              width: "100%",
59
+              aspectRatio: "3 / 4",
60
+              objectFit: "cover",
61
+              objectPosition: "top center",
43 62
             }}
44 63
           />
45 64
 
46
-          <Box sx={{ py: 5 }}>
47
-            <Typography variant="h5" sx={{ fontWeight: "bolder" }}>
65
+          {selected && (
66
+            <Button
67
+              sx={{
68
+                position: "absolute",
69
+                top: {
70
+                  xs: 0,
71
+                  sm: 0,
72
+                  md: 10,
73
+                  lg: 20,
74
+                },
75
+                left: {
76
+                  xs: 0,
77
+                  sm: 0,
78
+                  md: 10,
79
+                  lg: 20,
80
+                },
81
+                boxShadow: 0,
82
+                fontSize: 10,
83
+              }}
84
+              variant="contained"
85
+            >
86
+              NEW
87
+            </Button>
88
+          )}
89
+
90
+          <Box sx={{ pb: 3, pt: 1, width: "90%" }}>
91
+            <Typography
92
+              variant="body2"
93
+              sx={{
94
+                fontWeight: "100",
95
+                fontSize: {
96
+                  xs: "0.875rem",
97
+                  sm: "0.875rem",
98
+                  md: "1.1rem",
99
+                },
100
+              }}
101
+            >
102
+              {collection_name}
103
+            </Typography>
104
+            <Typography
105
+              variant="body2"
106
+              sx={{
107
+                fontWeight: "400",
108
+                fontSize: {
109
+                  xs: "0.875rem",
110
+                  sm: "0.875rem",
111
+                  md: "1.1rem",
112
+                },
113
+              }}
114
+            >
48 115
               {title}
49 116
             </Typography>
50
-            <Typography variant="h6" >
51
-              {`${currency} ${parseFloat(price).toFixed(2)}`}
117
+            <Typography
118
+              variant="body2"
119
+              sx={{
120
+                fontWeight: "100",
121
+                fontSize: {
122
+                  xs: "0.875rem",
123
+                  sm: "0.875rem",
124
+                  md: "1.1rem",
125
+                },
126
+              }}
127
+            >
128
+              {`${minPriceCurrency} ${parseFloat(minPrice).toFixed(2)}`}
52 129
             </Typography>
53 130
           </Box>
54 131
         </Box>
55 132
       </Grid>
56
-    )
57
-  }
133
+    );
134
+  };
58 135
 
59 136
 
60 137
   return (
61 138
     <Box sx={{ mb: 5 }}>
62 139
       <Grid container spacing={1} columns={12}>
63 140
         {suggestProducts.map((product, index) => {
64
- 
65
-          let {id, title, compareAtPriceRange, images, collections} = product
66
-          let price = compareAtPriceRange.maxVariantPrice.amount
67
-          let currency = compareAtPriceRange.maxVariantPrice.currencyCode
68
-          let img_url = images.nodes[0]?.url
69 141
 
70
-          // ID
71
-          const parts = id.split('/');
72
-          let prodID = parts[parts.length - 1];
142
+          let {
143
+            handle,
144
+            title,
145
+            images,
146
+            collections,
147
+            minVariantPrice,
148
+            maxVariantPrice,
149
+            productType,
150
+            variants,
151
+            selected,
152
+          } = product;
153
+
154
+          let minPrice = minVariantPrice.amount;
155
+          let minPriceCurrency = minVariantPrice.currencyCode;
156
+          let maxPrice = maxVariantPrice.amount;
157
+          let maxPriceCurrency = maxVariantPrice.currencyCode;
158
+          let img_url = images[0]?.url;
159
+          let collection_name = collections[0]?.title;
73 160
 
74
-          return renderProduct(prodID, img_url, title, price, currency)
161
+          return renderProduct(
162
+            handle,
163
+            img_url,
164
+            title,
165
+            collection_name,
166
+            minPrice,
167
+            minPriceCurrency,
168
+            maxPrice,
169
+            maxPriceCurrency,
170
+            "",
171
+            selected
172
+          );
75 173
         })}
76 174
       </Grid>
77 175
     </Box>

+ 2
- 2
src/pages/Products/Product.jsx Dosyayı Görüntüle

@@ -87,7 +87,7 @@ const Product = () => {
87 87
           YOU MAY ALSO LIKE
88 88
         </Typography>
89 89
 
90
-        {/* <ProductSuggestion /> */}
90
+        <ProductSuggestion />
91 91
 
92 92
       </Box>
93 93
 
@@ -101,7 +101,7 @@ const Product = () => {
101 101
           RECENTLY VIEWED
102 102
         </Typography>
103 103
 
104
-        {/* <ProductHistoryList /> */}
104
+        <ProductHistoryList />
105 105
 
106 106
       </Box>
107 107
 

+ 0
- 23
src/redux/slices/productSlice.js Dosyayı Görüntüle

@@ -61,16 +61,6 @@ export const fetchProductsByTags = createAsyncThunk(
61 61
   }
62 62
 )
63 63
 
64
-export const fetchProductsHistory = createAsyncThunk(
65
-  'product/fetchProductsHistory',
66
-  async (productIDList) => {
67
-
68
-    const idsQuery = productIDList.map(id => `id:${id}`).join(" OR ");
69
-    const response = await ProductService.getProducts(6, "TITLE", idsQuery)
70
-    return response
71
-
72
-  }
73
-)
74 64
 
75 65
 export const productSlice = createSlice({
76 66
   name: 'product',
@@ -129,19 +119,6 @@ export const productSlice = createSlice({
129 119
         state.products.data = [];
130 120
         state.products.error = action.error.message;
131 121
       })
132
-      .addCase(fetchProductsHistory.pending, (state) => {
133
-        state.productsHistory.status = 'loading';
134
-        state.productsHistory.error = null;
135
-      })
136
-      .addCase(fetchProductsHistory.fulfilled, (state, action) => {
137
-        state.productsHistory.status = 'succeeded';
138
-        state.productsHistory.data = action.payload
139
-      })
140
-      .addCase(fetchProductsHistory.rejected, (state, action) => {
141
-        state.productsHistory.status = 'failed';
142
-        state.productsHistory.data = [];
143
-        state.productsHistory.error = action.error.message;
144
-      })
145 122
   }
146 123
 });
147 124
 

Loading…
İptal
Kaydet