azri пре 4 недеља
родитељ
комит
2c7c26005b

+ 9
- 0
src/App.js Прегледај датотеку

@@ -14,6 +14,7 @@ import theme from './theme/theme';
14 14
 import { ThemeProvider } from '@mui/material';
15 15
 import { fetchCart, createCart } from './redux/slices/cartSlice';
16 16
 import { useSelector, useDispatch } from 'react-redux';
17
+import Collection from './pages/Collection';
17 18
 
18 19
 const isEmptyObject = (obj) => Object.keys(obj).length === 0 && obj.constructor === Object;
19 20
 
@@ -61,6 +62,14 @@ function App() {
61 62
           <Route path='/newsletter' element={<Newsletter />} />
62 63
           <Route path='/cart' element={<Cart />} />
63 64
           <Route path='/checkout' element={<Checkout />} />
65
+
66
+          <Route path='collection'>
67
+            {/* All Products */}
68
+            <Route index element={<Products />} />
69
+            {/* Single Product */}
70
+            <Route path=':pid' element={<Collection />} />
71
+          </Route>
72
+
64 73
         </Routes>
65 74
       </BrowserRouter>
66 75
       <Footer />

BIN
src/assets/images/titleBg.jpg Прегледај датотеку


+ 71
- 0
src/components/CollectionList/CollectionList.jsx Прегледај датотеку

@@ -0,0 +1,71 @@
1
+import { useEffect, useState } from "react";
2
+import { Box, Typography, Button } from "@mui/material";
3
+import ProductService from "../../services/ProductService";
4
+import Grid from '@mui/material/Grid2';
5
+
6
+const CollectionList = ({ collectionName }) => {
7
+
8
+  const [collections, setCollections] = useState([])
9
+
10
+  useEffect(() => {
11
+
12
+    ProductService.getCollections(collectionName).then((data) => {
13
+      setCollections(data)
14
+    })
15
+
16
+  }, [])
17
+
18
+
19
+
20
+  return (
21
+    <Box sx={{ flexGrow: 1, mt: 10 }}>
22
+      <Grid container spacing={2}>
23
+
24
+        {collections.map(({id, name, src}) => {
25
+
26
+          return (<Grid size={12}>
27
+            <Box
28
+              sx={{
29
+                position: 'relative',
30
+                width: '100%',
31
+                height: 0,
32
+                backgroundImage: `url("${src}")`,
33
+                backgroundSize: "cover",
34
+                backgroundPosition: "top center",
35
+                paddingTop: '600px', // This sets the height based on top padding
36
+                overflow: 'hidden',
37
+              }}
38
+            >
39
+              <Box
40
+                sx={{
41
+                  position: 'absolute',
42
+                  top: 0,
43
+                  left: 0,
44
+                  width: '100%',
45
+                  height: '100%',
46
+                  backgroundColor: 'rgba(0, 0, 0, 0.5)', // Filter overlay
47
+                  display: 'flex',
48
+                  flexDirection: 'column',
49
+                  justifyContent: 'center',
50
+                  alignItems: 'center',
51
+                  color: '#fff', // Text and button color for visibility
52
+                }}
53
+              >
54
+                <Typography variant="h4" gutterBottom>
55
+                  {name}
56
+                </Typography>
57
+                <Button onClick={()=>{ window.location.href = "/products" }} variant="contained" color="primary">
58
+                  SHOP NOW
59
+                </Button>
60
+              </Box>
61
+            </Box>
62
+          </Grid>)
63
+        })}
64
+
65
+
66
+      </Grid>
67
+    </Box>
68
+  );
69
+};
70
+
71
+export default CollectionList;

+ 1
- 0
src/components/CollectionList/index.js Прегледај датотеку

@@ -0,0 +1 @@
1
+export { default } from "./CollectionList"

+ 41
- 0
src/components/CollectionViewer/ProductType.jsx Прегледај датотеку

@@ -0,0 +1,41 @@
1
+import React from 'react';
2
+import { Box, Button, Typography } from '@mui/material';
3
+
4
+const ProductType = () => {
5
+  return (
6
+    <Box
7
+      sx={{
8
+        position: 'relative',
9
+        width: '100%',
10
+        height: 0,
11
+        paddingTop: '600px', // This sets the height based on top padding
12
+        overflow: 'hidden',
13
+      }}
14
+    >
15
+      <Box
16
+        sx={{
17
+          position: 'absolute',
18
+          top: 0,
19
+          left: 0,
20
+          width: '100%',
21
+          height: '100%',
22
+          backgroundColor: 'rgba(0, 0, 0, 0.5)', // Filter overlay
23
+          display: 'flex',
24
+          flexDirection: 'column',
25
+          justifyContent: 'center',
26
+          alignItems: 'center',
27
+          color: '#fff', // Text and button color for visibility
28
+        }}
29
+      >
30
+        <Typography variant="h4" gutterBottom>
31
+          Some Type
32
+        </Typography>
33
+        <Button variant="contained" color="primary">
34
+          SHOP NOW
35
+        </Button>
36
+      </Box>
37
+    </Box>
38
+  );
39
+};
40
+
41
+export default ProductType;

+ 1
- 0
src/components/CollectionViewer/index.js Прегледај датотеку

@@ -0,0 +1 @@
1
+export { default } from './ProductType'

+ 24
- 21
src/components/Navbar/Navbar.jsx Прегледај датотеку

@@ -19,6 +19,7 @@ import BrushIcon from '@mui/icons-material/Brush';
19 19
 import LoyaltyIcon from '@mui/icons-material/Loyalty';
20 20
 import Grid from '@mui/material/Grid2';
21 21
 import { useSelector } from 'react-redux';
22
+import ProductService from "../../services/ProductService";
22 23
 
23 24
 function calculateTotalQuantity(cartItems) {
24 25
   return cartItems.reduce((total, item) => total + item.quantity, 0);
@@ -55,25 +56,6 @@ const LanguageSelectItem = styled(MenuItem)(() => ({
55 56
   },
56 57
 }));
57 58
 
58
-const navItem = [
59
-  {
60
-    title: "DISCOVER",
61
-    link: "/products",
62
-    icon: <CategoryIcon />
63
-  },
64
-  {
65
-    title: "HOME",
66
-    link: "/products",
67
-    icon: <HomeIcon />
68
-  },
69
-  {
70
-    title: "BEAUTY",
71
-    link: "/products",
72
-    icon: <BrushIcon />
73
-  }
74
-]
75
-
76
-
77 59
 const Navbar = () => {
78 60
 
79 61
   const [showHeader, setShowHeader] = useState(true);
@@ -84,6 +66,29 @@ const Navbar = () => {
84 66
   const [cartAmount, setCartAmount] = useState(0);
85 67
 
86 68
   const [open, setOpen] = React.useState(false);
69
+  const [navItem, setNavItem] = useState([])
70
+
71
+  useEffect(()=>{
72
+    fetchProductTypes()
73
+  },[])
74
+
75
+  const fetchProductTypes = async () => {
76
+    try {
77
+      const data = await ProductService.getProductTypes();
78
+  
79
+      if (Array.isArray(data)) {
80
+
81
+        let navItemData = data.map(({node})=>({title:`${node.toUpperCase()}`, link:`/collection/${node}` }))
82
+        setNavItem(navItemData);
83
+
84
+      } else {
85
+        setNavItem([]); 
86
+      }
87
+    } catch (error) {
88
+      console.error("Error fetching product types:", error);
89
+      setNavItem([]); // Handle error by setting fallback empty array
90
+    }
91
+  };
87 92
 
88 93
   useEffect(() => {
89 94
 
@@ -93,8 +98,6 @@ const Navbar = () => {
93 98
 
94 99
   }, [cart])
95 100
 
96
-
97
-
98 101
   const handleChange = (event) => {
99 102
     setLanguage(event.target.value);
100 103
   };

+ 1
- 2
src/components/Navbar/components/MobileNav/MobileNav.jsx Прегледај датотеку

@@ -40,7 +40,7 @@ const MobileNav = ({ open, onClose, menu = [] }) => {
40 40
       {/* Main Navigation */}
41 41
       <Box sx={{ width: 250 }} role="presentation">
42 42
         <List>
43
-          {menu.map(({ title, link, icon }) => (
43
+          {menu.map(({ title, link }) => (
44 44
             <ListItem key={title} disablePadding>
45 45
               <ListItemButton
46 46
                 onClick={() => { window.location.href = link }}
@@ -52,7 +52,6 @@ const MobileNav = ({ open, onClose, menu = [] }) => {
52 52
                   },
53 53
                 }}
54 54
               >
55
-                {icon}
56 55
                 <ListItemText sx={{ ml: 2 }} primary={title} />
57 56
               </ListItemButton>
58 57
             </ListItem>

+ 6
- 4
src/components/PageTitle/PageTitle.jsx Прегледај датотеку

@@ -1,16 +1,18 @@
1 1
 import React from "react";
2 2
 import Box from "@mui/material/Box";
3
+
3 4
 import Typography from "@mui/material/Typography";
4 5
 
5
-const PageTitle = () => {
6
+const PageTitle = ({title = "", image = ""}) => {
7
+
6 8
   return (
7 9
     <Box
8 10
       sx={{
9 11
         position: "relative",
10 12
         minHeight: "300px",
11
-        backgroundImage: `url("https://p16-va.lemon8cdn.com/tos-alisg-v-a3e477-sg/1bab0c0797934592bb5a705ad62ed4c4~tplv-tej9nj120t-origin.webp")`,
13
+        backgroundImage: `url("${image}")`,
12 14
         backgroundSize: "cover",
13
-        backgroundPosition: "center",
15
+        backgroundPosition: "top center",
14 16
         color: "white",
15 17
         textAlign: "center",
16 18
         overflow: "hidden", // Ensures the dim layer stays inside the box
@@ -39,7 +41,7 @@ const PageTitle = () => {
39 41
           margin:"auto auto"
40 42
         }}
41 43
       >
42
-        ATMA SARI COLLECTION
44
+        {title.toUpperCase() || " "}
43 45
       </Typography>
44 46
     </Box>
45 47
   );

+ 1
- 1
src/components/ProductSelected/ProductSelected.jsx Прегледај датотеку

@@ -11,7 +11,7 @@ const ProductSelected = () => {
11 11
 
12 12
   useEffect(() => {
13 13
 
14
-    dispatch(fetchProducts())
14
+    dispatch(fetchProducts({maxResults: 4, sortBy:'TITLE', customQuery:"tag:new"}))
15 15
 
16 16
   }, [])
17 17
 

+ 5
- 5
src/pages/Cart.jsx Прегледај датотеку

@@ -138,6 +138,10 @@ const Cart = () => {
138 138
 
139 139
                     </TableCell>
140 140
 
141
+                    <TableCell align='center'>
142
+                      <Typography variant='body2' sx={{ fontWeight: "bold" }} >{title}</Typography>
143
+                    </TableCell>
144
+
141 145
                     <TableCell align='center'>
142 146
                       <Box sx={{ display: "flex", justifyContent: "center" }}>
143 147
 
@@ -159,15 +163,11 @@ const Cart = () => {
159 163
 
160 164
                       </Box>
161 165
                     </TableCell>
162
-                    
163
-                    <TableCell align='center'>
164
-                      <Typography variant='body2' sx={{ fontWeight: "bold" }} >{title}</Typography>
165
-                    </TableCell>
166 166
 
167 167
                     <TableCell align='center'>
168 168
                       <Typography variant='h6' sx={{ fontWeight: "bold" }}>{`${currencyCode} ${parseFloat(amount).toFixed(2)}`}</Typography>
169 169
                     </TableCell>
170
-
170
+                    
171 171
                   </TableRow>
172 172
                 )
173 173
 

+ 46
- 0
src/pages/Collection.jsx Прегледај датотеку

@@ -0,0 +1,46 @@
1
+import { useEffect } from 'react'
2
+import { useParams } from 'react-router-dom'
3
+import PageTitle from '../components/PageTitle'
4
+import Filter from '../components/Filter'
5
+import ProductList from '../components/ProductList'
6
+import { Box } from '@mui/material'
7
+import SocialMedia from '../components/SocialMedia'
8
+import Feature from '../components/Feature'
9
+import { useSelector, useDispatch } from 'react-redux'
10
+import { fetchProducts } from '../redux/slices/productSlice'
11
+import image from "../assets/images/titleBg.jpg"
12
+import CollectionList from '../components/CollectionList/CollectionList'
13
+
14
+const Collection = () => {
15
+
16
+  let { pid } = useParams();
17
+  const dispatch = useDispatch();
18
+
19
+  useEffect(()=>{
20
+
21
+   //dispatch(fetchProducts(250, 'created_at',  `product_type:${pid}`))
22
+
23
+  }, [])
24
+
25
+  return (
26
+    <>
27
+      <PageTitle title={`${pid} COLLECTIONS`} image={image} />
28
+      <CollectionList collectionName={pid}/>
29
+      <Box sx={{
30
+        px: {
31
+          xs: 2,
32
+          md: 12,
33
+          lg: 20
34
+        },
35
+        mb: {
36
+          xs: 0,
37
+          md: 5,
38
+          lg: 10
39
+        }
40
+      }}>
41
+      </Box>
42
+    </>
43
+  )
44
+}
45
+
46
+export default Collection

+ 1
- 1
src/pages/Home.jsx Прегледај датотеку

@@ -58,7 +58,7 @@ const Home = () => {
58 58
           </Grid>
59 59
 
60 60
           <Grid size={{xs:12, md:2}} sx={{display:"flex", alignItems:"center", py:{xs:2, md:0} }}>
61
-            <Link href="#" sx={{ color:"#000", textDecoration: "underline", m:{xs:"auto auto auto auto", md:"0 0 0 auto"}}}>VIEW ALL</Link>
61
+            <Link href="/product" sx={{ color:"#000", textDecoration: "underline", m:{xs:"auto auto auto auto", md:"0 0 0 auto"}}}>VIEW ALL</Link>
62 62
           </Grid>
63 63
 
64 64
         </Grid>

+ 0
- 1
src/pages/Products/Product.jsx Прегледај датотеку

@@ -18,7 +18,6 @@ const Product = () => {
18 18
   const product = useSelector((state) => state.products.product.data)
19 19
   const dispatch = useDispatch();
20 20
   
21
-
22 21
   useEffect(() => {
23 22
 
24 23
     dispatch(fetchProduct(pid))

+ 3
- 2
src/redux/slices/productSlice.js Прегледај датотеку

@@ -33,8 +33,9 @@ export const fetchProduct = createAsyncThunk(
33 33
 
34 34
 export const fetchProducts = createAsyncThunk(
35 35
   'product/fetchProducts',
36
-  async () => {
37
-    const response = await ProductService.getProducts()
36
+  async ({maxResults, sortBy, customQuery}) => {
37
+
38
+    const response = await ProductService.getProducts(maxResults, sortBy, customQuery)
38 39
     return response
39 40
 
40 41
   }

+ 69
- 3
src/services/ProductService.js Прегледај датотеку

@@ -2,7 +2,7 @@ import { createStorefrontApiClient } from '@shopify/storefront-api-client';
2 2
 import { REACT_APP_ACCESS_TOKEN, REACT_APP_SHOP_NAME } from '../utils/httpCommon'
3 3
 
4 4
 const defaultQuery = 'status:active, product_type:clothing, product_categroy:dresses';
5
-const defaultResult = 10;
5
+const defaultResult = 250;
6 6
 const defaultSortBy = 'TITLE';
7 7
 
8 8
 const client = createStorefrontApiClient({
@@ -15,7 +15,7 @@ const client = createStorefrontApiClient({
15 15
 const getProducts = async (maxResults = defaultResult, sortBy = defaultSortBy, customQuery = defaultQuery) => {
16 16
 
17 17
   const query = `{
18
-    products(first: ${maxResults}, query: "${customQuery}", sortKey: ${sortBy}) {
18
+    products(first: ${maxResults}, query: "${customQuery}", sortKey:${sortBy}) {
19 19
       nodes {
20 20
         id
21 21
         title
@@ -65,6 +65,8 @@ const getProducts = async (maxResults = defaultResult, sortBy = defaultSortBy, c
65 65
     },
66 66
   });
67 67
 
68
+  debugger
69
+
68 70
   return data.products.nodes
69 71
 
70 72
 }
@@ -126,10 +128,74 @@ const getProduct = async (id = "") => {
126 128
 
127 129
 }
128 130
 
131
+const getProductTypes = async () => {
132
+  const query = `{
133
+    productTypes(first: 250) {
134
+      edges {
135
+        node
136
+      }
137
+    }  
138
+  }`
139
+
140
+  const { data, errors, extensions } = await client.request(query, {
141
+    variables: {},
142
+  });
143
+
144
+  return data.productTypes.edges
145
+}
146
+
147
+const getCollections = async (name) => {
148
+
149
+  const query = `{
150
+    products(first: 250, query: "product_type:${name}") {
151
+      nodes {
152
+        createdAt
153
+        productType
154
+        collections(first: 1) {
155
+          nodes {
156
+            title
157
+            id
158
+            image {
159
+              src
160
+            }
161
+          }
162
+        }
163
+      }
164
+    }
165
+  }`
166
+
167
+  const { data, errors, extensions } = await client.request(query, {
168
+    variables: {},
169
+  });
170
+
171
+  const uniqueCollections = new Map();
172
+
173
+  // Iterate through all products
174
+  data.products.nodes.forEach((product) => {
175
+    // Iterate through each collection within a product
176
+    product.collections.nodes.forEach((collection) => {
177
+      const { title, id, image } = collection;
178
+
179
+      // Use the collection ID as a unique key to avoid duplicates
180
+      if (!uniqueCollections.has(id)) {
181
+        uniqueCollections.set(id, {
182
+          name: title,
183
+          id,
184
+          src: image ? image.src : null, // Handle null image gracefully
185
+        });
186
+      }
187
+    });
188
+  });
189
+
190
+  return Array.from(uniqueCollections.values());
191
+
192
+}
129 193
 
130 194
 const ProductService = {
131 195
   getProducts,
132
-  getProduct
196
+  getProduct,
197
+  getProductTypes,
198
+  getCollections
133 199
 }
134 200
 
135 201
 export default ProductService

Loading…
Откажи
Сачувај