@merchi/cart 1.4.5 → 1.4.6
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/esm/CartProvider.js +50 -42
- package/esm/forms/FormShipmentAddressAndNotes.js +24 -3
- package/esm/utilities/index.js +1 -0
- package/esm/utilities/job_source.js +139 -0
- package/esm/utilities/job_source.test.js +75 -0
- package/esm/utilities/shipment.js +22 -0
- package/esm/utilities/shipment.test.js +60 -0
- package/lib/CartProvider.js +50 -42
- package/lib/forms/FormShipmentAddressAndNotes.js +22 -1
- package/lib/utilities/index.d.ts +1 -0
- package/lib/utilities/index.js +11 -0
- package/lib/utilities/job_source.d.ts +23 -0
- package/lib/utilities/job_source.js +152 -0
- package/lib/utilities/job_source.test.d.ts +1 -0
- package/lib/utilities/shipment.d.ts +15 -0
- package/lib/utilities/shipment.js +24 -0
- package/lib/utilities/shipment.test.d.ts +1 -0
- package/package.json +4 -4
- package/src/CartProvider.tsx +31 -14
- package/src/forms/FormShipmentAddressAndNotes.tsx +34 -2
- package/src/utilities/index.ts +1 -0
- package/src/utilities/job_source.test.ts +86 -0
- package/src/utilities/job_source.ts +165 -0
- package/src/utilities/shipment.test.ts +68 -0
- package/src/utilities/shipment.ts +34 -0
package/lib/CartProvider.js
CHANGED
|
@@ -19,6 +19,7 @@ var _product = require("./utilities/product");
|
|
|
19
19
|
var _local_storage = require("./utilities/local_storage");
|
|
20
20
|
var _user = require("./utilities/user");
|
|
21
21
|
var _test_checkout = require("./utilities/test_checkout");
|
|
22
|
+
var _job_source = require("./utilities/job_source");
|
|
22
23
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
23
24
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t9 in e) "default" !== _t9 && {}.hasOwnProperty.call(e, _t9) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t9)) && (i.get || i.set) ? o(f, _t9, i) : f[_t9] = e[_t9]); return f; })(e, t); }
|
|
24
25
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
@@ -504,65 +505,56 @@ var CartProvider = function CartProvider(_ref) {
|
|
|
504
505
|
}
|
|
505
506
|
function _createCartAndCookie() {
|
|
506
507
|
_createCartAndCookie = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(callback) {
|
|
507
|
-
var isTest, _cart, created, cartJson, _t3;
|
|
508
|
+
var isTest, jobSource, _cart, query, created, cartJson, _t3;
|
|
508
509
|
return _regenerator().w(function (_context2) {
|
|
509
510
|
while (1) switch (_context2.p = _context2.n) {
|
|
510
511
|
case 0:
|
|
511
512
|
setFetchingCart(true);
|
|
512
513
|
_context2.p = 1;
|
|
513
514
|
isTest = (0, _test_checkout.readTestCheckoutFlag)();
|
|
515
|
+
jobSource = (0, _job_source.jobSourceFieldsForApi)((0, _job_source.captureAndReadJobSource)());
|
|
514
516
|
_cart = (0, _cart3.makeCart)({
|
|
515
517
|
domain: {
|
|
516
518
|
id: domainId
|
|
517
519
|
},
|
|
518
520
|
isTest: isTest
|
|
519
521
|
}, true);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
522
|
+
query = [['embed', JSON.stringify(_helpers.cartEmbed)], ['skip_rights', 'y']];
|
|
523
|
+
if (isTest) query.push(['is_test', 'true']);
|
|
524
524
|
_context2.n = 2;
|
|
525
525
|
return merchi.authenticatedFetch('/carts/', {
|
|
526
526
|
method: 'POST',
|
|
527
|
-
body: _cart.toFormData(),
|
|
528
|
-
query:
|
|
527
|
+
body: (0, _job_source.appendJobSourceToFormData)(_cart.toFormData(), jobSource),
|
|
528
|
+
query: query
|
|
529
529
|
});
|
|
530
530
|
case 2:
|
|
531
531
|
created = _context2.v;
|
|
532
532
|
_cart.fromJson(created.cart);
|
|
533
|
-
_context2.n =
|
|
534
|
-
break;
|
|
535
|
-
case 3:
|
|
536
|
-
_context2.n = 4;
|
|
537
|
-
return _cart.create({
|
|
538
|
-
embed: _helpers.cartEmbed
|
|
539
|
-
});
|
|
540
|
-
case 4:
|
|
541
|
-
_context2.n = 5;
|
|
533
|
+
_context2.n = 3;
|
|
542
534
|
return _cart.toJson();
|
|
543
|
-
case
|
|
535
|
+
case 3:
|
|
544
536
|
cartJson = _context2.v;
|
|
545
537
|
if (domainId) (0, _cookie.setCartCookie)(Number(domainId), cartJson, undefined, isTest);
|
|
546
|
-
_context2.n =
|
|
538
|
+
_context2.n = 4;
|
|
547
539
|
return attachSavedClientIfNeeded(cartJson);
|
|
548
|
-
case
|
|
540
|
+
case 4:
|
|
549
541
|
cartJson = _context2.v;
|
|
550
542
|
setCart(_objectSpread({}, cartJson));
|
|
551
543
|
if (callback) callback();
|
|
552
|
-
_context2.n =
|
|
544
|
+
_context2.n = 6;
|
|
553
545
|
break;
|
|
554
|
-
case
|
|
555
|
-
_context2.p =
|
|
546
|
+
case 5:
|
|
547
|
+
_context2.p = 5;
|
|
556
548
|
_t3 = _context2.v;
|
|
557
549
|
alertError(_t3.errorMessage || _t3.message || 'Unable to fetch cart.');
|
|
558
|
-
case
|
|
559
|
-
_context2.p =
|
|
550
|
+
case 6:
|
|
551
|
+
_context2.p = 6;
|
|
560
552
|
setFetchingCart(false);
|
|
561
|
-
return _context2.f(
|
|
562
|
-
case
|
|
553
|
+
return _context2.f(6);
|
|
554
|
+
case 7:
|
|
563
555
|
return _context2.a(2);
|
|
564
556
|
}
|
|
565
|
-
}, _callee2, null, [[1,
|
|
557
|
+
}, _callee2, null, [[1, 5, 6, 7]]);
|
|
566
558
|
}));
|
|
567
559
|
return _createCartAndCookie.apply(this, arguments);
|
|
568
560
|
}
|
|
@@ -571,7 +563,7 @@ var CartProvider = function CartProvider(_ref) {
|
|
|
571
563
|
}
|
|
572
564
|
function _getCart() {
|
|
573
565
|
_getCart = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(cartIdAndToken) {
|
|
574
|
-
var id, _cart2, cartJson, isTest, _t4;
|
|
566
|
+
var id, _cart2, cartJson, isTest, jobSource, saved, _t4;
|
|
575
567
|
return _regenerator().w(function (_context3) {
|
|
576
568
|
while (1) switch (_context3.p = _context3.n) {
|
|
577
569
|
case 0:
|
|
@@ -599,36 +591,52 @@ var CartProvider = function CartProvider(_ref) {
|
|
|
599
591
|
case 4:
|
|
600
592
|
return _context3.a(2);
|
|
601
593
|
case 5:
|
|
602
|
-
|
|
594
|
+
jobSource = (0, _job_source.jobSourceFieldsForApi)((0, _job_source.captureAndReadJobSource)());
|
|
595
|
+
if (!(0, _job_source.cartNeedsSourceUpdate)(cartJson, jobSource)) {
|
|
603
596
|
_context3.n = 7;
|
|
604
597
|
break;
|
|
605
598
|
}
|
|
606
599
|
_context3.n = 6;
|
|
607
|
-
return
|
|
600
|
+
return merchi.authenticatedFetch("/carts/".concat(_cart2.id, "/"), {
|
|
601
|
+
method: 'PATCH',
|
|
602
|
+
body: (0, _job_source.appendJobSourceToFormData)(_cart2.toFormData(), jobSource),
|
|
603
|
+
query: [['embed', JSON.stringify(_helpers.cartEmbed)], ['skip_rights', 'y']]
|
|
604
|
+
});
|
|
608
605
|
case 6:
|
|
606
|
+
saved = _context3.v;
|
|
607
|
+
_cart2.fromJson(saved.cart);
|
|
608
|
+
cartJson = _cart2.toJson();
|
|
609
|
+
case 7:
|
|
610
|
+
if (!((0, _cart3.stripeIsValidAndActive)(cartJson) || isTest)) {
|
|
611
|
+
_context3.n = 9;
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
_context3.n = 8;
|
|
615
|
+
return attachSavedClientIfNeeded(cartJson);
|
|
616
|
+
case 8:
|
|
609
617
|
cartJson = _context3.v;
|
|
610
618
|
setCart(_objectSpread({}, cartJson));
|
|
611
|
-
_context3.n =
|
|
619
|
+
_context3.n = 10;
|
|
612
620
|
break;
|
|
613
|
-
case
|
|
621
|
+
case 9:
|
|
614
622
|
console.error("MErhci cart error: Stripe payment " + "options have not been correctly set up. " + "Check the company profile payment options tab " + "to set and edit stripe payment options.");
|
|
615
623
|
setCartSettingsInvalid(true);
|
|
616
|
-
case
|
|
617
|
-
_context3.n =
|
|
624
|
+
case 10:
|
|
625
|
+
_context3.n = 12;
|
|
618
626
|
break;
|
|
619
|
-
case
|
|
620
|
-
_context3.p =
|
|
627
|
+
case 11:
|
|
628
|
+
_context3.p = 11;
|
|
621
629
|
_t4 = _context3.v;
|
|
622
|
-
_context3.n =
|
|
630
|
+
_context3.n = 12;
|
|
623
631
|
return createCartAndCookie();
|
|
624
|
-
case
|
|
625
|
-
_context3.p =
|
|
632
|
+
case 12:
|
|
633
|
+
_context3.p = 12;
|
|
626
634
|
setFetchingCart(false);
|
|
627
|
-
return _context3.f(
|
|
628
|
-
case
|
|
635
|
+
return _context3.f(12);
|
|
636
|
+
case 13:
|
|
629
637
|
return _context3.a(2);
|
|
630
638
|
}
|
|
631
|
-
}, _callee3, null, [[1,
|
|
639
|
+
}, _callee3, null, [[1, 11, 12, 13]]);
|
|
632
640
|
}));
|
|
633
641
|
return _getCart.apply(this, arguments);
|
|
634
642
|
}
|
|
@@ -129,7 +129,9 @@ function ActiveFormShipmentAddressAndNotes() {
|
|
|
129
129
|
cart = _useCartContext2.cart,
|
|
130
130
|
setCart = _useCartContext2.setCart,
|
|
131
131
|
setLoadingTotals = _useCartContext2.setLoadingTotals,
|
|
132
|
-
setActiveTabAndEditDisabled = _useCartContext2.setActiveTabAndEditDisabled
|
|
132
|
+
setActiveTabAndEditDisabled = _useCartContext2.setActiveTabAndEditDisabled,
|
|
133
|
+
updateCartShipmentAddress = _useCartContext2.updateCartShipmentAddress,
|
|
134
|
+
getCartShipmentOptions = _useCartContext2.getCartShipmentOptions;
|
|
133
135
|
var saved = (0, _local_storage.getSavedCheckoutAddress)(domainId);
|
|
134
136
|
var cartAddress = cart === null || cart === void 0 ? void 0 : cart.receiverAddress;
|
|
135
137
|
var receiverAddress = (0, _local_storage.addressHasContent)(cartAddress) ? cartAddress : saved.address || {};
|
|
@@ -138,6 +140,25 @@ function ActiveFormShipmentAddressAndNotes() {
|
|
|
138
140
|
_useState2 = _slicedToArray(_useState, 2),
|
|
139
141
|
addressFieldsOpen = _useState2[0],
|
|
140
142
|
setAddressFieldsOpen = _useState2[1];
|
|
143
|
+
var hydratedShipmentOptionsRef = (0, _react.useRef)(false);
|
|
144
|
+
(0, _react.useEffect)(function () {
|
|
145
|
+
if (hydratedShipmentOptionsRef.current || !(cart !== null && cart !== void 0 && cart.id)) return;
|
|
146
|
+
var draft = (0, _local_storage.getSavedCheckoutAddress)(domainId);
|
|
147
|
+
var action = (0, _shipment.checkoutShipmentHydrationAction)({
|
|
148
|
+
cartAddress: cart === null || cart === void 0 ? void 0 : cart.receiverAddress,
|
|
149
|
+
savedAddress: draft.address,
|
|
150
|
+
shipmentGroups: cart === null || cart === void 0 ? void 0 : cart.shipmentGroups
|
|
151
|
+
});
|
|
152
|
+
if (!action) return;
|
|
153
|
+
hydratedShipmentOptionsRef.current = true;
|
|
154
|
+
if (action === "apply-saved-address" && draft.address) {
|
|
155
|
+
updateCartShipmentAddress(draft.address);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (action === "refresh-quotes") {
|
|
159
|
+
getCartShipmentOptions === null || getCartShipmentOptions === void 0 || getCartShipmentOptions();
|
|
160
|
+
}
|
|
161
|
+
}, [cart === null || cart === void 0 ? void 0 : cart.id, cart === null || cart === void 0 ? void 0 : cart.receiverAddress, cart === null || cart === void 0 ? void 0 : cart.shipmentGroups, domainId, getCartShipmentOptions, updateCartShipmentAddress]);
|
|
141
162
|
function saveCartShipmentAddressAndGoToNextTab(_x) {
|
|
142
163
|
return _saveCartShipmentAddressAndGoToNextTab.apply(this, arguments);
|
|
143
164
|
}
|
package/lib/utilities/index.d.ts
CHANGED
package/lib/utilities/index.js
CHANGED
|
@@ -91,6 +91,17 @@ Object.keys(_job).forEach(function (key) {
|
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
|
+
var _job_source = require("./job_source");
|
|
95
|
+
Object.keys(_job_source).forEach(function (key) {
|
|
96
|
+
if (key === "default" || key === "__esModule") return;
|
|
97
|
+
if (key in exports && exports[key] === _job_source[key]) return;
|
|
98
|
+
Object.defineProperty(exports, key, {
|
|
99
|
+
enumerable: true,
|
|
100
|
+
get: function get() {
|
|
101
|
+
return _job_source[key];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
94
105
|
var _local_storage = require("./local_storage");
|
|
95
106
|
Object.keys(_local_storage).forEach(function (key) {
|
|
96
107
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const JOB_SOURCE_STORAGE_KEY = "merchi_job_source";
|
|
2
|
+
export interface JobSourceFields {
|
|
3
|
+
utmSource?: string;
|
|
4
|
+
utmMedium?: string;
|
|
5
|
+
utmCampaign?: string;
|
|
6
|
+
utmContent?: string;
|
|
7
|
+
utmTerm?: string;
|
|
8
|
+
sourceClickId?: string;
|
|
9
|
+
sourceLanding?: string;
|
|
10
|
+
sourceReferrer?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function sourceFromLocation(): JobSourceFields;
|
|
13
|
+
export declare function hasPaidClick(source: JobSourceFields | null | undefined): boolean;
|
|
14
|
+
export declare function hasSourceData(source: JobSourceFields | null | undefined): boolean;
|
|
15
|
+
export declare function captureAndReadJobSource(): JobSourceFields;
|
|
16
|
+
export declare function jobSourceFieldsForApi(source?: JobSourceFields | null): JobSourceFields;
|
|
17
|
+
export declare function cartNeedsSourceUpdate(cart: {
|
|
18
|
+
utmSource?: string;
|
|
19
|
+
sourceClickId?: string;
|
|
20
|
+
sourceChannel?: string;
|
|
21
|
+
} | null | undefined, source: JobSourceFields): boolean;
|
|
22
|
+
export declare const JOB_SOURCE_URL_KEYS: ("gclid" | "gbraid" | "wbraid" | "fbclid" | "msclkid" | "utm_source" | "utm_medium" | "utm_campaign" | "utm_content" | "utm_term")[];
|
|
23
|
+
export declare function appendJobSourceToFormData(data: FormData, source?: JobSourceFields | null): FormData;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.JOB_SOURCE_URL_KEYS = exports.JOB_SOURCE_STORAGE_KEY = void 0;
|
|
7
|
+
exports.appendJobSourceToFormData = appendJobSourceToFormData;
|
|
8
|
+
exports.captureAndReadJobSource = captureAndReadJobSource;
|
|
9
|
+
exports.cartNeedsSourceUpdate = cartNeedsSourceUpdate;
|
|
10
|
+
exports.hasPaidClick = hasPaidClick;
|
|
11
|
+
exports.hasSourceData = hasSourceData;
|
|
12
|
+
exports.jobSourceFieldsForApi = jobSourceFieldsForApi;
|
|
13
|
+
exports.sourceFromLocation = sourceFromLocation;
|
|
14
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
15
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
16
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
17
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
18
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
19
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
20
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
21
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
22
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
23
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
24
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
25
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
26
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
27
|
+
var JOB_SOURCE_STORAGE_KEY = exports.JOB_SOURCE_STORAGE_KEY = 'merchi_job_source';
|
|
28
|
+
var CLICK_ID_PARAMS = ['gclid', 'gbraid', 'wbraid', 'fbclid', 'msclkid'];
|
|
29
|
+
var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
30
|
+
function trimTo(value, limit) {
|
|
31
|
+
if (!value) return undefined;
|
|
32
|
+
var text = value.trim().slice(0, limit);
|
|
33
|
+
return text || undefined;
|
|
34
|
+
}
|
|
35
|
+
function readSearchParams() {
|
|
36
|
+
if (typeof window === 'undefined') return new URLSearchParams();
|
|
37
|
+
try {
|
|
38
|
+
return new URLSearchParams(window.location.search);
|
|
39
|
+
} catch (_unused) {
|
|
40
|
+
return new URLSearchParams();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function readStoredSource() {
|
|
44
|
+
if (typeof window === 'undefined') return null;
|
|
45
|
+
try {
|
|
46
|
+
var raw = window.localStorage.getItem(JOB_SOURCE_STORAGE_KEY);
|
|
47
|
+
if (!raw) return null;
|
|
48
|
+
var parsed = JSON.parse(raw);
|
|
49
|
+
if (!parsed || _typeof(parsed) !== 'object') return null;
|
|
50
|
+
return parsed;
|
|
51
|
+
} catch (_unused2) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function writeStoredSource(source) {
|
|
56
|
+
if (typeof window === 'undefined') return;
|
|
57
|
+
try {
|
|
58
|
+
window.localStorage.setItem(JOB_SOURCE_STORAGE_KEY, JSON.stringify(source));
|
|
59
|
+
} catch (_unused3) {
|
|
60
|
+
// Ignore quota / private-mode failures.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function currentLanding() {
|
|
64
|
+
if (typeof window === 'undefined') return undefined;
|
|
65
|
+
try {
|
|
66
|
+
var path = "".concat(window.location.pathname || '/').concat(window.location.search || '');
|
|
67
|
+
return trimTo(path, 512);
|
|
68
|
+
} catch (_unused4) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function currentReferrer() {
|
|
73
|
+
if (typeof document === 'undefined') return undefined;
|
|
74
|
+
try {
|
|
75
|
+
return trimTo(document.referrer, 512);
|
|
76
|
+
} catch (_unused5) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function sourceFromLocation() {
|
|
81
|
+
var params = readSearchParams();
|
|
82
|
+
var source = {
|
|
83
|
+
utmSource: trimTo(params.get('utm_source'), 256),
|
|
84
|
+
utmMedium: trimTo(params.get('utm_medium'), 256),
|
|
85
|
+
utmCampaign: trimTo(params.get('utm_campaign'), 256),
|
|
86
|
+
utmContent: trimTo(params.get('utm_content'), 256),
|
|
87
|
+
utmTerm: trimTo(params.get('utm_term'), 256),
|
|
88
|
+
sourceLanding: currentLanding(),
|
|
89
|
+
sourceReferrer: currentReferrer()
|
|
90
|
+
};
|
|
91
|
+
var _iterator = _createForOfIteratorHelper(CLICK_ID_PARAMS),
|
|
92
|
+
_step;
|
|
93
|
+
try {
|
|
94
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
95
|
+
var key = _step.value;
|
|
96
|
+
var value = trimTo(params.get(key), 256);
|
|
97
|
+
if (value) {
|
|
98
|
+
source.sourceClickId = value;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch (err) {
|
|
103
|
+
_iterator.e(err);
|
|
104
|
+
} finally {
|
|
105
|
+
_iterator.f();
|
|
106
|
+
}
|
|
107
|
+
return source;
|
|
108
|
+
}
|
|
109
|
+
function hasPaidClick(source) {
|
|
110
|
+
return Boolean(source === null || source === void 0 ? void 0 : source.sourceClickId);
|
|
111
|
+
}
|
|
112
|
+
function hasSourceData(source) {
|
|
113
|
+
if (!source) return false;
|
|
114
|
+
return Boolean(source.utmSource || source.utmMedium || source.utmCampaign || source.utmContent || source.utmTerm || source.sourceClickId || source.sourceLanding || source.sourceReferrer);
|
|
115
|
+
}
|
|
116
|
+
function captureAndReadJobSource() {
|
|
117
|
+
var incoming = sourceFromLocation();
|
|
118
|
+
var stored = readStoredSource();
|
|
119
|
+
if (hasPaidClick(incoming) || !hasSourceData(stored)) {
|
|
120
|
+
var next = _objectSpread(_objectSpread({}, stored || {}), Object.fromEntries(Object.entries(incoming).filter(function (_ref) {
|
|
121
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
122
|
+
value = _ref2[1];
|
|
123
|
+
return Boolean(value);
|
|
124
|
+
})));
|
|
125
|
+
if (hasSourceData(next)) writeStoredSource(next);
|
|
126
|
+
return next;
|
|
127
|
+
}
|
|
128
|
+
return stored || incoming;
|
|
129
|
+
}
|
|
130
|
+
function jobSourceFieldsForApi(source) {
|
|
131
|
+
var resolved = source || captureAndReadJobSource();
|
|
132
|
+
var out = {};
|
|
133
|
+
Object.keys(resolved).forEach(function (key) {
|
|
134
|
+
var value = resolved[key];
|
|
135
|
+
if (value) out[key] = value;
|
|
136
|
+
});
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
function cartNeedsSourceUpdate(cart, source) {
|
|
140
|
+
if (!hasSourceData(source)) return false;
|
|
141
|
+
if (!(cart !== null && cart !== void 0 && cart.utmSource) && !(cart !== null && cart !== void 0 && cart.sourceClickId) && !(cart !== null && cart !== void 0 && cart.sourceChannel)) return true;
|
|
142
|
+
return Boolean(source.sourceClickId && !(cart !== null && cart !== void 0 && cart.sourceClickId));
|
|
143
|
+
}
|
|
144
|
+
var JOB_SOURCE_URL_KEYS = exports.JOB_SOURCE_URL_KEYS = [].concat(UTM_PARAMS, CLICK_ID_PARAMS);
|
|
145
|
+
function appendJobSourceToFormData(data, source) {
|
|
146
|
+
var fields = jobSourceFieldsForApi(source);
|
|
147
|
+
Object.keys(fields).forEach(function (key) {
|
|
148
|
+
var value = fields[key];
|
|
149
|
+
if (value) data.append(key, value);
|
|
150
|
+
});
|
|
151
|
+
return data;
|
|
152
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,17 @@
|
|
|
1
|
+
import { SavedCheckoutAddress } from './local_storage';
|
|
1
2
|
export declare const shipmentFormId = "_shipment-address-form-id";
|
|
2
3
|
export declare function cartItemsNeedShipment(cart: any): boolean;
|
|
4
|
+
export declare function shipmentGroupsHaveQuotes(groups?: any[] | null): boolean;
|
|
5
|
+
export type CheckoutShipmentHydrationAction = 'apply-saved-address' | 'refresh-quotes' | null;
|
|
6
|
+
/**
|
|
7
|
+
* When checkout hydrates a saved address (localStorage) the form shows it,
|
|
8
|
+
* but quotes are only fetched after the user edits the field. Returning
|
|
9
|
+
* `apply-saved-address` means the cart still needs that address applied so
|
|
10
|
+
* quotes can be generated; `refresh-quotes` means the cart already has an
|
|
11
|
+
* address but no usable shipment options.
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkoutShipmentHydrationAction(options: {
|
|
14
|
+
cartAddress?: SavedCheckoutAddress | null;
|
|
15
|
+
savedAddress?: SavedCheckoutAddress | null;
|
|
16
|
+
shipmentGroups?: any[] | null;
|
|
17
|
+
}): CheckoutShipmentHydrationAction;
|
|
@@ -4,7 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.cartItemsNeedShipment = cartItemsNeedShipment;
|
|
7
|
+
exports.checkoutShipmentHydrationAction = checkoutShipmentHydrationAction;
|
|
7
8
|
exports.shipmentFormId = void 0;
|
|
9
|
+
exports.shipmentGroupsHaveQuotes = shipmentGroupsHaveQuotes;
|
|
10
|
+
var _local_storage = require("./local_storage");
|
|
8
11
|
var shipmentFormId = exports.shipmentFormId = '_shipment-address-form-id';
|
|
9
12
|
function cartItemsNeedShipment(cart) {
|
|
10
13
|
var _cart$cartItems = cart.cartItems,
|
|
@@ -15,4 +18,25 @@ function cartItemsNeedShipment(cart) {
|
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
return false;
|
|
21
|
+
}
|
|
22
|
+
function shipmentGroupsHaveQuotes(groups) {
|
|
23
|
+
if (!(groups !== null && groups !== void 0 && groups.length)) return false;
|
|
24
|
+
return groups.some(function (group) {
|
|
25
|
+
return Array.isArray(group === null || group === void 0 ? void 0 : group.quotes) && group.quotes.length > 0;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* When checkout hydrates a saved address (localStorage) the form shows it,
|
|
30
|
+
* but quotes are only fetched after the user edits the field. Returning
|
|
31
|
+
* `apply-saved-address` means the cart still needs that address applied so
|
|
32
|
+
* quotes can be generated; `refresh-quotes` means the cart already has an
|
|
33
|
+
* address but no usable shipment options.
|
|
34
|
+
*/
|
|
35
|
+
function checkoutShipmentHydrationAction(options) {
|
|
36
|
+
var hasCartAddress = (0, _local_storage.addressHasContent)(options.cartAddress);
|
|
37
|
+
var hasSavedAddress = (0, _local_storage.addressHasContent)(options.savedAddress);
|
|
38
|
+
var hasQuotes = shipmentGroupsHaveQuotes(options.shipmentGroups);
|
|
39
|
+
if (!hasCartAddress && hasSavedAddress) return 'apply-saved-address';
|
|
40
|
+
if (hasCartAddress && !hasQuotes) return 'refresh-quotes';
|
|
41
|
+
return null;
|
|
18
42
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@merchi/cart",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "Merchi's cart",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -98,9 +98,9 @@
|
|
|
98
98
|
"browser-or-node": "^3.0.0-pre.0",
|
|
99
99
|
"js-cookie": "^3.0.5",
|
|
100
100
|
"lodash": "^4.17.21",
|
|
101
|
-
"@merchi/product-form": "^1.19.
|
|
102
|
-
"@merchi/product-form-sdk": "^1.0.
|
|
103
|
-
"@merchi/sdk": "^1.42.
|
|
101
|
+
"@merchi/product-form": "^1.19.14",
|
|
102
|
+
"@merchi/product-form-sdk": "^1.0.11",
|
|
103
|
+
"@merchi/sdk": "^1.42.1",
|
|
104
104
|
"react-country-region-selector": "^3.6.1",
|
|
105
105
|
"react-hook-form": "7.45.4",
|
|
106
106
|
"react-icons": "^4.10.1",
|
package/src/CartProvider.tsx
CHANGED
|
@@ -21,6 +21,12 @@ import {
|
|
|
21
21
|
} from './utilities/local_storage';
|
|
22
22
|
import { makeUser } from './utilities/user';
|
|
23
23
|
import { persistTestCheckoutFlag, readTestCheckoutFlag } from './utilities/test_checkout';
|
|
24
|
+
import {
|
|
25
|
+
appendJobSourceToFormData,
|
|
26
|
+
captureAndReadJobSource,
|
|
27
|
+
cartNeedsSourceUpdate,
|
|
28
|
+
jobSourceFieldsForApi,
|
|
29
|
+
} from './utilities/job_source';
|
|
24
30
|
|
|
25
31
|
export interface PropsCart {
|
|
26
32
|
cart: any;
|
|
@@ -622,21 +628,19 @@ const CartProvider = ({
|
|
|
622
628
|
setFetchingCart(true);
|
|
623
629
|
try {
|
|
624
630
|
const isTest = readTestCheckoutFlag();
|
|
631
|
+
const jobSource = jobSourceFieldsForApi(captureAndReadJobSource());
|
|
625
632
|
const cart = makeCart({domain: {id: domainId}, isTest}, true);
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
} else {
|
|
638
|
-
await cart.create({embed: cartEmbed});
|
|
639
|
-
}
|
|
633
|
+
const query: Array<[string, string]> = [
|
|
634
|
+
['embed', JSON.stringify(cartEmbed)],
|
|
635
|
+
['skip_rights', 'y'],
|
|
636
|
+
];
|
|
637
|
+
if (isTest) query.push(['is_test', 'true']);
|
|
638
|
+
const created = await merchi.authenticatedFetch('/carts/', {
|
|
639
|
+
method: 'POST',
|
|
640
|
+
body: appendJobSourceToFormData(cart.toFormData() as FormData, jobSource),
|
|
641
|
+
query,
|
|
642
|
+
});
|
|
643
|
+
cart.fromJson(created.cart);
|
|
640
644
|
let cartJson = await cart.toJson();
|
|
641
645
|
if (domainId) setCartCookie(Number(domainId), cartJson, undefined, isTest);
|
|
642
646
|
cartJson = await attachSavedClientIfNeeded(cartJson);
|
|
@@ -663,6 +667,19 @@ const CartProvider = ({
|
|
|
663
667
|
await createCartAndCookie();
|
|
664
668
|
return;
|
|
665
669
|
}
|
|
670
|
+
const jobSource = jobSourceFieldsForApi(captureAndReadJobSource());
|
|
671
|
+
if (cartNeedsSourceUpdate(cartJson, jobSource)) {
|
|
672
|
+
const saved = await merchi.authenticatedFetch(`/carts/${cart.id}/`, {
|
|
673
|
+
method: 'PATCH',
|
|
674
|
+
body: appendJobSourceToFormData(cart.toFormData() as FormData, jobSource),
|
|
675
|
+
query: [
|
|
676
|
+
['embed', JSON.stringify(cartEmbed)],
|
|
677
|
+
['skip_rights', 'y'],
|
|
678
|
+
],
|
|
679
|
+
});
|
|
680
|
+
cart.fromJson(saved.cart);
|
|
681
|
+
cartJson = cart.toJson();
|
|
682
|
+
}
|
|
666
683
|
if (stripeIsValidAndActive(cartJson) || isTest) {
|
|
667
684
|
cartJson = await attachSavedClientIfNeeded(cartJson);
|
|
668
685
|
setCart({...cartJson});
|
|
@@ -2,10 +2,13 @@ import { useForm } from "react-hook-form";
|
|
|
2
2
|
import InputsAddress from "./InputsAddress";
|
|
3
3
|
import { CheckoutContainer, InnerContainer } from "../components/containers";
|
|
4
4
|
import { Title } from "../components";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
checkoutShipmentHydrationAction,
|
|
7
|
+
shipmentFormId,
|
|
8
|
+
} from "../utilities/shipment";
|
|
6
9
|
import { faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons";
|
|
7
10
|
import { useCartContext } from "../CartProvider";
|
|
8
|
-
import { useState } from "react";
|
|
11
|
+
import { useEffect, useRef, useState } from "react";
|
|
9
12
|
import { getCartCookieToken } from "../utilities/cookie";
|
|
10
13
|
import { makeAddress, sanitizeAddressFields } from "../utilities/address";
|
|
11
14
|
import { makeCart } from "../utilities/cart";
|
|
@@ -114,6 +117,8 @@ export function ActiveFormShipmentAddressAndNotes() {
|
|
|
114
117
|
setCart,
|
|
115
118
|
setLoadingTotals,
|
|
116
119
|
setActiveTabAndEditDisabled,
|
|
120
|
+
updateCartShipmentAddress,
|
|
121
|
+
getCartShipmentOptions,
|
|
117
122
|
} = useCartContext();
|
|
118
123
|
const saved = getSavedCheckoutAddress(domainId);
|
|
119
124
|
const cartAddress = cart?.receiverAddress;
|
|
@@ -122,6 +127,33 @@ export function ActiveFormShipmentAddressAndNotes() {
|
|
|
122
127
|
: saved.address || {};
|
|
123
128
|
const receiverNotes = cart?.receiverNotes || saved.receiverNotes || "";
|
|
124
129
|
const [addressFieldsOpen, setAddressFieldsOpen] = useState(false);
|
|
130
|
+
const hydratedShipmentOptionsRef = useRef(false);
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (hydratedShipmentOptionsRef.current || !cart?.id) return;
|
|
134
|
+
const draft = getSavedCheckoutAddress(domainId);
|
|
135
|
+
const action = checkoutShipmentHydrationAction({
|
|
136
|
+
cartAddress: cart?.receiverAddress,
|
|
137
|
+
savedAddress: draft.address,
|
|
138
|
+
shipmentGroups: cart?.shipmentGroups,
|
|
139
|
+
});
|
|
140
|
+
if (!action) return;
|
|
141
|
+
hydratedShipmentOptionsRef.current = true;
|
|
142
|
+
if (action === "apply-saved-address" && draft.address) {
|
|
143
|
+
updateCartShipmentAddress(draft.address);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (action === "refresh-quotes") {
|
|
147
|
+
getCartShipmentOptions?.();
|
|
148
|
+
}
|
|
149
|
+
}, [
|
|
150
|
+
cart?.id,
|
|
151
|
+
cart?.receiverAddress,
|
|
152
|
+
cart?.shipmentGroups,
|
|
153
|
+
domainId,
|
|
154
|
+
getCartShipmentOptions,
|
|
155
|
+
updateCartShipmentAddress,
|
|
156
|
+
]);
|
|
125
157
|
|
|
126
158
|
async function saveCartShipmentAddressAndGoToNextTab(values: any) {
|
|
127
159
|
const { receiverAddress: address, receiverNotes } = values;
|
package/src/utilities/index.ts
CHANGED