bitsnap-react 1.3.2 → 1.3.3

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.mjs CHANGED
@@ -61,7 +61,7 @@ var PublicApiClient;
61
61
  // src/components/checkout/CartProvider.tsx
62
62
  import { create as create2 } from "@bufbuild/protobuf";
63
63
  import { createContext, useContext, useEffect } from "react";
64
- import zod from "zod";
64
+ import zod2 from "zod";
65
65
 
66
66
  // src/components/checkout/constants.ts
67
67
  var HOST = "https://bitsnap.pl";
@@ -320,6 +320,115 @@ function mapGooglePayDisplayItems(items, methods, deliveryMethod, couponCode, co
320
320
 
321
321
  // src/components/checkout/CartProvider.tsx
322
322
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
323
+
324
+ // src/components/checkout/frontent.analytics.ts
325
+ import zod from "zod";
326
+ var eventPayload = zod.object({
327
+ event: zod.enum([
328
+ "purchase",
329
+ "addToCart",
330
+ "customizeProduct",
331
+ "viewCart",
332
+ "removeFromCart",
333
+ "initiateCheckout"
334
+ ]),
335
+ step: zod.string().optional(),
336
+ value: zod.number().optional(),
337
+ currency: zod.string().optional(),
338
+ content_name: zod.string().optional(),
339
+ items: zod.array(
340
+ zod.object({
341
+ id: zod.string(),
342
+ name: zod.string(),
343
+ price: zod.number().default(0),
344
+ currency: zod.string().default("PLN"),
345
+ quantity: zod.number().default(1)
346
+ })
347
+ ).optional()
348
+ });
349
+ function sendAnalyticEvent(payload) {
350
+ if (typeof window == "undefined") {
351
+ return;
352
+ }
353
+ sendGoogleAnalyticsEvent(payload);
354
+ sendPixelAnalyticsEvent(payload);
355
+ }
356
+ function sendGoogleAnalyticsEvent(payload) {
357
+ try {
358
+ if (typeof window.dataLayer == "undefined") {
359
+ window.dataLayer = [];
360
+ }
361
+ window.dataLayer.push(payload);
362
+ } catch (e) {
363
+ console.warn("cannot send google analytics event", e);
364
+ }
365
+ }
366
+ function sendPixelAnalyticsEvent(payload) {
367
+ if (typeof window.fbq == "undefined") {
368
+ return;
369
+ }
370
+ let eventType = "";
371
+ let eventName = "";
372
+ let eventPayload2 = {};
373
+ switch (payload.event) {
374
+ case "purchase":
375
+ eventType = "track";
376
+ eventName = "Purchase";
377
+ eventPayload2 = {
378
+ category_name: payload.step,
379
+ ...payload
380
+ };
381
+ break;
382
+ case "addToCart":
383
+ eventType = "track";
384
+ eventName = "Add to Cart";
385
+ eventPayload2 = {
386
+ category_name: payload.step,
387
+ ...payload
388
+ };
389
+ break;
390
+ case "customizeProduct":
391
+ eventType = "track";
392
+ eventName = "Customize Product";
393
+ eventPayload2 = {
394
+ category_name: payload.step,
395
+ ...payload
396
+ };
397
+ break;
398
+ case "viewCart":
399
+ eventType = "track";
400
+ eventName = "View Cart";
401
+ eventPayload2 = {
402
+ category_name: payload.step,
403
+ ...payload
404
+ };
405
+ break;
406
+ case "removeFromCart":
407
+ eventType = "track";
408
+ eventName = "Remove from Cart";
409
+ eventPayload2 = {
410
+ category_name: payload.step,
411
+ ...payload
412
+ };
413
+ break;
414
+ case "initiateCheckout":
415
+ eventType = "track";
416
+ eventName = "Initiate Checkout";
417
+ eventPayload2 = {
418
+ category_name: payload.step,
419
+ ...payload
420
+ };
421
+ break;
422
+ default:
423
+ break;
424
+ }
425
+ if (window.location.search.includes("analytics")) {
426
+ console.log("Pushing FB event", eventType, eventName, eventPayload2);
427
+ }
428
+ window.fbq(eventType, eventName, eventPayload2);
429
+ }
430
+
431
+ // src/components/checkout/CartProvider.tsx
323
432
  import { Fragment, jsx } from "react/jsx-runtime";
324
433
  var MARKETING_AGREEMENT_ID = "__m_a";
325
434
  var CartProviderContext = createContext(void 0);
@@ -405,25 +514,25 @@ var useCartProvider = () => {
405
514
  return context;
406
515
  };
407
516
  var CartProvider_default = CartProvider;
408
- var googlePayConfigSchema = zod.object({
409
- isAvailable: zod.boolean(),
410
- merchantId: zod.string(),
411
- merchantName: zod.string(),
412
- gateway: zod.string(),
413
- gatewayId: zod.string()
517
+ var googlePayConfigSchema = zod2.object({
518
+ isAvailable: zod2.boolean(),
519
+ merchantId: zod2.string(),
520
+ merchantName: zod2.string(),
521
+ gateway: zod2.string(),
522
+ gatewayId: zod2.string()
414
523
  });
415
- var checkoutSchema = zod.object({
416
- country: zod.string().optional(),
417
- couponCode: zod.string().optional(),
418
- selectedDeliveryMethod: zod.string().optional(),
419
- postalCode: zod.string().optional(),
420
- email: zod.string().optional(),
421
- products: zod.array(
422
- zod.object({
423
- id: zod.string(),
424
- productID: zod.string(),
425
- quantity: zod.number(),
426
- metadata: zod.record(zod.string(), zod.string().optional()).optional()
524
+ var checkoutSchema = zod2.object({
525
+ country: zod2.string().optional(),
526
+ couponCode: zod2.string().optional(),
527
+ selectedDeliveryMethod: zod2.string().optional(),
528
+ postalCode: zod2.string().optional(),
529
+ email: zod2.string().optional(),
530
+ products: zod2.array(
531
+ zod2.object({
532
+ id: zod2.string(),
533
+ productID: zod2.string(),
534
+ quantity: zod2.number(),
535
+ metadata: zod2.record(zod2.string(), zod2.string().optional()).optional()
427
536
  })
428
537
  ).optional(),
429
538
  googlePayConfig: googlePayConfigSchema.optional()
@@ -454,12 +563,25 @@ function addProducts(products) {
454
563
  if (checkout.products == null) {
455
564
  checkout.products = [];
456
565
  }
457
- checkout.products.push(...products.map((el) => ({
458
- id: Math.random().toString(36).substring(7),
459
- productID: el.productID,
460
- quantity: el.quantity,
461
- metadata: el.metadata
462
- })));
566
+ checkout.products.push(
567
+ ...products.map((el) => ({
568
+ id: Math.random().toString(36).substring(7),
569
+ productID: el.productID,
570
+ quantity: el.quantity,
571
+ metadata: el.metadata
572
+ }))
573
+ );
574
+ sendAnalyticEvent({
575
+ event: "addToCart",
576
+ currency: "PLN",
577
+ items: products.map((el) => ({
578
+ id: el.productID,
579
+ name: "",
580
+ price: 0,
581
+ quantity: el.quantity,
582
+ currency: "PLN"
583
+ }))
584
+ });
463
585
  saveCheckout(checkout);
464
586
  updateNumberOfProductsInCart();
465
587
  }
@@ -472,6 +594,16 @@ function removeProductFromCheckout(ids) {
472
594
  (product) => !ids.includes(product.productID) && !ids.includes(product.id)
473
595
  )
474
596
  };
597
+ sendAnalyticEvent({
598
+ event: "removeFromCart",
599
+ items: ids.map((id) => ({
600
+ id,
601
+ name: "",
602
+ price: 0,
603
+ quantity: 1,
604
+ currency: "PLN"
605
+ }))
606
+ });
475
607
  saveCheckout(newCheckout);
476
608
  updateNumberOfProductsInCart();
477
609
  }
@@ -492,7 +624,9 @@ var getCheckoutMethods = (projectID) => {
492
624
  return false;
493
625
  }
494
626
  try {
495
- const result = await PublicApiClient.get(HOST).isOneClickPaymentAvailable({
627
+ const result = await PublicApiClient.get(
628
+ HOST
629
+ ).isOneClickPaymentAvailable({
496
630
  projectId: projectID
497
631
  });
498
632
  return result.applePay;
@@ -523,7 +657,9 @@ var getCheckoutMethods = (projectID) => {
523
657
  }
524
658
  if (args && args.items != null && args.items.length > 0) {
525
659
  if (checkout.products) {
526
- removeProductFromCheckout(checkout.products.map((el) => el.productID));
660
+ removeProductFromCheckout(
661
+ checkout.products.map((el) => el.productID)
662
+ );
527
663
  }
528
664
  addProducts(args.items);
529
665
  }
@@ -535,7 +671,10 @@ var getCheckoutMethods = (projectID) => {
535
671
  }
536
672
  const result = await PublicApiClient.get(HOST).getPreOrderDetails({
537
673
  items: products.map(
538
- (el) => create2(PreOrderItemSchema, { id: el.productID, quantity: el.quantity })
674
+ (el) => create2(PreOrderItemSchema, {
675
+ id: el.productID,
676
+ quantity: el.quantity
677
+ })
539
678
  ),
540
679
  projectId: projectID,
541
680
  // we can detect 5 the closest inpost pickup point based on shipping address.
@@ -591,10 +730,10 @@ var getCheckoutMethods = (projectID) => {
591
730
  return [];
592
731
  }
593
732
  try {
594
- return zod.array(
595
- zod.object({
596
- name: zod.string(),
597
- code: zod.string()
733
+ return zod2.array(
734
+ zod2.object({
735
+ name: zod2.string(),
736
+ code: zod2.string()
598
737
  })
599
738
  ).parse(await result.json());
600
739
  } catch (e) {
@@ -670,21 +809,18 @@ var getCheckoutMethods = (projectID) => {
670
809
  if (checkout.products == null || checkout.products.length == 0) {
671
810
  return Err("cart-is-empty", "badInput");
672
811
  }
673
- const mergedMetadata = checkout.products.reduce(
674
- (acc, product) => {
675
- if (product.metadata != null) {
676
- Object.keys(product.metadata).forEach((key) => {
677
- var _a;
678
- const value = (_a = product.metadata) == null ? void 0 : _a[key];
679
- if (value != null) {
680
- acc[key] = value;
681
- }
682
- });
683
- }
684
- return acc;
685
- },
686
- {}
687
- );
812
+ const mergedMetadata = checkout.products.reduce((acc, product) => {
813
+ if (product.metadata != null) {
814
+ Object.keys(product.metadata).forEach((key) => {
815
+ var _a;
816
+ const value = (_a = product.metadata) == null ? void 0 : _a[key];
817
+ if (value != null) {
818
+ acc[key] = value;
819
+ }
820
+ });
821
+ }
822
+ return acc;
823
+ }, {});
688
824
  const payload = {
689
825
  items: checkout.products.map((el) => {
690
826
  return {
@@ -901,7 +1037,9 @@ var getCheckoutMethods = (projectID) => {
901
1037
  }
902
1038
  if (args && args.expectedItems != null && args.expectedItems.length > 0) {
903
1039
  if (checkout.products) {
904
- removeProductFromCheckout(checkout.products.map((el) => el.productID));
1040
+ removeProductFromCheckout(
1041
+ checkout.products.map((el) => el.productID)
1042
+ );
905
1043
  }
906
1044
  addProducts(args.expectedItems);
907
1045
  }
@@ -911,7 +1049,10 @@ var getCheckoutMethods = (projectID) => {
911
1049
  }
912
1050
  const result = await PublicApiClient.get(HOST).getPreOrderDetails({
913
1051
  items: products.map(
914
- (el) => create2(PreOrderItemSchema, { id: el.productID, quantity: el.quantity })
1052
+ (el) => create2(PreOrderItemSchema, {
1053
+ id: el.productID,
1054
+ quantity: el.quantity
1055
+ })
915
1056
  ),
916
1057
  projectId: projectID,
917
1058
  // we can detect 5 the closest inpost pickup point based on shipping address.
@@ -929,7 +1070,9 @@ var getCheckoutMethods = (projectID) => {
929
1070
  };
930
1071
  });
931
1072
  if (result.selectedDeliveryMethod != null) {
932
- const deliveryMethod = result.methods.find((el) => el.id == result.selectedDeliveryMethod);
1073
+ const deliveryMethod = result.methods.find(
1074
+ (el) => el.id == result.selectedDeliveryMethod
1075
+ );
933
1076
  if (deliveryMethod != null) {
934
1077
  items.push({
935
1078
  amount: `${round(deliveryMethod.amount / 100, 2)}`,
@@ -1054,7 +1197,10 @@ function updateNumberOfProductsInCart() {
1054
1197
  const checkout = getCheckout();
1055
1198
  let numberOfProductsInCart = 0;
1056
1199
  if (checkout == null) {
1057
- useCheckoutStore.setState((state) => ({ ...state, numberOfProductsInCart }));
1200
+ useCheckoutStore.setState((state) => ({
1201
+ ...state,
1202
+ numberOfProductsInCart
1203
+ }));
1058
1204
  return;
1059
1205
  }
1060
1206
  numberOfProductsInCart = (_b = (_a = checkout.products) == null ? void 0 : _a.reduce((acc, product) => acc + product.quantity, 0)) != null ? _b : 0;
@@ -1064,7 +1210,13 @@ function updateNumberOfProductsInCart() {
1064
1210
  // src/components/checkout/ApplePay.tsx
1065
1211
  import { useQuery } from "@tanstack/react-query";
1066
1212
  import { Fragment as Fragment2, jsx as jsx2 } from "react/jsx-runtime";
1067
- function ApplePayButtonComponent({ style, buttonType, colorType, items, onClick }) {
1213
+ function ApplePayButtonComponent({
1214
+ style,
1215
+ buttonType,
1216
+ colorType,
1217
+ items,
1218
+ onClick
1219
+ }) {
1068
1220
  const {
1069
1221
  checkIfApplePayIsAvailable,
1070
1222
  getApplePayPaymentRequest,
@@ -1089,6 +1241,9 @@ function ApplePayButtonComponent({ style, buttonType, colorType, items, onClick
1089
1241
  metadata: el.metadata
1090
1242
  }));
1091
1243
  async function beginSession() {
1244
+ sendAnalyticEvent({
1245
+ event: "initiateCheckout"
1246
+ });
1092
1247
  const requiresShipping = items.find((el) => el.isDeliverable === true) != null;
1093
1248
  const session = new ApplePaySession(14, {
1094
1249
  countryCode: "PL",
@@ -1096,16 +1251,21 @@ function ApplePayButtonComponent({ style, buttonType, colorType, items, onClick
1096
1251
  supportedNetworks: ["visa", "masterCard"],
1097
1252
  currencyCode: "PLN",
1098
1253
  total: {
1099
- amount: `${round(items.reduce((acc, item) => acc + item.price * item.quantity, 0) / 100, 2)}`,
1254
+ amount: `${round(
1255
+ items.reduce((acc, item) => acc + item.price * item.quantity, 0) / 100,
1256
+ 2
1257
+ )}`,
1100
1258
  label: "P\u0142atno\u015B\u0107 za koszyk",
1101
1259
  type: "pending"
1102
1260
  },
1103
1261
  lineItems: [
1104
- ...items.map((item) => ({
1105
- amount: `${round(item.price * item.quantity / 100, 2)}`,
1106
- label: item.name,
1107
- type: "final"
1108
- })),
1262
+ ...items.map(
1263
+ (item) => ({
1264
+ amount: `${round(item.price * item.quantity / 100, 2)}`,
1265
+ label: item.name,
1266
+ type: "final"
1267
+ })
1268
+ ),
1109
1269
  requiresShipping ? {
1110
1270
  amount: `16.99`,
1111
1271
  type: "pending",
@@ -1115,8 +1275,18 @@ function ApplePayButtonComponent({ style, buttonType, colorType, items, onClick
1115
1275
  ...requiresShipping ? {
1116
1276
  shippingMethods: [],
1117
1277
  supportsCouponCode: true,
1118
- requiredBillingContactFields: ["name", "email", "postalAddress", "phone"],
1119
- requiredShippingContactFields: ["name", "email", "postalAddress", "phone"]
1278
+ requiredBillingContactFields: [
1279
+ "name",
1280
+ "email",
1281
+ "postalAddress",
1282
+ "phone"
1283
+ ],
1284
+ requiredShippingContactFields: [
1285
+ "name",
1286
+ "email",
1287
+ "postalAddress",
1288
+ "phone"
1289
+ ]
1120
1290
  } : {}
1121
1291
  });
1122
1292
  await (onClick == null ? void 0 : onClick());
@@ -1243,7 +1413,15 @@ function ApplePayButtonComponent({ style, buttonType, colorType, items, onClick
1243
1413
  };
1244
1414
  session.begin();
1245
1415
  }
1246
- return /* @__PURE__ */ jsx2(ApplePayButton, { style, buttonStyle: colorType, type: buttonType, onClick: beginSession });
1416
+ return /* @__PURE__ */ jsx2(
1417
+ ApplePayButton,
1418
+ {
1419
+ style,
1420
+ buttonStyle: colorType,
1421
+ type: buttonType,
1422
+ onClick: beginSession
1423
+ }
1424
+ );
1247
1425
  }
1248
1426
  function Wrapper(props) {
1249
1427
  return /* @__PURE__ */ jsx2(Fragment2, { children: /* @__PURE__ */ jsx2(CartProvider_default, { children: /* @__PURE__ */ jsx2(ApplePayButtonComponent, { ...props }) }) });
@@ -1280,7 +1458,13 @@ function Spinner({ className, ...props }) {
1280
1458
  // src/components/checkout/GooglePay.tsx
1281
1459
  import { useQuery as useQuery2, useMutation } from "@tanstack/react-query";
1282
1460
  import { Fragment as Fragment3, jsx as jsx4, jsxs } from "react/jsx-runtime";
1283
- function GooglePayButtonComponent({ items, style, buttonColor, buttonSizeMode, test }) {
1461
+ function GooglePayButtonComponent({
1462
+ items,
1463
+ style,
1464
+ buttonColor,
1465
+ buttonSizeMode,
1466
+ test
1467
+ }) {
1284
1468
  const {
1285
1469
  getGooglePayConfiguration,
1286
1470
  completeGooglePayPayment,
@@ -1292,7 +1476,10 @@ function GooglePayButtonComponent({ items, style, buttonColor, buttonSizeMode, t
1292
1476
  clearCart
1293
1477
  } = useCartProvider();
1294
1478
  const { data: googlePayConfiguration } = useQuery2({
1295
- queryKey: ["get-google-pay-configuration", items.map((el) => el.id).join(",")],
1479
+ queryKey: [
1480
+ "get-google-pay-configuration",
1481
+ items.map((el) => el.id).join(",")
1482
+ ],
1296
1483
  queryFn: () => getGooglePayConfiguration({
1297
1484
  items: items.map((el) => ({
1298
1485
  ...el,
@@ -1301,11 +1488,16 @@ function GooglePayButtonComponent({ items, style, buttonColor, buttonSizeMode, t
1301
1488
  }))
1302
1489
  })
1303
1490
  });
1304
- const { mutateAsync: completeGooglePayPaymentAsync, isPending } = useMutation({
1305
- mutationFn: completeGooglePayPayment
1306
- });
1491
+ const { mutateAsync: completeGooglePayPaymentAsync, isPending } = useMutation(
1492
+ {
1493
+ mutationFn: completeGooglePayPayment
1494
+ }
1495
+ );
1307
1496
  if (googlePayConfiguration == null || googlePayConfiguration.isAvailable != true) {
1308
- console.log("google pay configuration is not available", googlePayConfiguration);
1497
+ console.log(
1498
+ "google pay configuration is not available",
1499
+ googlePayConfiguration
1500
+ );
1309
1501
  return null;
1310
1502
  }
1311
1503
  return /* @__PURE__ */ jsxs(Fragment3, { children: [
@@ -1319,6 +1511,9 @@ function GooglePayButtonComponent({ items, style, buttonColor, buttonSizeMode, t
1319
1511
  environment: test === true ? "TEST" : "PRODUCTION",
1320
1512
  onPaymentDataChanged: async (paymentData) => {
1321
1513
  var _a, _b, _c, _d, _e;
1514
+ sendAnalyticEvent({
1515
+ event: "initiateCheckout"
1516
+ });
1322
1517
  console.log("payment data changed", paymentData);
1323
1518
  if (((_a = paymentData.shippingAddress) == null ? void 0 : _a.postalCode) != null) {
1324
1519
  await setPostalCode((_b = paymentData.shippingAddress) == null ? void 0 : _b.postalCode);
@@ -1372,7 +1567,7 @@ var GooglePay_default = Wrapper2;
1372
1567
 
1373
1568
  // src/components/checkout/BitsnapCart.tsx
1374
1569
  import { useEffect as useEffect4 } from "react";
1375
- import zod2 from "zod";
1570
+ import zod3 from "zod";
1376
1571
 
1377
1572
  // src/components/checkout/CartComponent.tsx
1378
1573
  import { useAutoAnimate as useAutoAnimate2 } from "@formkit/auto-animate/react";
@@ -1931,11 +2126,11 @@ var CartComponent_default = WrapperCartComponent;
1931
2126
 
1932
2127
  // src/components/checkout/BitsnapCart.tsx
1933
2128
  import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1934
- var cartAddToCartSchema = zod2.object({
1935
- id: zod2.string(),
1936
- isSubscription: zod2.boolean().default(false),
1937
- quantity: zod2.number(),
1938
- metadata: zod2.record(zod2.string(), zod2.string().optional()).optional()
2129
+ var cartAddToCartSchema = zod3.object({
2130
+ id: zod3.string(),
2131
+ isSubscription: zod3.boolean().default(false),
2132
+ quantity: zod3.number(),
2133
+ metadata: zod3.record(zod3.string(), zod3.string().optional()).optional()
1939
2134
  });
1940
2135
  function BitsnapCart({
1941
2136
  projectID,
@@ -1954,6 +2149,11 @@ function BitsnapCart({
1954
2149
  }
1955
2150
  useEffect4(() => {
1956
2151
  onVisibleChange == null ? void 0 : onVisibleChange(isCartVisible);
2152
+ if (isCartVisible) {
2153
+ sendAnalyticEvent({
2154
+ event: "viewCart"
2155
+ });
2156
+ }
1957
2157
  }, [isCartVisible]);
1958
2158
  useEffect4(() => {
1959
2159
  setProjectID(projectID);
@@ -1968,13 +2168,16 @@ function BitsnapCart({
1968
2168
  window["cart"] = {
1969
2169
  buyProduct: async (args) => {
1970
2170
  try {
1971
- const payload = zod2.object({
1972
- productID: zod2.string(),
1973
- email: zod2.string().optional(),
1974
- name: zod2.string().optional(),
1975
- country: zod2.string().optional(),
1976
- marketingAgreement: zod2.boolean().optional()
2171
+ const payload = zod3.object({
2172
+ productID: zod3.string(),
2173
+ email: zod3.string().optional(),
2174
+ name: zod3.string().optional(),
2175
+ country: zod3.string().optional(),
2176
+ marketingAgreement: zod3.boolean().optional()
1977
2177
  }).parse(args);
2178
+ sendAnalyticEvent({
2179
+ event: "initiateCheckout"
2180
+ });
1978
2181
  const methods = getCheckoutMethods(projectID2);
1979
2182
  const result = await methods.justRedirectToPayment(payload);
1980
2183
  console.log("result", result);
@@ -2064,7 +2267,10 @@ function BitsnapCart({
2064
2267
  {
2065
2268
  onClick: () => isCartVisible ? hideCart() : showCart(),
2066
2269
  style: { position: "relative" },
2067
- className: ["bitsnap-checkout", className != null ? className : "rounded-full hover:bg-neutral-300 transition p-1"].join(" "),
2270
+ className: [
2271
+ "bitsnap-checkout",
2272
+ className != null ? className : "rounded-full hover:bg-neutral-300 transition p-1"
2273
+ ].join(" "),
2068
2274
  children: [
2069
2275
  children ? /* @__PURE__ */ jsx10(Fragment6, { children }) : /* @__PURE__ */ jsxs6(
2070
2276
  "svg",