@springmicro/cart 0.5.7 → 0.5.8

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@springmicro/cart",
3
3
  "private": false,
4
- "version": "0.5.7",
4
+ "version": "0.5.8",
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.5.7",
27
+ "@springmicro/utils": "0.5.8",
28
28
  "dotenv": "^16.4.5",
29
29
  "nanostores": "^0.10.3",
30
30
  "react": "^18.2.0",
@@ -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": "b2df84fd444de6a50ca70ebd8cdbd6196ef0eda4"
52
+ "gitHead": "893349375763235632effda60aa0c1e20b78ba12"
53
53
  }
@@ -71,13 +71,18 @@ async function createOrder(cart, apiBaseUrl) {
71
71
  return order;
72
72
  }
73
73
 
74
- async function getTax(apiBaseUrl, taxProvider, items, v) {
74
+ async function getTax(apiBaseUrl, taxProvider, items, v, products) {
75
+ const taxable_items = items.filter(
76
+ (i) => i.unit_amount > 0 && products[i.product_id].type !== "DONATION"
77
+ );
78
+ if (taxable_items.length === 0) return { tax_amount: 0 };
79
+
75
80
  const res = await fetch(
76
81
  `${apiBaseUrl}/api/ecommerce/tax?tax_provider=${taxProvider ?? "dummy"}`,
77
82
  {
78
83
  method: "POST",
79
84
  body: JSON.stringify({
80
- cart_data: items,
85
+ cart_data: taxable_items,
81
86
  address: {
82
87
  country: v.country,
83
88
  city: v.locality,
@@ -102,6 +107,7 @@ export default function ReviewAndCalculateTaxes({
102
107
  statusState,
103
108
  cart,
104
109
  prices,
110
+ products,
105
111
  apiBaseUrl,
106
112
  orderState,
107
113
  disableProductLink,
@@ -126,7 +132,6 @@ export default function ReviewAndCalculateTaxes({
126
132
  setFormError(undefined);
127
133
  // status === 0 when this is clicked.
128
134
  // Creates an order and calculates tax.
129
-
130
135
  Promise.all([
131
136
  createOrder(cart, apiBaseUrl),
132
137
  getTax(
@@ -344,6 +349,7 @@ export default function ReviewAndCalculateTaxes({
344
349
  shipping,
345
350
  discount,
346
351
  prices,
352
+ products,
347
353
  disableMissingImage,
348
354
  disableProductLink,
349
355
  formik,
@@ -14,6 +14,7 @@ export function CartList({
14
14
  shipping,
15
15
  discount,
16
16
  prices,
17
+ products,
17
18
  disableMissingImage,
18
19
  disableProductLink,
19
20
  formik,
@@ -133,16 +134,21 @@ export function CartList({
133
134
  </Button>
134
135
  )}
135
136
  <Box className="checkout-list">
136
- {cart.items.map((p, i) => (
137
- <CartProductCard
138
- product={p}
139
- i={i}
140
- price={prices[p.price_id]}
141
- disableProductLink={disableProductLink}
142
- disableMissingImage={disableMissingImage}
143
- disableModification={status != 0}
144
- />
145
- ))}
137
+ {cart.items.map(
138
+ (p, i) => (
139
+ console.log(p),
140
+ (
141
+ <CartProductCard
142
+ product={products[p.product_id] ?? p}
143
+ i={i}
144
+ price={prices[p.price_id]}
145
+ disableProductLink={disableProductLink}
146
+ disableMissingImage={disableMissingImage}
147
+ disableModification={status != 0}
148
+ />
149
+ )
150
+ )
151
+ )}
146
152
  </Box>
147
153
  </Box>
148
154
  </Box>
@@ -51,10 +51,14 @@ export function CartProductCard({
51
51
  price.recurring.interval_count > 1 ? "s" : ""
52
52
  }`
53
53
  : ""
54
- }`
54
+ }${product.type === "DONATION" ? " - Donation" : ""}`
55
55
  : "Loading price..."}
56
56
  </Typography>
57
57
  </div>
58
+ <div className="two-row">
59
+ <Typography />
60
+ <Typography variant="caption"></Typography>
61
+ </div>
58
62
  </div>
59
63
  <div
60
64
  style={{
@@ -1,6 +1,6 @@
1
1
  import "./ReviewCartAndCalculateTaxes.css";
2
2
  import { useStore } from "@nanostores/react";
3
- import { useEffect, useState } from "react";
3
+ import { useEffect, useMemo, useState } from "react";
4
4
  import { Typography } from "@mui/material";
5
5
  import { cartStore, clearCart } from "../utils/storage";
6
6
  import { StatusBar } from "./components/StatusBar";
@@ -25,8 +25,11 @@ export default function Checkout({
25
25
  CollectExtraInfo?: React.FC<{ formik: FormikConfig<any> }>;
26
26
  defaultValues?: Record<string, any>;
27
27
  }) {
28
- const cart = JSON.parse(useStore(cartStore));
28
+ const store = useStore(cartStore);
29
+ const cart = useMemo(() => JSON.parse(store), [store]);
30
+ // const cart = JSON.parse(useStore(cartStore));
29
31
 
32
+ const [products, setProducts] = useState({});
30
33
  const [prices, setPrices] = useState({});
31
34
  const [subtotal, setSubtotal] = useState("Loading prices...");
32
35
  const taxState = useState({ tax_amount: "TBD" });
@@ -59,36 +62,74 @@ export default function Checkout({
59
62
  }
60
63
  }, []);
61
64
 
62
- // build pricing list
65
+ // build pricing list and product list
63
66
  useEffect(() => {
64
67
  // filter out prices that have already been queried
65
68
  const pricesToGet = cart.items
66
69
  .map((c) => c.price_id)
67
70
  .filter(
68
- (pId) => Object.keys(prices).findIndex((pKey) => pKey == pId) === -1
71
+ (pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1
69
72
  );
70
- if (pricesToGet.length === 0) return;
71
73
 
72
- const url = `${apiBaseUrl}/api/ecommerce/price?filter={'ids':[${pricesToGet.join(
74
+ // filter out products that have already been queried
75
+ const productsToGet = cart.items
76
+ .map((c) => c.product_id)
77
+ .filter(
78
+ (pId) => Object.keys(products).findIndex((pKey) => pKey == pId) === -1
79
+ );
80
+
81
+ const priceUrl = `${apiBaseUrl}/api/ecommerce/price?filter={'ids':[${pricesToGet.join(
82
+ ","
83
+ )}]}`;
84
+
85
+ const productUrl = `${apiBaseUrl}/api/ecommerce/products?filter={'ids':[${productsToGet.join(
73
86
  ","
74
87
  )}]}`;
75
- fetch(url, {
88
+
89
+ const fetchSettings = {
76
90
  method: "GET",
77
91
  headers: {
78
92
  "Content-Type": "application/json",
79
93
  },
80
- })
81
- .then((res) =>
82
- res.json().then((data) => {
83
- const pricingData = { ...prices };
84
-
85
- data.forEach((p) => {
86
- pricingData[p.id] = p;
87
- });
88
- setPrices(pricingData);
89
- })
90
- )
91
- .catch(() => {});
94
+ };
95
+
96
+ if (pricesToGet.length === 0 && productsToGet.length === 0) return;
97
+
98
+ Promise.all([
99
+ pricesToGet.length !== 0
100
+ ? fetch(priceUrl, fetchSettings)
101
+ : Promise.resolve(null),
102
+ productsToGet.length !== 0
103
+ ? fetch(productUrl, fetchSettings)
104
+ : Promise.resolve(null),
105
+ ]).then(([priceRes, productRes]) => {
106
+ Promise.all([
107
+ priceRes != null ? priceRes.json() : Promise.resolve(null),
108
+ productRes != null ? productRes.json() : Promise.resolve(null),
109
+ ]).then(([d1, d2]) => {
110
+ if (d1 != null) {
111
+ const data = d1.reduce(
112
+ (o, p) => ({
113
+ ...o,
114
+ [p.id]: p,
115
+ }),
116
+ prices
117
+ );
118
+ setPrices(data);
119
+ }
120
+
121
+ if (d2 != null) {
122
+ const data = d2.reduce(
123
+ (o, p) => ({
124
+ ...o,
125
+ [p.id]: p,
126
+ }),
127
+ products
128
+ );
129
+ setProducts(data);
130
+ }
131
+ });
132
+ });
92
133
  }, [cart]);
93
134
 
94
135
  useEffect(() => {
@@ -99,6 +140,18 @@ export default function Checkout({
99
140
  );
100
141
  }, [cart, prices]);
101
142
 
143
+ useEffect(() => {
144
+ const taxable_items = cart.items.filter(
145
+ (i) =>
146
+ prices[i.price_id]?.unit_amount > 0 &&
147
+ products[i.product_id]?.type !== "DONATION"
148
+ );
149
+
150
+ if (taxable_items.length === 0) {
151
+ taxState[1]({ tax_amount: 0 });
152
+ }
153
+ }, [cart, prices, products]);
154
+
102
155
  if (status === 0 && cart.items.length === 0)
103
156
  return (
104
157
  <div
@@ -146,6 +199,7 @@ export default function Checkout({
146
199
  statusState={[status, setStatus]}
147
200
  cart={cart}
148
201
  prices={prices}
202
+ products={products}
149
203
  apiBaseUrl={apiBaseUrl}
150
204
  orderState={[order, setOrder]}
151
205
  disableProductLink={disableProductLink}
@@ -121,7 +121,8 @@ export function addToCart(p: CartProduct) {
121
121
 
122
122
  // Update cart based on server info.
123
123
  const cart = await res.json();
124
- cartStore.set(apiCartToLocalCart(cart));
124
+ if (JSON.stringify(newCart) != apiCartToLocalCart(cart))
125
+ cartStore.set(apiCartToLocalCart(cart));
125
126
  });
126
127
  }
127
128
  }
@@ -156,7 +157,8 @@ export function removeFromCart(i: number) {
156
157
 
157
158
  // Update cart based on server info.
158
159
  const cart = await res.json();
159
- cartStore.set(apiCartToLocalCart(cart));
160
+ if (JSON.stringify(newCart) != apiCartToLocalCart(cart))
161
+ cartStore.set(apiCartToLocalCart(cart));
160
162
  });
161
163
  }
162
164
  }
@@ -171,7 +173,7 @@ export function clearCart() {
171
173
  const pathDetails = apiPathDetails.get();
172
174
  if (pathDetailsIsFullyDefined(pathDetails)) {
173
175
  fetchFromCartApi("DELETE", pathDetails).then(async () => {
174
- cartStore.set(JSON.stringify(newCart));
176
+ // cartStore.set(JSON.stringify(newCart));
175
177
  });
176
178
  }
177
179
  }