Przeglądaj źródła

select product by tags

master
azri 4 tygodni temu
rodzic
commit
cb1f00b4e9

+ 59
- 8
src/components/ProductList/ProductList.jsx Wyświetl plik

@@ -4,7 +4,7 @@ import Grid from '@mui/material/Grid2';
4 4
 import { styled } from "@mui/material";
5 5
 //REDUX
6 6
 import { useSelector, useDispatch } from 'react-redux';
7
-import { fetchProducts, fetchProductsByCollection } from '../../redux/slices/productSlice';
7
+import { fetchProductsByTags, fetchProductsByCollection } from '../../redux/slices/productSlice';
8 8
 
9 9
 //UTIL FUNCTION
10 10
 function getAllTags(data) {
@@ -14,6 +14,15 @@ function getAllTags(data) {
14 14
   return uniqueTags;
15 15
 }
16 16
 
17
+function getAllCollection(data) {
18
+  const products = data || [];
19
+  const allCollection = products.flatMap(product => product.collections.nodes);
20
+  const uniqueCollection = Array.from(
21
+    new Map(allCollection.map(item => [item.title, item])).values()
22
+  );
23
+  return uniqueCollection;
24
+}
25
+
17 26
 const BootstrapInput = styled(InputBase)(({ theme }) => ({
18 27
   'label + &': {
19 28
     marginTop: theme.spacing(3),
@@ -44,10 +53,12 @@ const ProductList = ({ size = 99999 }) => {
44 53
   const products = useSelector((state) => state.products.products.data) // only used as referenced
45 54
   const [filteredProducts, setFilteredProducts] = useState([]) // this one is the actual data to be rendered
46 55
   const [categoryFilterOption, setCategoryFilterOption] = useState([])
56
+  const [collectionFilterOption, setCollectionFilterOption] = useState([])
47 57
   const dispatch = useDispatch();
48 58
 
49 59
   //filter
50 60
   const [category, setCategory] = useState('all');
61
+  const [collection, setCollection] = useState('all');
51 62
   const [sort, setSort] = useState('title')
52 63
 
53 64
   useEffect(() => {
@@ -60,7 +71,9 @@ const ProductList = ({ size = 99999 }) => {
60 71
 
61 72
     } else if (sessionStorage.getItem('amber-select-category')) {
62 73
 
63
-      
74
+      let tag = sessionStorage.getItem('amber-select-category')
75
+      if(tag == 'all') tag = ""
76
+      dispatch(fetchProductsByTags({ tag }))
64 77
 
65 78
     }
66 79
 
@@ -68,15 +81,22 @@ const ProductList = ({ size = 99999 }) => {
68 81
 
69 82
   useEffect(() => {
70 83
 
84
+    console.log(products)
71 85
     let productType = sessionStorage.getItem('amber-select-product-type')
72 86
     let newFilteredProducts = products.filter(
73 87
       (product) => product.productType === productType
74 88
     );
75 89
 
76
-    const categoryList = getAllTags(newFilteredProducts) // yes we use tags as category, while I was coding this, this is the only way to implement category
77
-
78 90
     setFilteredProducts(newFilteredProducts)
79
-    setCategoryFilterOption(categoryList)
91
+
92
+    if (sessionStorage.getItem('amber-select-collection')){
93
+      const categoryList = getAllTags(newFilteredProducts) // yes we use tags as category, while I was coding this, this is the only way to implement category
94
+      setCategoryFilterOption(categoryList)
95
+    } else if (sessionStorage.getItem('amber-select-category')) {
96
+      const collectionList = getAllCollection(newFilteredProducts)
97
+      setCollectionFilterOption(collectionList)
98
+    }
99
+    
80 100
 
81 101
   }, [products])
82 102
 
@@ -87,6 +107,7 @@ const ProductList = ({ size = 99999 }) => {
87 107
 
88 108
       let productType = sessionStorage.getItem('amber-select-product-type')
89 109
 
110
+      // Category
90 111
       let newFilteredProducts = products.filter(
91 112
         (product) => {
92 113
 
@@ -99,6 +120,20 @@ const ProductList = ({ size = 99999 }) => {
99 120
         }
100 121
       );
101 122
 
123
+      // Collection
124
+      newFilteredProducts = newFilteredProducts.filter(
125
+        (product) => {
126
+
127
+          if(collection == 'all'){
128
+            return product.productType === productType
129
+          } else {
130
+            debugger
131
+            return product.productType === productType && product.collections.nodes.some(data => data.title === collection)
132
+          }
133
+
134
+        }
135
+      );
136
+
102 137
       if (sort === "title") {
103 138
         newFilteredProducts = newFilteredProducts.sort((a, b) => a.title.localeCompare(b.title));
104 139
       } else if (sort === "new") {
@@ -111,7 +146,7 @@ const ProductList = ({ size = 99999 }) => {
111 146
 
112 147
     }
113 148
 
114
-  }, [category, sort])
149
+  }, [category, collection, sort])
115 150
 
116 151
   useEffect(() => {
117 152
     if (products) console.log(products)
@@ -206,7 +241,8 @@ const ProductList = ({ size = 99999 }) => {
206 241
             lg:"row"
207 242
           }, }}>
208 243
 
209
-          <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
244
+          {/* length 1, cause we know upon selecting by tags, there would be only 1 category, which mean no need to view this option */}
245
+          {(categoryFilterOption.length > 0) && <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
210 246
             <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Category</Typography>
211 247
             <Select
212 248
               value={category}
@@ -219,7 +255,22 @@ const ProductList = ({ size = 99999 }) => {
219 255
               <MenuItem value={'all'}>All</MenuItem>
220 256
               {categoryFilterOption?.map((data) => (<MenuItem value={data}>{data}</MenuItem>))}
221 257
             </Select>
222
-          </FormControl>
258
+          </FormControl>}
259
+
260
+          {(collectionFilterOption.length > 0) && <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
261
+            <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Collection</Typography>
262
+            <Select
263
+              value={collection}
264
+              onChange={(event) => {
265
+                setCollection(event.target.value);
266
+              }}
267
+              input={<BootstrapInput />}
268
+              name="type"
269
+            >
270
+              <MenuItem value={'all'}>All</MenuItem>
271
+              {collectionFilterOption?.map(({title}) => (<MenuItem value={title}>{title}</MenuItem>))}
272
+            </Select>
273
+          </FormControl>}
223 274
 
224 275
           <FormControl sx={{ m: 1, display: "flex", flexDirection: "row" }} variant="standard">
225 276
             <Typography variant="body2" sx={{ mr: 1, my: "auto" }}>Sort</Typography>

+ 23
- 0
src/redux/slices/productSlice.js Wyświetl plik

@@ -51,6 +51,16 @@ export const fetchProductsByCollection = createAsyncThunk(
51 51
   }
52 52
 )
53 53
 
54
+export const fetchProductsByTags = createAsyncThunk(
55
+  'product/fetchProductsByTags',
56
+  async ({tag}) => {
57
+    const response = await ProductService.getProductsByTags(tag)
58
+    console.log(response)
59
+    return response
60
+
61
+  }
62
+)
63
+
54 64
 export const fetchProductsHistory = createAsyncThunk(
55 65
   'product/fetchProductsHistory',
56 66
   async (productIDList) => {
@@ -106,6 +116,19 @@ export const productSlice = createSlice({
106 116
         state.products.data = [];
107 117
         state.products.error = action.error.message;
108 118
       })
119
+      .addCase(fetchProductsByTags.pending, (state) => {
120
+        state.products.status = 'loading';
121
+        state.products.error = null;
122
+      })
123
+      .addCase(fetchProductsByTags.fulfilled, (state, action) => {
124
+        state.products.status = 'succeeded';
125
+        state.products.data = action.payload
126
+      })
127
+      .addCase(fetchProductsByTags.rejected, (state, action) => {
128
+        state.products.status = 'failed';
129
+        state.products.data = [];
130
+        state.products.error = action.error.message;
131
+      })
109 132
       .addCase(fetchProductsHistory.pending, (state) => {
110 133
         state.productsHistory.status = 'loading';
111 134
         state.productsHistory.error = null;

+ 46
- 0
src/services/ProductService.js Wyświetl plik

@@ -170,6 +170,51 @@ const getProductsByCollection = async (collectionId) => {
170 170
   return data.collection.products.nodes
171 171
 }
172 172
 
173
+const getProductsByTags = async (tag) => {
174
+
175
+  let customQuery = `query: "tag:${tag}"`
176
+  if(tag == 'all') customQuery = ''
177
+
178
+  const query = `{
179
+    products(first: 250, ${customQuery}) {
180
+      nodes {
181
+        id
182
+        title
183
+        createdAt
184
+        productType
185
+        tags
186
+        compareAtPriceRange {
187
+          maxVariantPrice {
188
+            amount
189
+            currencyCode
190
+          }
191
+          minVariantPrice {
192
+            amount
193
+            currencyCode
194
+          }
195
+        }
196
+        images(first: 4) {
197
+          nodes {
198
+            src
199
+            url
200
+          }
201
+        }
202
+        collections(first: 5) {
203
+          nodes {
204
+            title
205
+          }
206
+        }
207
+      }
208
+    }
209
+  }`
210
+
211
+  const { data, errors, extensions } = await client.request(query, {
212
+    variables: {},
213
+  });
214
+
215
+  return data.products.nodes
216
+}
217
+
173 218
 const getProductTypes = async () => {
174 219
   const query = `{
175 220
     productTypes(first: 250) {
@@ -274,6 +319,7 @@ const ProductService = {
274 319
   getProducts,
275 320
   getProduct,
276 321
   getProductsByCollection,
322
+  getProductsByTags,
277 323
   getProductTypes,
278 324
   getCollections,
279 325
   getTags

Ładowanie…
Anuluj
Zapisz