@springmicro/cart 0.7.22 → 0.7.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2701 -2666
- package/dist/index.umd.cjs +49 -49
- package/package.json +3 -3
- package/src/checkout/ReviewCartAndCalculateTaxes.tsx +24 -15
- package/src/checkout/components/AddCard.tsx +66 -43
- package/src/checkout/components/Address.tsx +7 -5
- package/src/checkout/components/StatusBar.tsx +10 -4
- package/src/checkout/index.tsx +13 -10
- package/src/utils/storage.ts +0 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@springmicro/cart",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.23",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@nanostores/persistent": "^0.10.1",
|
|
25
25
|
"@nanostores/query": "^0.3.3",
|
|
26
26
|
"@nanostores/react": "^0.7.2",
|
|
27
|
-
"@springmicro/utils": "^0.7.
|
|
27
|
+
"@springmicro/utils": "^0.7.23",
|
|
28
28
|
"dotenv": "^16.4.5",
|
|
29
29
|
"nanostores": "^0.10.3",
|
|
30
30
|
"react": "^19.2.4",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"vite-plugin-css-injected-by-js": "^3.5.1",
|
|
50
50
|
"yup": "^1.4.0"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "d1f4ad0110ef4cf25f65cc1b59886624db416a78"
|
|
53
53
|
}
|
|
@@ -39,12 +39,18 @@ import { postCheckout } from "../utils/api";
|
|
|
39
39
|
import { CheckoutFieldsType } from ".";
|
|
40
40
|
import CloseIcon from "@mui/icons-material/Close";
|
|
41
41
|
|
|
42
|
-
async function createOrder(
|
|
42
|
+
async function createOrder(
|
|
43
|
+
cart,
|
|
44
|
+
customer_create,
|
|
45
|
+
apiBaseUrl,
|
|
46
|
+
affiliateCode,
|
|
47
|
+
dev,
|
|
48
|
+
) {
|
|
43
49
|
dev && console.log("Creating order");
|
|
44
50
|
// If an order has already been created and hasn't been changed, get the previous order.
|
|
45
51
|
if (cart.order && cart.order.id && cart.order.reference) {
|
|
46
52
|
const res = await fetch(
|
|
47
|
-
`${apiBaseUrl}/api/ecommerce/orders/${cart.order.id}/reference/${cart.order.reference}
|
|
53
|
+
`${apiBaseUrl}/api/ecommerce/orders/${cart.order.id}/reference/${cart.order.reference}`,
|
|
48
54
|
);
|
|
49
55
|
const order = await res.json();
|
|
50
56
|
|
|
@@ -71,6 +77,7 @@ async function createOrder(cart, customer_create, apiBaseUrl, dev) {
|
|
|
71
77
|
image: undefined,
|
|
72
78
|
})),
|
|
73
79
|
},
|
|
80
|
+
affiliate_code: affiliateCode,
|
|
74
81
|
}),
|
|
75
82
|
credentials: "include",
|
|
76
83
|
});
|
|
@@ -92,10 +99,10 @@ async function getTax(apiBaseUrl, taxProvider, items, v, products, dev) {
|
|
|
92
99
|
console.log(
|
|
93
100
|
"Getting product data",
|
|
94
101
|
products,
|
|
95
|
-
products[items[0].product_id]
|
|
102
|
+
products[items[0].product_id],
|
|
96
103
|
);
|
|
97
104
|
const taxable_items = items.filter(
|
|
98
|
-
(i) => i.unit_amount > 0 && products[i.product_id].type != "DONATION"
|
|
105
|
+
(i) => i.unit_amount > 0 && products[i.product_id].type != "DONATION",
|
|
99
106
|
);
|
|
100
107
|
dev && console.log("Taxable items", taxable_items);
|
|
101
108
|
if (taxable_items.length === 0) return { tax_amount: 0 };
|
|
@@ -120,7 +127,7 @@ async function getTax(apiBaseUrl, taxProvider, items, v, products, dev) {
|
|
|
120
127
|
headers: {
|
|
121
128
|
"Content-Type": "application/json",
|
|
122
129
|
},
|
|
123
|
-
}
|
|
130
|
+
},
|
|
124
131
|
);
|
|
125
132
|
return await res.json();
|
|
126
133
|
}
|
|
@@ -145,6 +152,7 @@ export default function ReviewAndCalculateTaxes({
|
|
|
145
152
|
CollectExtraInfo = undefined,
|
|
146
153
|
defaultValues = {},
|
|
147
154
|
dev,
|
|
155
|
+
affiliateCode,
|
|
148
156
|
hideFields = [],
|
|
149
157
|
disableFields = [],
|
|
150
158
|
}) {
|
|
@@ -174,7 +182,8 @@ export default function ReviewAndCalculateTaxes({
|
|
|
174
182
|
name: values.name,
|
|
175
183
|
},
|
|
176
184
|
apiBaseUrl,
|
|
177
|
-
|
|
185
|
+
affiliateCode,
|
|
186
|
+
dev,
|
|
178
187
|
),
|
|
179
188
|
getTax(
|
|
180
189
|
apiBaseUrl,
|
|
@@ -186,7 +195,7 @@ export default function ReviewAndCalculateTaxes({
|
|
|
186
195
|
})),
|
|
187
196
|
values,
|
|
188
197
|
products,
|
|
189
|
-
dev
|
|
198
|
+
dev,
|
|
190
199
|
),
|
|
191
200
|
])
|
|
192
201
|
.then(([order, taxData]) => {
|
|
@@ -212,7 +221,7 @@ export default function ReviewAndCalculateTaxes({
|
|
|
212
221
|
order.reference,
|
|
213
222
|
values,
|
|
214
223
|
"stripe",
|
|
215
|
-
invoiceId
|
|
224
|
+
invoiceId,
|
|
216
225
|
)
|
|
217
226
|
.then(async (data) => {
|
|
218
227
|
dev && console.log("Checkout submitted.", data);
|
|
@@ -324,7 +333,7 @@ export default function ReviewAndCalculateTaxes({
|
|
|
324
333
|
...validationSchemaAddress,
|
|
325
334
|
}
|
|
326
335
|
: validationSchemaBase
|
|
327
|
-
: {}
|
|
336
|
+
: {},
|
|
328
337
|
),
|
|
329
338
|
onSubmit: async (v, helpers) => {
|
|
330
339
|
dev && console.log("Formik submit");
|
|
@@ -405,7 +414,7 @@ export default function ReviewAndCalculateTaxes({
|
|
|
405
414
|
flexDirection: { xs: "column", xl: "row" },
|
|
406
415
|
justifyContent: "center",
|
|
407
416
|
alignItems: { xs: undefined, xl: "flex-start" },
|
|
408
|
-
px: { xs:
|
|
417
|
+
px: { xs: 2, xl: 16 },
|
|
409
418
|
"&>div": { width: { xs: undefined, xl: "50%" } },
|
|
410
419
|
}}
|
|
411
420
|
>
|
|
@@ -475,14 +484,14 @@ function CheckoutActionFields({
|
|
|
475
484
|
const checkoutFields: Record<string, CheckoutFieldsType> = [
|
|
476
485
|
...Object.keys(products).flatMap((productKey) =>
|
|
477
486
|
(products[productKey].actions ?? []).flatMap(
|
|
478
|
-
(action) => action.checkout_fields ?? []
|
|
479
|
-
)
|
|
487
|
+
(action) => action.checkout_fields ?? [],
|
|
488
|
+
),
|
|
480
489
|
),
|
|
481
490
|
// TODO Add this once prices have checkout fields
|
|
482
491
|
...Object.keys(prices).flatMap((priceKey) =>
|
|
483
492
|
(prices[priceKey].actions ?? []).flatMap(
|
|
484
|
-
(action) => action.checkout_fields ?? []
|
|
485
|
-
)
|
|
493
|
+
(action) => action.checkout_fields ?? [],
|
|
494
|
+
),
|
|
486
495
|
),
|
|
487
496
|
|
|
488
497
|
// Overwrites the checkout field to use the last one provided. This allows prices to overwrite product checkout fields if necessary.
|
|
@@ -512,7 +521,7 @@ function CheckoutActionFields({
|
|
|
512
521
|
!(
|
|
513
522
|
checkoutFields[key].hidden === true ||
|
|
514
523
|
checkoutFields[key].hidden === "true"
|
|
515
|
-
)
|
|
524
|
+
),
|
|
516
525
|
)
|
|
517
526
|
.map((key) => {
|
|
518
527
|
const {
|
|
@@ -58,7 +58,7 @@ export type AddCardProps = {
|
|
|
58
58
|
cardRequired?: boolean;
|
|
59
59
|
address?: boolean;
|
|
60
60
|
onSubmit?: (
|
|
61
|
-
values: CreditCardValues & Partial<AddressValues
|
|
61
|
+
values: CreditCardValues & Partial<AddressValues>,
|
|
62
62
|
) => Promise<any>;
|
|
63
63
|
PriceDetails?: JSX.Element;
|
|
64
64
|
formData?: {
|
|
@@ -195,7 +195,6 @@ export const AddCard = ({
|
|
|
195
195
|
display: "flex",
|
|
196
196
|
flexDirection: "row",
|
|
197
197
|
gap: 2,
|
|
198
|
-
width: "100%",
|
|
199
198
|
}}
|
|
200
199
|
>
|
|
201
200
|
<Box sx={{ flexGrow: 1 }}>
|
|
@@ -204,51 +203,75 @@ export const AddCard = ({
|
|
|
204
203
|
<Typography variant="h6" sx={{ mt: 2, mb: 3 }}>
|
|
205
204
|
Billing Address
|
|
206
205
|
</Typography>
|
|
207
|
-
<
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
<Box
|
|
207
|
+
sx={{
|
|
208
|
+
display: "flex",
|
|
209
|
+
flexDirection: "column",
|
|
210
|
+
gap: 2,
|
|
211
|
+
width: "100%",
|
|
212
|
+
}}
|
|
213
|
+
>
|
|
214
|
+
{!hideFields.includes("email") && (
|
|
215
|
+
<AddressEmailField
|
|
216
|
+
formik={formik}
|
|
217
|
+
name="email"
|
|
218
|
+
sx={{ width: "100%" }}
|
|
219
|
+
/>
|
|
220
|
+
)}
|
|
221
|
+
<AddressCountryField
|
|
210
222
|
formik={formik}
|
|
211
|
-
name="
|
|
212
|
-
sx={{
|
|
223
|
+
name="country"
|
|
224
|
+
sx={{ width: "100%" }}
|
|
213
225
|
/>
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
226
|
+
<AddressOrganizationNameField
|
|
227
|
+
formik={formik}
|
|
228
|
+
name="organization"
|
|
229
|
+
sx={{ width: "100%" }}
|
|
230
|
+
/>
|
|
231
|
+
<AddressStreetField
|
|
232
|
+
formik={formik}
|
|
233
|
+
name="line1"
|
|
234
|
+
lineNo="1"
|
|
235
|
+
sx={{ width: "100%" }}
|
|
236
|
+
/>
|
|
237
|
+
<AddressStreetField
|
|
238
|
+
formik={formik}
|
|
239
|
+
name="line2"
|
|
240
|
+
lineNo="2"
|
|
241
|
+
required={false}
|
|
242
|
+
sx={{ width: "100%" }}
|
|
243
|
+
/>
|
|
244
|
+
<Box
|
|
245
|
+
sx={{
|
|
246
|
+
display: "flex",
|
|
247
|
+
flexDirection: { xs: "column", md: "row" },
|
|
248
|
+
gap: 2,
|
|
249
|
+
width: "100%",
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<AddressCityField
|
|
253
|
+
formik={formik}
|
|
254
|
+
name="city"
|
|
255
|
+
sx={{ flex: "2 1 0", minWidth: 0 }}
|
|
256
|
+
/>
|
|
257
|
+
|
|
258
|
+
<AddressRegionField
|
|
259
|
+
formik={formik}
|
|
260
|
+
name="region"
|
|
261
|
+
sx={{ width: 300, flexShrink: 0 }}
|
|
262
|
+
/>
|
|
263
|
+
|
|
264
|
+
<AddressPostalCodeField
|
|
265
|
+
formik={formik}
|
|
266
|
+
name="postal_code"
|
|
267
|
+
sx={{ flex: "1 1 0", minWidth: 0 }}
|
|
268
|
+
/>
|
|
269
|
+
</Box>
|
|
270
|
+
</Box>
|
|
248
271
|
</Box>
|
|
249
272
|
)}
|
|
250
273
|
</Box>
|
|
251
|
-
<Box
|
|
274
|
+
{/* <Box
|
|
252
275
|
sx={{
|
|
253
276
|
mt: "16px",
|
|
254
277
|
display: "flex",
|
|
@@ -258,7 +281,7 @@ export const AddCard = ({
|
|
|
258
281
|
}}
|
|
259
282
|
>
|
|
260
283
|
{PriceDetails}
|
|
261
|
-
</Box>
|
|
284
|
+
</Box> */}
|
|
262
285
|
</Box>
|
|
263
286
|
)}
|
|
264
287
|
{error && (
|
|
@@ -105,13 +105,13 @@ export function AddressRegionField({ formik, name, sx }: AddressFieldProps) {
|
|
|
105
105
|
useEffect(() => {
|
|
106
106
|
setAddressRegionFieldOptional(
|
|
107
107
|
provinces.filter(
|
|
108
|
-
(province: Province) => province.country === country2code
|
|
109
|
-
).length === 0
|
|
108
|
+
(province: Province) => province.country === country2code,
|
|
109
|
+
).length === 0,
|
|
110
110
|
);
|
|
111
111
|
}, [country2code]);
|
|
112
112
|
|
|
113
113
|
const baseProps = {
|
|
114
|
-
sx: { width: 300, ...sx },
|
|
114
|
+
sx: { width: 300, flexShrink: 0, ...sx },
|
|
115
115
|
label: getRegionLabel(country2code),
|
|
116
116
|
name: name as string,
|
|
117
117
|
id: name as string,
|
|
@@ -160,6 +160,7 @@ export function AddressStreetField({
|
|
|
160
160
|
return (
|
|
161
161
|
<>
|
|
162
162
|
<TextField
|
|
163
|
+
fullWidth
|
|
163
164
|
label={lineNo ? `Street Address ${lineNo}` : "Street Address"}
|
|
164
165
|
sx={{ width: 400, display: "block", ...sx }}
|
|
165
166
|
name={name as string}
|
|
@@ -198,6 +199,7 @@ export function AddressOrganizationNameField({
|
|
|
198
199
|
}: AddressFieldProps) {
|
|
199
200
|
return (
|
|
200
201
|
<TextField
|
|
202
|
+
fullWidth
|
|
201
203
|
label="Organization Name"
|
|
202
204
|
sx={{ width: 400, display: "block", ...sx }}
|
|
203
205
|
name={name as string}
|
|
@@ -215,7 +217,7 @@ export function AddressCityField({ formik, name, sx }: AddressFieldProps) {
|
|
|
215
217
|
return (
|
|
216
218
|
<TextField
|
|
217
219
|
label="City"
|
|
218
|
-
sx={
|
|
220
|
+
sx={sx}
|
|
219
221
|
name={name as string}
|
|
220
222
|
id={name as string}
|
|
221
223
|
value={formik.values[name]}
|
|
@@ -244,7 +246,7 @@ export function AddressPostalCodeField({
|
|
|
244
246
|
return (
|
|
245
247
|
<TextField
|
|
246
248
|
label={getPostalCodeLabel(country2code)}
|
|
247
|
-
sx={{
|
|
249
|
+
sx={{ ...sx }}
|
|
248
250
|
name={name as string}
|
|
249
251
|
id={name as string}
|
|
250
252
|
value={formik.values[name]}
|
|
@@ -17,17 +17,23 @@ export function StatusBar({ status, backlink = "" }) {
|
|
|
17
17
|
</IconButton>
|
|
18
18
|
</Tooltip>
|
|
19
19
|
</Box>
|
|
20
|
-
<
|
|
20
|
+
<Box id="status-bar">
|
|
21
21
|
<Typography className="status-text active">PAYMENT DETAILS</Typography>
|
|
22
|
-
<
|
|
22
|
+
<Box
|
|
23
|
+
className={"status-bar" + (status > 0 ? " active" : "")}
|
|
24
|
+
sx={{ display: { xs: "none", md: "block" } }}
|
|
25
|
+
></Box>
|
|
23
26
|
<Typography className={"status-text" + (status > 0 ? " active" : "")}>
|
|
24
27
|
CONFIRMATION
|
|
25
28
|
</Typography>
|
|
26
|
-
<
|
|
29
|
+
<Box
|
|
30
|
+
className={"status-bar" + (status > 1 ? " active" : "")}
|
|
31
|
+
sx={{ display: { xs: "none", md: "block" } }}
|
|
32
|
+
></Box>
|
|
27
33
|
<Typography className={"status-text" + (status > 1 ? " active" : "")}>
|
|
28
34
|
ORDER PLACED
|
|
29
35
|
</Typography>
|
|
30
|
-
</
|
|
36
|
+
</Box>
|
|
31
37
|
<Box sx={{ flex: "1 1" }} />
|
|
32
38
|
</Box>
|
|
33
39
|
);
|
package/src/checkout/index.tsx
CHANGED
|
@@ -28,6 +28,7 @@ export default function Checkout({
|
|
|
28
28
|
disableFields = [],
|
|
29
29
|
dev,
|
|
30
30
|
invoiceId,
|
|
31
|
+
affiliateCode,
|
|
31
32
|
order: _order,
|
|
32
33
|
}: {
|
|
33
34
|
apiBaseUrl: string;
|
|
@@ -41,6 +42,7 @@ export default function Checkout({
|
|
|
41
42
|
disableFields?: string[];
|
|
42
43
|
dev?: boolean;
|
|
43
44
|
invoiceId?;
|
|
45
|
+
affiliateCode?;
|
|
44
46
|
order?;
|
|
45
47
|
}) {
|
|
46
48
|
const store = useStore(cartStore);
|
|
@@ -76,12 +78,12 @@ export default function Checkout({
|
|
|
76
78
|
order.charge_id ||
|
|
77
79
|
!["pending", "awaiting_payment"].includes(order.status)
|
|
78
80
|
? 2
|
|
79
|
-
: 0 // normally this should be set to 1 but we need to ensure it sends card data to the payment provider and that data is likely lost on refresh.
|
|
81
|
+
: 0, // normally this should be set to 1 but we need to ensure it sends card data to the payment provider and that data is likely lost on refresh.
|
|
80
82
|
);
|
|
81
83
|
})
|
|
82
84
|
.catch(() => {
|
|
83
85
|
console.error("Failed to get order");
|
|
84
|
-
})
|
|
86
|
+
}),
|
|
85
87
|
);
|
|
86
88
|
}
|
|
87
89
|
}, []);
|
|
@@ -92,22 +94,22 @@ export default function Checkout({
|
|
|
92
94
|
const pricesToGet = cart.items
|
|
93
95
|
.map((c) => c.price_id)
|
|
94
96
|
.filter(
|
|
95
|
-
(pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1
|
|
97
|
+
(pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1,
|
|
96
98
|
);
|
|
97
99
|
|
|
98
100
|
// filter out products that have already been queried
|
|
99
101
|
const productsToGet = cart.items
|
|
100
102
|
.map((c) => c.product_id)
|
|
101
103
|
.filter(
|
|
102
|
-
(pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1
|
|
104
|
+
(pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1,
|
|
103
105
|
);
|
|
104
106
|
|
|
105
107
|
const priceUrl = `${apiBaseUrl}/api/ecommerce/price?filter={'ids':[${pricesToGet.join(
|
|
106
|
-
","
|
|
108
|
+
",",
|
|
107
109
|
)}]}`;
|
|
108
110
|
|
|
109
111
|
const productUrl = `${apiBaseUrl}/api/ecommerce/products?filter={'ids':[${productsToGet.join(
|
|
110
|
-
","
|
|
112
|
+
",",
|
|
111
113
|
)}]}`;
|
|
112
114
|
|
|
113
115
|
const fetchSettings = {
|
|
@@ -137,7 +139,7 @@ export default function Checkout({
|
|
|
137
139
|
...o,
|
|
138
140
|
[p.id]: p,
|
|
139
141
|
}),
|
|
140
|
-
prices
|
|
142
|
+
prices,
|
|
141
143
|
);
|
|
142
144
|
setPrices(data);
|
|
143
145
|
}
|
|
@@ -148,7 +150,7 @@ export default function Checkout({
|
|
|
148
150
|
...o,
|
|
149
151
|
[p.id]: p,
|
|
150
152
|
}),
|
|
151
|
-
products
|
|
153
|
+
products,
|
|
152
154
|
);
|
|
153
155
|
setProducts(data);
|
|
154
156
|
}
|
|
@@ -160,7 +162,7 @@ export default function Checkout({
|
|
|
160
162
|
setSubtotal(
|
|
161
163
|
cart.items
|
|
162
164
|
.map((product) => prices[product.price_id]?.unit_amount)
|
|
163
|
-
.reduce((p, c) => (c ? p + c : p), 0)
|
|
165
|
+
.reduce((p, c) => (c ? p + c : p), 0),
|
|
164
166
|
);
|
|
165
167
|
}, [cart, prices]);
|
|
166
168
|
|
|
@@ -168,7 +170,7 @@ export default function Checkout({
|
|
|
168
170
|
const taxable_items = cart.items.filter(
|
|
169
171
|
(i) =>
|
|
170
172
|
prices[i.price_id]?.unit_amount > 0 &&
|
|
171
|
-
products[i.product_id]?.type !== "DONATION"
|
|
173
|
+
products[i.product_id]?.type !== "DONATION",
|
|
172
174
|
);
|
|
173
175
|
|
|
174
176
|
if (taxable_items.length === 0) {
|
|
@@ -239,6 +241,7 @@ export default function Checkout({
|
|
|
239
241
|
hideFields={hideFields}
|
|
240
242
|
disableFields={disableFields}
|
|
241
243
|
invoiceId={invoiceId}
|
|
244
|
+
affiliateCode={affiliateCode}
|
|
242
245
|
/>
|
|
243
246
|
)}
|
|
244
247
|
{status === 2 && order !== undefined && (
|
package/src/utils/storage.ts
CHANGED
|
@@ -61,7 +61,6 @@ apiPathDetails.listen((pathDetails, oldPathDetails) => {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
cartStore.set(cartStr);
|
|
64
|
-
console.log(cartStr);
|
|
65
64
|
} else if (status === 404 && localCartData.items.length > 0) {
|
|
66
65
|
fetchFromCartApi(
|
|
67
66
|
"PUT",
|
|
@@ -115,7 +114,6 @@ export function logout(apiBaseUrl: string | undefined) {
|
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
export function addToCart(p: CartProduct) {
|
|
118
|
-
console.log("ADD TO CART", p);
|
|
119
117
|
const cart: Cart = JSON.parse(cartStore.get());
|
|
120
118
|
const newCart: Cart = {
|
|
121
119
|
...cart,
|