Browse Source

shopping bag

master
azri 11 hours ago
parent
commit
a646356766

+ 1
- 4
src/App.js View File

30
     // if we got cart, then just fetch from BE based on ID
30
     // if we got cart, then just fetch from BE based on ID
31
     if (!isEmptyObject(cartHistory)) {
31
     if (!isEmptyObject(cartHistory)) {
32
 
32
 
33
-      let cartId = cartHistory.id.split('/')
34
-      cartId = cartId[cartId.length - 1]
35
-
36
-      dispatch(fetchCart("gid://shopify/Cart/Z2NwLWFzaWEtc291dGhlYXN0MTowMUpGTkVDODRQNFY2RUtNV1JZTlJDVFBQNA?key=6d58758401066b048e3795c9cf0fa716"));
33
+      dispatch(fetchCart(cartHistory.id));
37
 
34
 
38
     }
35
     }
39
 
36
 

+ 41
- 23
src/components/Navbar/Navbar.jsx View File

17
 import HomeIcon from '@mui/icons-material/Home';
17
 import HomeIcon from '@mui/icons-material/Home';
18
 import BrushIcon from '@mui/icons-material/Brush';
18
 import BrushIcon from '@mui/icons-material/Brush';
19
 import LoyaltyIcon from '@mui/icons-material/Loyalty';
19
 import LoyaltyIcon from '@mui/icons-material/Loyalty';
20
+import { useSelector } from 'react-redux';
21
+
22
+function calculateTotalQuantity(cartItems) {
23
+  return cartItems.reduce((total, item) => total + item.quantity, 0);
24
+}
20
 
25
 
21
 const LanguageSelect = styled(Select)(({ theme }) => ({
26
 const LanguageSelect = styled(Select)(({ theme }) => ({
22
   backgroundColor: 'black',
27
   backgroundColor: 'black',
49
   },
54
   },
50
 }));
55
 }));
51
 
56
 
57
+const navItem = [
58
+  {
59
+    title: "DISCOVER",
60
+    link: "/products",
61
+    icon: <CategoryIcon />
62
+  },
63
+  {
64
+    title: "HOME",
65
+    link: "/",
66
+    icon: <HomeIcon />
67
+  },
68
+  {
69
+    title: "BEAUTY",
70
+    link: "/products",
71
+    icon: <BrushIcon />
72
+  },
73
+  {
74
+    title: "SALE",
75
+    link: "/products",
76
+    icon: <LoyaltyIcon />
77
+  }
78
+]
79
+
52
 
80
 
53
 const Navbar = () => {
81
 const Navbar = () => {
54
 
82
 
55
   const [showHeader, setShowHeader] = useState(true);
83
   const [showHeader, setShowHeader] = useState(true);
56
   const [lastScrollPos, setLastScrollPos] = useState(0);
84
   const [lastScrollPos, setLastScrollPos] = useState(0);
57
   const [language, setLanguage] = useState('English');
85
   const [language, setLanguage] = useState('English');
86
+  
87
+  const cart = useSelector((state) => state.cart.cart)
88
+  const [cartAmount, setCartAmount] = useState(0);
58
 
89
 
59
   const [open, setOpen] = React.useState(false);
90
   const [open, setOpen] = React.useState(false);
91
+  
92
+  useEffect(() => {
93
+    
94
+    if(!cart?.lines?.nodes) return // don't need to do anything if we have no cart data
95
+
96
+    setCartAmount(calculateTotalQuantity(cart?.lines?.nodes))
97
+
98
+  }, [cart])
99
+  
60
 
100
 
61
-  const navItem = [
62
-    {
63
-      title: "DISCOVER",
64
-      link: "/products",
65
-      icon: <CategoryIcon />
66
-    },
67
-    {
68
-      title: "HOME",
69
-      link: "/",
70
-      icon: <HomeIcon />
71
-    },
72
-    {
73
-      title: "BEAUTY",
74
-      link: "/products",
75
-      icon: <BrushIcon />
76
-    },
77
-    {
78
-      title: "SALE",
79
-      link: "/products",
80
-      icon: <LoyaltyIcon />
81
-    }
82
-  ]
83
 
101
 
84
   const handleChange = (event) => {
102
   const handleChange = (event) => {
85
     setLanguage(event.target.value);
103
     setLanguage(event.target.value);
228
               <SearchIcon sx={{ color: "white" }} />
246
               <SearchIcon sx={{ color: "white" }} />
229
             </IconButton>
247
             </IconButton>
230
 
248
 
231
-            <Badge sx={{cursor:"pointer"}} onClick={()=>{ window.location.href = "/cart" }} badgeContent={1} color="primary">
249
+            <Badge sx={{cursor:"pointer"}} onClick={()=>{ window.location.href = "/cart" }} badgeContent={cartAmount} color="primary">
232
               <LocalMallIcon color="action" sx={{ color: "white" }} />
250
               <LocalMallIcon color="action" sx={{ color: "white" }} />
233
             </Badge>
251
             </Badge>
234
 
252
 

+ 56
- 21
src/components/ProductDetails/ProductDetails.jsx View File

3
   Box,
3
   Box,
4
   Typography,
4
   Typography,
5
   Button,
5
   Button,
6
-  TextField
6
+  TextField,
7
+  CircularProgress
7
 } from "@mui/material";
8
 } from "@mui/material";
8
 import AddIcon from '@mui/icons-material/Add';
9
 import AddIcon from '@mui/icons-material/Add';
9
 import RemoveIcon from '@mui/icons-material/Remove';
10
 import RemoveIcon from '@mui/icons-material/Remove';
10
 import { useSelector, useDispatch } from "react-redux";
11
 import { useSelector, useDispatch } from "react-redux";
11
-import { createCart } from "../../redux/slices/cartSlice";
12
+import { createCart, addItemToCart } from "../../redux/slices/cartSlice";
13
+import Alert from '@mui/material/Alert';
14
+import AlertTitle from '@mui/material/AlertTitle';
12
 
15
 
13
 // Utility function to check if an object is empty
16
 // Utility function to check if an object is empty
14
 const isEmptyObject = (obj) => Object.keys(obj).length === 0 && obj.constructor === Object;
17
 const isEmptyObject = (obj) => Object.keys(obj).length === 0 && obj.constructor === Object;
31
     quantityAvailable: 0
34
     quantityAvailable: 0
32
   })
35
   })
33
   const [variants, setVariants] = useState([])
36
   const [variants, setVariants] = useState([])
37
+  const [showLoader, setShowLoader] = useState(false)
38
+  const [alert, setAlert] = useState({ open: false, severity: '', message: '' });
34
 
39
 
35
   useEffect(() => {
40
   useEffect(() => {
36
     if (product) {
41
     if (product) {
138
     let cartHistory = localStorage.getItem('amber-cart');
143
     let cartHistory = localStorage.getItem('amber-cart');
139
     cartHistory = cartHistory ? JSON.parse(cartHistory) : {};
144
     cartHistory = cartHistory ? JSON.parse(cartHistory) : {};
140
 
145
 
146
+    setShowLoader(true) //cause I want to prevent user from mutiple clicking
147
+
141
     // if we got no cart, then create a new one
148
     // if we got no cart, then create a new one
142
     if (isEmptyObject(cart) || isEmptyObject(cartHistory)) {
149
     if (isEmptyObject(cart) || isEmptyObject(cartHistory)) {
143
 
150
 
144
-      dispatch(createCart());
151
+      dispatch(createCart())
152
+      .then(() => {
153
+        showAlert('success', 'Cart created successfully!');
154
+      })
155
+      .catch(() => {
156
+        showAlert('error', 'Failed to create cart. Please try again.');
157
+      })
158
+      .finally(() => setShowLoader(false));
145
 
159
 
146
     } else {
160
     } else {
147
 
161
 
148
-      // // Update cart content
149
-      // const existingItemIndex = cartHistory.lines?.findIndex(
150
-      //   (line) => line.merchandiseId === item.merchandiseId
151
-      // );
152
-
153
-      // if (existingItemIndex !== -1) {
154
-      //   // If the item exists, update the quantity
155
-      //   cartHistory.lines[existingItemIndex].quantity += item.quantity;
156
-      // } else {
157
-      //   // If the item doesn't exist, add it
158
-      //   cartHistory.lines = [...(cartHistory.lines || []), item];
159
-      // }
160
-
161
-      // // Update Redux store and localStorage
162
-      // dispatch(updateCart(cartHistory)); // Redux action to update cart
163
-      // localStorage.setItem('amber-cart', JSON.stringify(cartHistory));
162
+      console.log("ADD ITEM:", variantSelection)
163
+      
164
+      dispatch(addItemToCart({
165
+        cartId: cartHistory.id,
166
+        lines:[
167
+          {
168
+            merchandiseId:variantSelection.id,
169
+            quantity
170
+          }
171
+        ]
172
+      }))
173
+      .then(() => {
174
+        showAlert('success', 'Item added to cart successfully!');
175
+      })
176
+      .catch(() => {
177
+        showAlert('error', 'Failed to add item to cart. Please try again.');
178
+      })
179
+      .finally(() => setShowLoader(false));
164
     }
180
     }
165
 
181
 
166
   }
182
   }
167
 
183
 
184
+  const showAlert = (severity, message) => {
185
+    setAlert({ open: true, severity, message });
186
+
187
+    // Auto-close the alert after 3 seconds
188
+    setTimeout(() => {
189
+      setAlert({ ...alert, open: false });
190
+    }, 2000);
191
+  };
192
+
168
   const handleIncrement = () => {
193
   const handleIncrement = () => {
169
     setQuantity((prevQuantity) => (prevQuantity >= variantSelection.quantityAvailable ? variantSelection.quantityAvailable : prevQuantity + 1));
194
     setQuantity((prevQuantity) => (prevQuantity >= variantSelection.quantityAvailable ? variantSelection.quantityAvailable : prevQuantity + 1));
170
   };
195
   };
282
           variant="contained"
307
           variant="contained"
283
           color="common.black"
308
           color="common.black"
284
           fullWidth
309
           fullWidth
310
+          disabled={variantSelection?.quantityAvailable == 0 || showLoader}
285
           sx={{
311
           sx={{
286
             backgroundColor: (theme) => theme.palette.common.black,
312
             backgroundColor: (theme) => theme.palette.common.black,
287
             color: "white",
313
             color: "white",
292
             },
318
             },
293
           }}
319
           }}
294
         >
320
         >
295
-          ADD TO CART
321
+          ADD TO CART {showLoader && <CircularProgress sx={{ml:1}} color="white" size={20} />} 
296
         </Button>
322
         </Button>
297
       </Box>
323
       </Box>
298
-
324
+      {alert.open && (
325
+        <Alert
326
+          severity={alert.severity}
327
+          onClose={() => setAlert({ ...alert, open: false })}
328
+          sx={{ marginTop: 2 }}
329
+        >
330
+          <AlertTitle>{alert.severity === 'success' ? 'Success' : 'Error'}</AlertTitle>
331
+          {alert.message}
332
+        </Alert>
333
+      )}
299
     </Box>
334
     </Box>
300
   );
335
   );
301
 };
336
 };

+ 95
- 93
src/pages/Cart.jsx View File

1
-import React from 'react'
1
+import { useEffect, useState } from 'react'
2
 import { Box, Button, IconButton } from '@mui/material'
2
 import { Box, Button, IconButton } from '@mui/material'
3
 import SocialMedia from '../components/SocialMedia'
3
 import SocialMedia from '../components/SocialMedia'
4
 import Feature from '../components/Feature'
4
 import Feature from '../components/Feature'
12
 import TableRow from '@mui/material/TableRow';
12
 import TableRow from '@mui/material/TableRow';
13
 import AddIcon from '@mui/icons-material/Add';
13
 import AddIcon from '@mui/icons-material/Add';
14
 import RemoveIcon from '@mui/icons-material/Remove';
14
 import RemoveIcon from '@mui/icons-material/Remove';
15
+import { useSelector, useDispatch } from 'react-redux';
15
 
16
 
16
 const Cart = () => {
17
 const Cart = () => {
17
 
18
 
18
-  function createData(img_src, description, colour, quantity, price) {
19
-    return { img_src, description, colour, quantity, price };
20
-  }
21
-
22
-  const rows = [
23
-    {
24
-      img_src: 'https://via.placeholder.com/300',
25
-      name: 'MELUR',
26
-      description: 'Atma Sari New Raya Collection 2024',
27
-      colour: 'black',
28
-      quantity: 1,
29
-      price: 335.50
30
-    },
31
-    {
32
-      img_src: 'https://via.placeholder.com/300',
33
-      name: 'MELUR2',
34
-      description: 'Atma Sari New Raya Collection 2025',
35
-      colour: 'red',
36
-      quantity: 2,
37
-      price: 665.00
38
-    },
39
-  ];
19
+  const dispatch = useDispatch()
20
+  const cart = useSelector((state) => state.cart.cart)
21
+  const [cartProducts, setCartProducts] = useState([]) // this is being used as view only, will not used as a way to manipulate cart in any way
22
+
23
+  useEffect(() => {
24
+
25
+    console.log(cart)
26
+
27
+  }, [])
28
+
29
+  useEffect(() => {
30
+    setCartProducts(cart?.lines?.nodes || [])
31
+  }, [cart])
32
+
40
 
33
 
41
   return (
34
   return (
42
     <>
35
     <>
51
           md: 5,
44
           md: 5,
52
           lg: 10
45
           lg: 10
53
         },
46
         },
54
-        mt:10
47
+        mt: 10
55
       }}>
48
       }}>
56
 
49
 
57
 
50
 
58
         {/* Header */}
51
         {/* Header */}
59
-        <Grid container spacing={2} alignItems="center" sx={{ mb: 5, flexDirection: { xs: 'column-reverse', lg: 'row' } }}> 
60
-
61
-          {/* Type */}
62
-          <Grid item size={{xs:12, lg:2}}>
63
-            <Typography variant="body2">
64
-              <p>Mens Fashion <span style={{ fontWeight: "bold", display: "inline-block" }}>Shopping Bag</span></p>
65
-            </Typography>
66
-          </Grid>
52
+        <Grid container spacing={2} alignItems="center" sx={{ mb: 5, flexDirection: { xs: 'column-reverse', lg: 'row' } }}>
67
 
53
 
68
-          <Grid item size={{xs:12, md:4}}>
54
+          <Grid item size={{ xs: 12, md: 4 }}>
69
             <Typography variant="h5" sx={{ fontWeight: "bold" }}>
55
             <Typography variant="h5" sx={{ fontWeight: "bold" }}>
70
               SHOPPING BAG
56
               SHOPPING BAG
71
             </Typography>
57
             </Typography>
85
                   <Typography variant='body1'>Description</Typography>
71
                   <Typography variant='body1'>Description</Typography>
86
                 </TableCell>
72
                 </TableCell>
87
                 <TableCell align='center'>
73
                 <TableCell align='center'>
88
-                  <Typography variant='body1'>Colour</Typography>
74
+                  <Typography variant='body1'>Variant</Typography>
89
                 </TableCell>
75
                 </TableCell>
90
                 <TableCell align='center'>
76
                 <TableCell align='center'>
91
 
77
 
97
               </TableRow>
83
               </TableRow>
98
             </TableHead>
84
             </TableHead>
99
             <TableBody>
85
             <TableBody>
100
-              {rows.map((row) => (
101
-                <TableRow
102
-                  key={row.id}
103
-                  sx={{
104
-                    '& td, & th': { border: 0 },
105
-                    '&:last-child td, &:last-child th': { border: 0 }
106
-                  }}
107
-                >
108
-                  <TableCell component="th" scope="row">
109
-                    <img
110
-                      src={row.img_src}
111
-                      alt={row.img_src}
112
-                      style={{
113
-                        width: 100,
114
-                        height: 100,
115
-                        aspectRatio: '4 / 4',
116
-                        objectFit: 'cover',
117
-                      }}
118
-                    />
119
-                  </TableCell>
120
-                  <TableCell>
121
-                    <Typography variant='body2' sx={{ fontWeight: "bold", mb: 1 }}>{row.name}</Typography>
122
-                    <Typography variant='body2'>{row.description}</Typography>
123
-                  </TableCell>
124
-                  <TableCell align='center'>
125
-                    <Typography variant='h6' sx={{ fontWeight: "bold" }} >{row.colour}</Typography>
126
-                  </TableCell>
127
-                  <TableCell align='center'>
128
-                    <Box sx={{ display: "flex", justifyContent: "center" }}>
129
-                      <IconButton>
130
-                        <RemoveIcon sx={{ fontSize: 16, margin: "0 15px" }} />
131
-                      </IconButton>
132
-                      <p style={{ fontSize: 20, fontWeight: "bold" }}>{row.quantity}</p>
133
-                      <IconButton >
134
-                        <AddIcon sx={{ fontSize: 16, margin: "0 15px" }} />
135
-                      </IconButton>
136
-                    </Box>
137
-                  </TableCell>
138
-                  <TableCell align='center'>
139
-                    <Typography variant='h6' sx={{ fontWeight: "bold" }}>{`RM ${parseFloat(row.price).toFixed(2)}`}</Typography>
140
-                  </TableCell>
141
-                </TableRow>
142
-              ))}
86
+              {cartProducts?.map(({ cost, merchandise, quantity }) => {
87
+                
88
+                let {amount, currencyCode} = cost.totalAmount
89
+                let {id, image, product, title } = merchandise // the title here is actually the variant title name
90
+
91
+                return (
92
+                  <TableRow
93
+                    key={id}
94
+                    sx={{
95
+                      '& td, & th': { border: 0 },
96
+                      '&:last-child td, &:last-child th': { border: 0 }
97
+                    }}
98
+                  >
99
+                    <TableCell component="th" scope="row">
100
+                      <img
101
+                        src={image.src}
102
+                        alt={image.src}
103
+                        style={{
104
+                          width: 100,
105
+                          height: 100,
106
+                          aspectRatio: '4 / 4',
107
+                          objectFit: 'cover',
108
+                          objectPosition:"top center"
109
+                        }}
110
+                      />
111
+                    </TableCell>
112
+                    <TableCell>
113
+                      <Typography variant='body2' sx={{ fontWeight: "bold", mb: 1 }}>{product.title}</Typography>
114
+                      
115
+                      {product?.collections?.nodes?.map(({title}) => (<Typography variant='body2'>{title}</Typography>) )}
116
+
117
+                    </TableCell>
118
+                    <TableCell align='center'>
119
+                      <Typography variant='body2' sx={{ fontWeight: "bold" }} >{title}</Typography>
120
+                    </TableCell>
121
+                    <TableCell align='center'>
122
+                      <Box sx={{ display: "flex", justifyContent: "center" }}>
123
+                        <IconButton>
124
+                          <RemoveIcon sx={{ fontSize: 16, margin: "0 15px" }} />
125
+                        </IconButton>
126
+                        <p style={{ fontSize: 20, fontWeight: "bold" }}>{quantity}</p>
127
+                        <IconButton >
128
+                          <AddIcon sx={{ fontSize: 16, margin: "0 15px" }} />
129
+                        </IconButton>
130
+                      </Box>
131
+                    </TableCell>
132
+                    <TableCell align='center'>
133
+                      <Typography variant='h6' sx={{ fontWeight: "bold" }}>{`${currencyCode} ${parseFloat(amount).toFixed(2)}`}</Typography>
134
+                    </TableCell>
135
+                  </TableRow>
136
+                )
137
+
138
+              })}
143
             </TableBody>
139
             </TableBody>
144
           </Table>
140
           </Table>
145
         </TableContainer>
141
         </TableContainer>
147
         {/* INVOICES */}
143
         {/* INVOICES */}
148
         <Grid container spacing={2} sx={{ mb: 5 }}>
144
         <Grid container spacing={2} sx={{ mb: 5 }}>
149
 
145
 
150
-          <Grid item size={{xs:12, sm:4, md:3}} sx={{ ml: "auto" }}>
146
+          <Grid item size={{ xs: 12, sm: 4, md: 3 }} sx={{ ml: "auto" }}>
151
             <Box
147
             <Box
152
               display="flex"
148
               display="flex"
153
               justifyContent="space-between"
149
               justifyContent="space-between"
155
               sx={{ mb: 2 }}
151
               sx={{ mb: 2 }}
156
             >
152
             >
157
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Subtotal</Typography>
153
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Subtotal</Typography>
158
-              <Typography variant="body1" sx={{ fontWeight: "400" }}>{`RM ${parseFloat(500).toFixed(2)}`}</Typography>
159
-            </Box>
160
-            <Box
161
-              display="flex"
162
-              justifyContent="space-between"
163
-              alignItems="center"
164
-              sx={{ mb: 2 }}
165
-            >
166
-              <Typography variant="body1" sx={{ fontWeight: "400" }}>Shipping</Typography>
167
-              <Typography variant="body1" sx={{ fontWeight: "400" }}>{`RM ${parseFloat(500).toFixed(2)}`}</Typography>
154
+              <Typography variant="body1" sx={{ fontWeight: "400" }}>
155
+                {`
156
+                  ${cart?.cost?.subtotalAmount?.currencyCode} 
157
+                  ${parseFloat(cart?.cost?.subtotalAmount?.amount).toFixed(2)}
158
+                `}
159
+              </Typography>
168
             </Box>
160
             </Box>
169
             <Box
161
             <Box
170
               display="flex"
162
               display="flex"
173
               sx={{ mb: 2 }}
165
               sx={{ mb: 2 }}
174
             >
166
             >
175
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Taxes</Typography>
167
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Taxes</Typography>
176
-              <Typography variant="body1" sx={{ fontWeight: "400" }}>{`RM ${parseFloat(500).toFixed(2)}`}</Typography>
168
+              <Typography variant="body1" sx={{ fontWeight: "400" }}>
169
+                {`
170
+                  ${cart?.cost?.totalTaxAmount?.currencyCode} 
171
+                  ${parseFloat(cart?.cost?.totalTaxAmount?.amount).toFixed(2)}
172
+                `}
173
+              </Typography>
177
             </Box>
174
             </Box>
178
             <Box
175
             <Box
179
               display="flex"
176
               display="flex"
182
               sx={{ mb: 2 }}
179
               sx={{ mb: 2 }}
183
             >
180
             >
184
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Total</Typography>
181
               <Typography variant="body1" sx={{ fontWeight: "400" }}>Total</Typography>
185
-              <Typography variant="body1" sx={{ fontWeight: "bold" }}>{`RM ${parseFloat(500).toFixed(2)}`}</Typography>
182
+              <Typography variant="body1" sx={{ fontWeight: "bold" }}>
183
+                {`
184
+                  ${cart?.cost?.totalAmount?.currencyCode} 
185
+                  ${parseFloat(cart?.cost?.totalAmount?.amount).toFixed(2)}
186
+                `}
187
+              </Typography>
186
             </Box>
188
             </Box>
187
           </Grid>
189
           </Grid>
188
 
190
 
190
 
192
 
191
         {/* BUY NOW */}
193
         {/* BUY NOW */}
192
         <Box sx={{ mb: 15 }}>
194
         <Box sx={{ mb: 15 }}>
193
-          <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexDirection:{xs:"column-reverse", md:"row" } }}>
195
+          <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexDirection: { xs: "column-reverse", md: "row" } }}>
194
             <Typography variant='body2'><span style={{ fontWeight: "bolder" }}>NEED HELP?</span> CALL US: +44 (0)10 2345 6789 | EMAIL CUSTOMER CARE | SHIPPING INFORMATION | RETURNS & EXCHANGES</Typography>
196
             <Typography variant='body2'><span style={{ fontWeight: "bolder" }}>NEED HELP?</span> CALL US: +44 (0)10 2345 6789 | EMAIL CUSTOMER CARE | SHIPPING INFORMATION | RETURNS & EXCHANGES</Typography>
195
             <Button
197
             <Button
196
               variant="contained"
198
               variant="contained"
203
                 px: 8,
205
                 px: 8,
204
                 py: 2,
206
                 py: 2,
205
                 mb: {
207
                 mb: {
206
-                  xs:5,
207
-                  md:0
208
+                  xs: 5,
209
+                  md: 0
208
                 },
210
                 },
209
                 "&:hover": {
211
                 "&:hover": {
210
                   backgroundColor: (theme) => theme.palette.grey[900],
212
                   backgroundColor: (theme) => theme.palette.grey[900],

+ 9
- 9
src/redux/slices/cartSlice.js View File

7
   error: null,
7
   error: null,
8
 };
8
 };
9
 
9
 
10
-// Async Thunks
11
 export const createCart = createAsyncThunk(
10
 export const createCart = createAsyncThunk(
12
   'cart/createCart',
11
   'cart/createCart',
13
   async () => {
12
   async () => {
16
   }
15
   }
17
 );
16
 );
18
 
17
 
19
-export const addItemToCart = createAsyncThunk(
20
-  'cart/addItemToCart',
21
-  async ({ cartId, lines }, { rejectWithValue }) => {
18
+export const fetchCart = createAsyncThunk(
19
+  'cart/fetchCart',
20
+  async (cartId, { rejectWithValue }) => {
22
     try {
21
     try {
23
-      const response = await CartService.addItemToCart(cartId, lines);
22
+      const response = await CartService.getCart(cartId);
24
       return response;
23
       return response;
25
     } catch (error) {
24
     } catch (error) {
26
       return rejectWithValue(error.message);
25
       return rejectWithValue(error.message);
28
   }
27
   }
29
 );
28
 );
30
 
29
 
31
-export const fetchCart = createAsyncThunk(
32
-  'cart/fetchCart',
33
-  async (cartId, { rejectWithValue }) => {
30
+export const addItemToCart = createAsyncThunk(
31
+  'cart/addItemToCart',
32
+  async ({ cartId, lines }, { rejectWithValue }) => {
34
     try {
33
     try {
35
-      const response = await CartService.getCart(cartId);
34
+      const response = await CartService.addItemToCart(cartId, lines);
36
       return response;
35
       return response;
37
     } catch (error) {
36
     } catch (error) {
38
       return rejectWithValue(error.message);
37
       return rejectWithValue(error.message);
94
       })
93
       })
95
       .addCase(addItemToCart.fulfilled, (state, action) => {
94
       .addCase(addItemToCart.fulfilled, (state, action) => {
96
         state.status = 'succeeded';
95
         state.status = 'succeeded';
96
+        localStorage.setItem('amber-cart', JSON.stringify(action.payload));
97
         state.cart = action.payload;
97
         state.cart = action.payload;
98
       })
98
       })
99
       .addCase(addItemToCart.rejected, (state, action) => {
99
       .addCase(addItemToCart.rejected, (state, action) => {

+ 84
- 25
src/services/CartService.js View File

17
           createdAt
17
           createdAt
18
           updatedAt
18
           updatedAt
19
         }
19
         }
20
-        userErrors {
21
-          field
22
-          message
23
-        }
24
       }
20
       }
25
     }
21
     }
26
   `;
22
   `;
30
 
26
 
31
 // Add a line item to the cart
27
 // Add a line item to the cart
32
 const addItemToCart = async (cartId, lines) => {
28
 const addItemToCart = async (cartId, lines) => {
29
+
33
   const query = `
30
   const query = `
34
-    mutation AddItemToCart($cartId: ID!, $lines: [CartLineInput!]!) {
31
+    mutation($cartId: ID!, $lines: [CartLineInput!]!) {
35
       cartLinesAdd(cartId: $cartId, lines: $lines) {
32
       cartLinesAdd(cartId: $cartId, lines: $lines) {
36
         cart {
33
         cart {
37
           id
34
           id
35
+          createdAt
36
+          updatedAt
37
+          cost {
38
+            totalAmount {
39
+              amount
40
+              currencyCode
41
+            }
42
+            subtotalAmount {
43
+              amount
44
+              currencyCode
45
+            }
46
+            totalTaxAmount {
47
+              amount
48
+              currencyCode
49
+            }
50
+          }
38
           lines(first: 10) {
51
           lines(first: 10) {
39
-            edges {
40
-              node {
41
-                id
42
-                quantity
43
-                merchandise {
44
-                  ... on ProductVariant {
45
-                    id
52
+            nodes {
53
+              id
54
+              merchandise {
55
+                ... on ProductVariant {
56
+                  id
57
+                  title
58
+                  selectedOptions {
59
+                    name
60
+                    value
61
+                  }
62
+                  image {
63
+                    src
64
+                  }
65
+                  product {
46
                     title
66
                     title
67
+                    collections(first: 5) {
68
+                      nodes {
69
+                        title
70
+                      }
71
+                    }
47
                   }
72
                   }
48
                 }
73
                 }
49
               }
74
               }
75
+              quantity
76
+              cost {
77
+                totalAmount {
78
+                  amount
79
+                  currencyCode
80
+                }
81
+              }
50
             }
82
             }
51
           }
83
           }
52
         }
84
         }
53
-        userErrors {
54
-          field
55
-          message
56
-        }
57
       }
85
       }
58
     }
86
     }
59
   `;
87
   `;
60
   const variables = { cartId, lines };
88
   const variables = { cartId, lines };
61
-  const { data } = await client.request(query, variables);
89
+
90
+  const {data, errors, extensions} = await client.request(query,{
91
+    variables: {
92
+      cartId,
93
+      lines
94
+    }
95
+  });
96
+  
62
   return data.cartLinesAdd.cart;
97
   return data.cartLinesAdd.cart;
63
 };
98
 };
64
 
99
 
80
             amount
115
             amount
81
             currencyCode
116
             currencyCode
82
           }
117
           }
118
+          totalTaxAmount {
119
+            amount
120
+            currencyCode
121
+          }
83
         }
122
         }
84
-        lines(first: 99) {
85
-          edges {
86
-            node {
87
-              id
88
-              quantity
89
-              merchandise {
90
-                ... on ProductVariant {
91
-                  id
123
+        lines(first: 10) {
124
+          nodes {
125
+            id
126
+            merchandise {
127
+              ... on ProductVariant {
128
+                id
129
+                title
130
+                selectedOptions {
131
+                  name
132
+                  value
133
+                }
134
+                image {
135
+                  src
136
+                }
137
+                product {
92
                   title
138
                   title
139
+                  collections(first: 5) {
140
+                    nodes {
141
+                      title
142
+                    }
143
+                  }
93
                 }
144
                 }
94
               }
145
               }
95
             }
146
             }
147
+            quantity
148
+            cost {
149
+              totalAmount {
150
+                amount
151
+                currencyCode
152
+              }
153
+            }
96
           }
154
           }
97
         }
155
         }
98
       }
156
       }
157
+        
99
     }
158
     }
100
   `;
159
   `;
101
 
160
 

Loading…
Cancel
Save