fontdue-js 2.16.1 → 2.17.1
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/CHANGELOG.md +11 -0
- package/dist/__generated__/AddressFieldsRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/AddressFieldsRefetchQuery.graphql.js +25 -4
- package/dist/__generated__/AddressFields_viewer.graphql.d.ts +5 -1
- package/dist/__generated__/AddressFields_viewer.graphql.js +23 -2
- package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.js +10 -4
- package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.js +10 -4
- package/dist/__generated__/CartOrderUpdateMutation.graphql.d.ts +3 -2
- package/dist/__generated__/CartOrderUpdateMutation.graphql.js +10 -4
- package/dist/__generated__/CartQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CartQuery.graphql.js +22 -4
- package/dist/__generated__/CartStateRemoveDiscountMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartStateRemoveDiscountMutation.graphql.js +43 -4
- package/dist/__generated__/CartStateUpdateMutation.graphql.d.ts +4 -3
- package/dist/__generated__/CartStateUpdateMutation.graphql.js +75 -54
- package/dist/__generated__/CartState_order.graphql.d.ts +2 -1
- package/dist/__generated__/CartState_order.graphql.js +8 -2
- package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.js +10 -4
- package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.d.ts +5 -4
- package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.js +10 -4
- package/dist/__generated__/Checkout_UpdateOrderErrors.graphql.d.ts +3 -3
- package/dist/__generated__/Checkout_UpdateOrderErrors.graphql.js +3 -3
- package/dist/__generated__/Checkout_identity.graphql.d.ts +2 -2
- package/dist/__generated__/Checkout_identity.graphql.js +3 -3
- package/dist/__generated__/Checkout_order.graphql.d.ts +3 -3
- package/dist/__generated__/Checkout_order.graphql.js +2 -2
- package/dist/__generated__/CouponCodeInputApplyCouponMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CouponCodeInputApplyCouponMutation.graphql.js +43 -4
- package/dist/__generated__/CustomerLoginFormLoginMutation.graphql.d.ts +4 -1
- package/dist/__generated__/CustomerLoginFormLoginMutation.graphql.js +1 -1
- package/dist/__generated__/FontFamiliesQuery.graphql.d.ts +2 -1
- package/dist/__generated__/FontFamiliesQuery.graphql.js +1 -1
- package/dist/__generated__/OrderVariableSelectionReduxRefetchQuery.graphql.d.ts +26 -0
- package/dist/__generated__/OrderVariableSelectionReduxRefetchQuery.graphql.js +154 -0
- package/dist/__generated__/OrderVariableSelectionRedux_viewer.graphql.d.ts +6 -1
- package/dist/__generated__/OrderVariableSelectionRedux_viewer.graphql.js +48 -5
- package/dist/__generated__/OrderVariableSelection_variables.graphql.d.ts +5 -1
- package/dist/__generated__/OrderVariableSelection_variables.graphql.js +41 -17
- package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +2 -1
- package/dist/__generated__/PrecartAddToCartMutation.graphql.js +10 -4
- package/dist/__generated__/PriceBarSectionRefetchQuery.graphql.d.ts +2 -1
- package/dist/__generated__/PriceBarSectionRefetchQuery.graphql.js +1 -1
- package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +8 -2
- package/dist/__generated__/StoreModalCartQuery.graphql.js +171 -114
- package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.js +8 -2
- package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalIndexQuery.graphql.js +9 -3
- package/dist/__generated__/StoreModalOrderVariableSelectionHookQuery.graphql.d.ts +26 -0
- package/dist/__generated__/StoreModalOrderVariableSelectionRefetchQuery.graphql.d.ts +26 -0
- package/dist/__generated__/StoreModalOrderVariableSelection_order.graphql.d.ts +30 -0
- package/dist/__generated__/StoreModalOrderVariableSelection_order.graphql.js +98 -0
- package/dist/__generated__/StoreModalOrderVariableSelection_viewer.graphql.d.ts +1 -16
- package/dist/__generated__/StoreModalOrderVariableSelection_viewer.graphql.js +40 -104
- package/dist/__generated__/StoreModalProductContent_viewer.graphql.d.ts +30 -0
- package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalProductQuery.graphql.js +90 -63
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +1 -1
- package/dist/__generated__/StoreModalProductSummaryAddToCartMutation.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalProductSummaryAddToCartMutation.graphql.js +1 -1
- package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.js +1 -1
- package/dist/__generated__/StoreModalProductViewerRefetchQuery.graphql.d.ts +31 -0
- package/dist/__generated__/StoreModalUnifiedCheckoutCompleteOrderMutation.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalUnifiedCheckoutCompleteOrderMutation.graphql.js +43 -4
- package/dist/__generated__/StoreModalUnifiedCheckoutUpdateCustomerMutation.graphql.d.ts +6 -1
- package/dist/__generated__/StoreModalUnifiedCheckoutUpdateCustomerMutation.graphql.js +74 -24
- package/dist/__generated__/StoreModalUnifiedCheckoutUpdateOrderMutation.graphql.d.ts +5 -4
- package/dist/__generated__/StoreModalUnifiedCheckoutUpdateOrderMutation.graphql.js +43 -4
- package/dist/__generated__/StoreModalUnifiedCheckout_order.graphql.d.ts +13 -3
- package/dist/__generated__/StoreModalUnifiedCheckout_order.graphql.js +50 -4
- package/dist/__generated__/StoreModalUnifiedCheckout_viewer.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalUnifiedCheckout_viewer.graphql.js +8 -2
- package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
- package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +10 -4
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.d.ts +2 -1
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.js +30 -14
- package/dist/__generated__/TypeTesterStyleSelectData_fontStyle.graphql.d.ts +2 -1
- package/dist/__generated__/TypeTesterStyleSelectData_fontStyle.graphql.js +8 -2
- package/dist/__generated__/TypeTesterStyleSelectData_viewer.graphql.d.ts +4 -1
- package/dist/__generated__/TypeTesterStyleSelectData_viewer.graphql.js +17 -2
- package/dist/__generated__/TypeTesterStyleSelect_family.graphql.d.ts +33 -0
- package/dist/__generated__/TypeTesterStyleSelect_fontStyle.graphql.d.ts +27 -0
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.d.ts +2 -1
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersIDQuery.graphql.js +53 -37
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +2 -1
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersSlugQuery.graphql.js +53 -37
- package/dist/components/Cart/AddressFields.d.ts +3 -2
- package/dist/components/Cart/AddressFields.js +45 -47
- package/dist/components/Cart/CartState.js +2 -2
- package/dist/components/Cart/CartTotals.d.ts +5 -2
- package/dist/components/Cart/CartTotals.js +24 -10
- package/dist/components/Cart/Checkout.js +33 -6
- package/dist/components/Cart/CustomerFields.d.ts +5 -0
- package/dist/components/Cart/CustomerFields.js +11 -3
- package/dist/components/Cart/types.d.ts +1 -1
- package/dist/components/ConfigContext.d.ts +10 -0
- package/dist/components/ConfigContext.js +4 -1
- package/dist/components/OrderVariableSelection/OrderVariableSelectionRedux.js +30 -1
- package/dist/components/OrderVariableSelection/index.d.ts +3 -1
- package/dist/components/OrderVariableSelection/index.js +31 -11
- package/dist/components/StoreModal/StoreModalCart.js +9 -6
- package/dist/components/StoreModal/StoreModalIndexItem.js +3 -3
- package/dist/components/StoreModal/StoreModalOrderVariableSelection.d.ts +3 -1
- package/dist/components/StoreModal/StoreModalOrderVariableSelection.js +25 -6
- package/dist/components/StoreModal/StoreModalProduct.js +1 -1
- package/dist/components/StoreModal/StoreModalStyleButton.js +1 -8
- package/dist/components/StripeProvider/index.js +5 -3
- package/dist/components/TypeTester/TypeTesterStyleSelectData.js +12 -3
- package/dist/components/elements/StoreModalUnifiedCheckout.d.ts +60 -1
- package/dist/components/elements/StoreModalUnifiedCheckout.js +425 -208
- package/dist/fontdue.css +36 -10
- package/dist/reducer.d.ts +1 -0
- package/dist/utils/interpolateOrderVariableDescription.d.ts +36 -0
- package/dist/utils/interpolateOrderVariableDescription.test.d.ts +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +11 -2
- package/package.json +2 -1
|
@@ -10,14 +10,13 @@ var _StoreModalUnifiedCheckoutUpdateCustomerMutation2 = _interopRequireDefault(r
|
|
|
10
10
|
var _StoreModalUnifiedCheckout_order2 = _interopRequireDefault(require("../../__generated__/StoreModalUnifiedCheckout_order.graphql"));
|
|
11
11
|
var _StoreModalUnifiedCheckout_viewer2 = _interopRequireDefault(require("../../__generated__/StoreModalUnifiedCheckout_viewer.graphql"));
|
|
12
12
|
var _react = _interopRequireWildcard(require("react"));
|
|
13
|
+
var Sentry = _interopRequireWildcard(require("@sentry/react"));
|
|
13
14
|
var _reactRelay = require("react-relay");
|
|
14
15
|
var _AddressFields = _interopRequireDefault(require("../Cart/AddressFields"));
|
|
15
16
|
var _CustomerFields = _interopRequireDefault(require("../Cart/CustomerFields"));
|
|
16
|
-
var _StoreModalReviewIdentity = _interopRequireDefault(require("../StoreModal/StoreModalReviewIdentity"));
|
|
17
17
|
var _reactStripeJs = require("@stripe/react-stripe-js");
|
|
18
18
|
var _StoreModalLicenseeIsBillingIdentityElement = _interopRequireDefault(require("./StoreModalLicenseeIsBillingIdentityElement"));
|
|
19
19
|
var _reactRedux = require("react-redux");
|
|
20
|
-
var _reactErrorBoundary = require("react-error-boundary");
|
|
21
20
|
var _StripeLogo = _interopRequireDefault(require("../StripeLogo"));
|
|
22
21
|
var _Icons = require("../Icons");
|
|
23
22
|
var _ConfigContext = _interopRequireDefault(require("../ConfigContext"));
|
|
@@ -25,9 +24,68 @@ var _Price = require("../Price");
|
|
|
25
24
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
26
25
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
27
26
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
|
+
/**
|
|
28
|
+
* StoreModalUnifiedCheckout
|
|
29
|
+
*
|
|
30
|
+
* This component handles the checkout flow for orders, collecting customer information,
|
|
31
|
+
* billing/licensee details, and processing payment through Stripe.
|
|
32
|
+
*
|
|
33
|
+
* Key implementation details:
|
|
34
|
+
*
|
|
35
|
+
* 1. Auto-save billing identity (fontdue tax system only):
|
|
36
|
+
* - When using fontdue's tax system (not Stripe Tax), we need the billing address
|
|
37
|
+
* to calculate taxes before showing the final amount
|
|
38
|
+
* - The billing identity is auto-saved (with 500ms debounce) once the Stripe Address
|
|
39
|
+
* Element reports complete (name + address fields)
|
|
40
|
+
* - Email is a separate field (not part of Address Element), so auto-save may trigger
|
|
41
|
+
* before email is filled, which will cause backend validation errors to display
|
|
42
|
+
* - This ensures taxes are calculated and displayed before the user clicks Pay
|
|
43
|
+
* - On page reload, if billing identity already exists, billingAddressComplete starts
|
|
44
|
+
* as true to prevent re-triggering auto-save
|
|
45
|
+
*
|
|
46
|
+
* 2. Billing identity diff tracking:
|
|
47
|
+
* - We track differences between local state and saved backend data (billingIdentityDiff)
|
|
48
|
+
* - This determines isBillingIdentitySaved, which controls when payment can proceed
|
|
49
|
+
* - If the user edits any field after auto-save, it triggers another save cycle
|
|
50
|
+
* - All fields are normalized (null/undefined/empty string treated as equivalent)
|
|
51
|
+
*
|
|
52
|
+
* 3. Pay button validation:
|
|
53
|
+
* - The Pay button is always enabled (as long as EULA is checked) even if billing
|
|
54
|
+
* info isn't fully saved yet
|
|
55
|
+
* - This is intentional: we need to allow the user to click Pay so we can call
|
|
56
|
+
* elements.submit(), which triggers Stripe's validation and shows any validation
|
|
57
|
+
* errors inline in the Stripe UI elements
|
|
58
|
+
* - After Stripe validation passes, we check if billing identity is saved
|
|
59
|
+
* - If not saved, we show an error message above the Pay button asking them to
|
|
60
|
+
* complete billing information (validation errors should now be visible above)
|
|
61
|
+
*
|
|
62
|
+
* 4. Customer info pre-fill:
|
|
63
|
+
* - When customer submits their contact info, if billing name/email are empty,
|
|
64
|
+
* we pre-fill them from customer data as a convenience
|
|
65
|
+
*
|
|
66
|
+
* 5. Country mismatch handling (order snapshots):
|
|
67
|
+
* - When loading a hydrated order (e.g., from quote/snapshot), the order may have
|
|
68
|
+
* a country variable that differs from the user's detected country
|
|
69
|
+
* - In this case, we force licenseeIsBillingIdentity to false and always collect
|
|
70
|
+
* separate licensee information to ensure the licensee country matches the quote
|
|
71
|
+
* - This preserves pricing/availability from the original quote
|
|
72
|
+
*
|
|
73
|
+
* 6. Licensee country syncing:
|
|
74
|
+
* - When licensee country changes, it automatically updates any country-type order
|
|
75
|
+
* variables to maintain consistent pricing based on the selected country
|
|
76
|
+
*
|
|
77
|
+
* 7. Zero-order/coupon flow:
|
|
78
|
+
* - Orders with $0 total (due to coupons) bypass Stripe payment entirely
|
|
79
|
+
* - These use the completeOrder mutation instead of confirmPayment
|
|
80
|
+
*
|
|
81
|
+
* 8. Tax system variations:
|
|
82
|
+
* - Stripe Tax system: Uses embedded checkout, billing handled by Stripe
|
|
83
|
+
* - Fontdue tax system: Collects billing info directly, auto-saves for tax calculation
|
|
84
|
+
*/
|
|
85
|
+
|
|
28
86
|
/* const LICENSEE_REQUIRED_FIELDS = ['organization', 'country'] as (keyof Identity)[]; */
|
|
29
87
|
|
|
30
|
-
const IDENTITY_REQUIRED_FIELDS = ['name', 'email', '
|
|
88
|
+
const IDENTITY_REQUIRED_FIELDS = ['name', 'email', 'country'];
|
|
31
89
|
const defaultIdentity = {
|
|
32
90
|
name: '',
|
|
33
91
|
organization: '',
|
|
@@ -43,17 +101,18 @@ const defaultIdentity = {
|
|
|
43
101
|
};
|
|
44
102
|
function getIdentityFields(object) {
|
|
45
103
|
if (!object) return;
|
|
46
|
-
const identityKeys = Object.keys(defaultIdentity);
|
|
47
|
-
const result = {};
|
|
48
|
-
for (const key of identityKeys) {
|
|
49
|
-
if (key in object) {
|
|
50
|
-
const value = object[key];
|
|
51
|
-
if (value) result[key] = value;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
104
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
105
|
+
name: object.name ?? '',
|
|
106
|
+
organization: object.organization ?? null,
|
|
107
|
+
email: object.email ?? '',
|
|
108
|
+
phone: object.phoneNullable ?? '',
|
|
109
|
+
country: object.country ?? '',
|
|
110
|
+
administrativeArea: object.administrativeArea ?? null,
|
|
111
|
+
street: object.street ?? null,
|
|
112
|
+
locality: object.locality ?? null,
|
|
113
|
+
sublocality: object.sublocality ?? null,
|
|
114
|
+
zip: object.zip ?? null,
|
|
115
|
+
vatNumber: object.vatNumber ?? null
|
|
57
116
|
};
|
|
58
117
|
}
|
|
59
118
|
function EditableSection(_ref) {
|
|
@@ -67,7 +126,8 @@ function EditableSection(_ref) {
|
|
|
67
126
|
editing,
|
|
68
127
|
children: {
|
|
69
128
|
show,
|
|
70
|
-
edit
|
|
129
|
+
edit,
|
|
130
|
+
save
|
|
71
131
|
}
|
|
72
132
|
} = _ref;
|
|
73
133
|
const [submitting, setSubmitting] = (0, _react.useState)(false);
|
|
@@ -101,24 +161,54 @@ function EditableSection(_ref) {
|
|
|
101
161
|
className: "store-modal__cart__button",
|
|
102
162
|
type: "submit",
|
|
103
163
|
disabled: submitting || disableSubmit
|
|
104
|
-
}, submitting ? 'Submitting...' :
|
|
164
|
+
}, submitting ? 'Submitting...' : save))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, show, /*#__PURE__*/_react.default.createElement("button", {
|
|
105
165
|
type: "button",
|
|
106
166
|
className: "store-modal__cart__edit-button",
|
|
107
167
|
onClick: onEdit
|
|
108
168
|
}, "Change")));
|
|
109
169
|
}
|
|
110
170
|
function StoreModalUnifiedCheckout(_ref2) {
|
|
111
|
-
var _viewer$settings, _viewer$settings2, _viewer$settings3, _order$stripePaymentI, _order$stripePaymentI2;
|
|
171
|
+
var _order$orderVariableS, _viewer$settings, _viewer$settings2, _viewer$settings3, _order$stripePaymentI, _order$stripePaymentI2;
|
|
112
172
|
let {
|
|
113
173
|
order: orderKey,
|
|
114
174
|
viewer: viewerKey,
|
|
115
|
-
onScrollToTop
|
|
175
|
+
onScrollToTop,
|
|
176
|
+
onUpdateOrderVariableSelections
|
|
116
177
|
} = _ref2;
|
|
117
|
-
const viewer = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_viewer2.default.hash && _StoreModalUnifiedCheckout_viewer2.default.hash !== "
|
|
118
|
-
const order = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_order2.default.hash && _StoreModalUnifiedCheckout_order2.default.hash !== "
|
|
178
|
+
const viewer = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_viewer2.default.hash && _StoreModalUnifiedCheckout_viewer2.default.hash !== "83cc5e6f8d508fb1c2356a72b040f9b0" && console.error("The definition of 'StoreModalUnifiedCheckout_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_viewer2.default), viewerKey);
|
|
179
|
+
const order = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_order2.default.hash && _StoreModalUnifiedCheckout_order2.default.hash !== "ea43fb766c4dd1183b46ddf449aa85bd" && console.error("The definition of 'StoreModalUnifiedCheckout_order' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_order2.default), orderKey);
|
|
180
|
+
|
|
181
|
+
// Check if order has a country-type order variable with a different country than detected
|
|
182
|
+
// This is important for order snapshot/quote functionality where a quote was created for
|
|
183
|
+
// a different country than the user's detected country. In this case, we must collect
|
|
184
|
+
// licensee information to ensure the country variable matches the licensee's country.
|
|
185
|
+
// If the countries match (or no country variable exists), allow the normal checkout flow.
|
|
186
|
+
const countryVariableSelection = (_order$orderVariableS = order.orderVariableSelections) === null || _order$orderVariableS === void 0 ? void 0 : _order$orderVariableS.find(selection => selection.orderVariable.variableType === 'country');
|
|
187
|
+
const hasCountryMismatch = countryVariableSelection && countryVariableSelection.countryCode && countryVariableSelection.countryCode !== viewer.detectedCountry;
|
|
188
|
+
|
|
189
|
+
// When loading a hydrated order (e.g., from order snapshot/quote), initialize the
|
|
190
|
+
// licensee country from the order variable country if no licensee country exists yet.
|
|
191
|
+
// This is useful for the "order snapshot" functionality where we want to preserve
|
|
192
|
+
// the original country selection from the quote.
|
|
193
|
+
const getInitialCountry = () => {
|
|
194
|
+
var _order$licenseeIdenti, _order$orderVariableS2;
|
|
195
|
+
// If order already has a licensee identity with country, use that
|
|
196
|
+
if (order !== null && order !== void 0 && (_order$licenseeIdenti = order.licenseeIdentity) !== null && _order$licenseeIdenti !== void 0 && _order$licenseeIdenti.country) {
|
|
197
|
+
return order.licenseeIdentity.country;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Otherwise, check if there's a country-type order variable selection
|
|
201
|
+
const countryVariableSelection = order === null || order === void 0 ? void 0 : (_order$orderVariableS2 = order.orderVariableSelections) === null || _order$orderVariableS2 === void 0 ? void 0 : _order$orderVariableS2.find(selection => selection.orderVariable.variableType === 'country');
|
|
202
|
+
if (countryVariableSelection !== null && countryVariableSelection !== void 0 && countryVariableSelection.countryCode) {
|
|
203
|
+
return countryVariableSelection.countryCode;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Fall back to detected country or viewer country
|
|
207
|
+
return viewer.detectedCountry ?? viewer.country;
|
|
208
|
+
};
|
|
119
209
|
const initialIdentity = {
|
|
120
210
|
...defaultIdentity,
|
|
121
|
-
country:
|
|
211
|
+
country: getInitialCountry()
|
|
122
212
|
};
|
|
123
213
|
const [customer, setCustomer] = (0, _react.useState)((order === null || order === void 0 ? void 0 : order.customer) ?? {
|
|
124
214
|
name: null,
|
|
@@ -127,25 +217,73 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
127
217
|
});
|
|
128
218
|
const [licenseeIdentity, setLicenseeIdentity] = (0, _react.useState)(getIdentityFields(order === null || order === void 0 ? void 0 : order.licenseeIdentity) ?? initialIdentity);
|
|
129
219
|
const [billingIdentity, setBillingIdentity] = (0, _react.useState)(getIdentityFields(order === null || order === void 0 ? void 0 : order.billingIdentity) ?? initialIdentity);
|
|
220
|
+
|
|
221
|
+
// Track if the Stripe Address Element reports as complete
|
|
222
|
+
// Start as true if order already has billing identity (page reload case)
|
|
223
|
+
const [billingAddressComplete, setBillingAddressComplete] = (0, _react.useState)(!!(order !== null && order !== void 0 && order.billingIdentity));
|
|
224
|
+
|
|
225
|
+
// Track differences between local state and saved backend data
|
|
226
|
+
const billingIdentityDiff = (0, _react.useMemo)(() => {
|
|
227
|
+
const savedIdentity = order === null || order === void 0 ? void 0 : order.billingIdentity;
|
|
228
|
+
if (!savedIdentity) return null;
|
|
229
|
+
|
|
230
|
+
// Helper to normalize values (treat null, undefined, and empty string as equivalent)
|
|
231
|
+
const normalize = val => val || '';
|
|
232
|
+
const differences = {};
|
|
233
|
+
const checkField = (field, localValue, savedValue) => {
|
|
234
|
+
const normalizedLocal = normalize(localValue);
|
|
235
|
+
const normalizedSaved = normalize(savedValue);
|
|
236
|
+
if (normalizedLocal !== normalizedSaved) {
|
|
237
|
+
differences[field] = {
|
|
238
|
+
local: normalizedLocal,
|
|
239
|
+
saved: normalizedSaved
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
checkField('name', billingIdentity.name, savedIdentity.name);
|
|
244
|
+
checkField('email', billingIdentity.email, savedIdentity.email);
|
|
245
|
+
checkField('phone', billingIdentity.phone, savedIdentity.phoneNullable);
|
|
246
|
+
checkField('country', billingIdentity.country, savedIdentity.country);
|
|
247
|
+
checkField('street', billingIdentity.street, savedIdentity.street);
|
|
248
|
+
checkField('locality', billingIdentity.locality, savedIdentity.locality);
|
|
249
|
+
checkField('sublocality', billingIdentity.sublocality, savedIdentity.sublocality);
|
|
250
|
+
checkField('administrativeArea', billingIdentity.administrativeArea, savedIdentity.administrativeArea);
|
|
251
|
+
checkField('zip', billingIdentity.zip, savedIdentity.zip);
|
|
252
|
+
checkField('organization', billingIdentity.organization, savedIdentity.organization);
|
|
253
|
+
checkField('vatNumber', billingIdentity.vatNumber, savedIdentity.vatNumber);
|
|
254
|
+
return Object.keys(differences).length > 0 ? differences : null;
|
|
255
|
+
}, [billingIdentity, order === null || order === void 0 ? void 0 : order.billingIdentity]);
|
|
256
|
+
const isBillingIdentitySaved = billingIdentityDiff === null && !!(order !== null && order !== void 0 && order.billingIdentity);
|
|
130
257
|
const handleCustomerChange = (0, _react.useCallback)(value => setCustomer(currentValue => ({
|
|
131
258
|
...currentValue,
|
|
132
259
|
...value
|
|
133
260
|
})), [setCustomer]);
|
|
134
261
|
const handleLicenseeChange = (0, _react.useCallback)(value => {
|
|
262
|
+
setErrorsObject(currentValue => {
|
|
263
|
+
if (currentValue !== null && currentValue !== void 0 && currentValue.licenseeIdentity) {
|
|
264
|
+
const keys = Object.keys(value);
|
|
265
|
+
return {
|
|
266
|
+
...currentValue,
|
|
267
|
+
licenseeIdentity: {
|
|
268
|
+
...currentValue.licenseeIdentity,
|
|
269
|
+
...keys.reduce((acc, field) => {
|
|
270
|
+
acc[field] = null;
|
|
271
|
+
return acc;
|
|
272
|
+
}, {})
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return currentValue;
|
|
277
|
+
});
|
|
135
278
|
setLicenseeIdentity(currentValue => ({
|
|
136
279
|
...currentValue,
|
|
137
280
|
...value
|
|
138
281
|
}));
|
|
139
282
|
}, [setLicenseeIdentity]);
|
|
140
|
-
const handleBillingChange = (0, _react.useCallback)(value => {
|
|
141
|
-
setBillingIdentity(currentValue => ({
|
|
142
|
-
...currentValue,
|
|
143
|
-
...value
|
|
144
|
-
}));
|
|
145
|
-
}, [setBillingIdentity]);
|
|
146
283
|
const environment = (0, _reactRelay.useRelayEnvironment)();
|
|
147
284
|
const [error, setError] = (0, _react.useState)(null);
|
|
148
285
|
const [errorsObject, setErrorsObject] = (0, _react.useState)(null);
|
|
286
|
+
const [customerErrorsObject, setCustomerErrorsObject] = (0, _react.useState)(null);
|
|
149
287
|
const [_submitting, setSubmitting] = (0, _react.useState)(false);
|
|
150
288
|
/* const [licenseeRequiredFields, setLicenseeRequiredFields] = useState<
|
|
151
289
|
* (keyof Identity)[]
|
|
@@ -155,11 +293,15 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
155
293
|
form: config
|
|
156
294
|
} = (0, _react.useContext)(_ConfigContext.default);
|
|
157
295
|
const onCompleted = (res, errors, onSuccess, onError) => {
|
|
158
|
-
var _res$updateOrder;
|
|
296
|
+
var _res$updateCustomer, _res$updateOrder;
|
|
159
297
|
if (errors && errors.length > 0) {
|
|
160
298
|
setError(errors[0].message);
|
|
161
299
|
setSubmitting(false);
|
|
162
300
|
onError === null || onError === void 0 ? void 0 : onError();
|
|
301
|
+
} else if ('updateCustomer' in res && (_res$updateCustomer = res.updateCustomer) !== null && _res$updateCustomer !== void 0 && _res$updateCustomer.errors && (res.updateCustomer.errors.name || res.updateCustomer.errors.email || res.updateCustomer.errors.newsletterOptIn)) {
|
|
302
|
+
setSubmitting(false);
|
|
303
|
+
setCustomerErrorsObject(res.updateCustomer.errors);
|
|
304
|
+
onError === null || onError === void 0 ? void 0 : onError();
|
|
163
305
|
} else if ('updateOrder' in res && (_res$updateOrder = res.updateOrder) !== null && _res$updateOrder !== void 0 && _res$updateOrder.errors) {
|
|
164
306
|
setSubmitting(false);
|
|
165
307
|
setErrorsObject(res.updateOrder.errors);
|
|
@@ -168,18 +310,19 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
168
310
|
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
|
|
169
311
|
setSubmitting(false);
|
|
170
312
|
setError(null);
|
|
313
|
+
setCustomerErrorsObject(null);
|
|
314
|
+
setErrorsObject(null);
|
|
171
315
|
}
|
|
172
316
|
};
|
|
173
317
|
const onError = error => {
|
|
174
318
|
setError(error.message);
|
|
175
319
|
setSubmitting(false);
|
|
176
|
-
onScrollToTop();
|
|
177
320
|
};
|
|
178
|
-
const updateCustomer = (0, _react.useCallback)((variables, onSuccess) => {
|
|
321
|
+
const updateCustomer = (0, _react.useCallback)((variables, onSuccess, onErrorCallback) => {
|
|
179
322
|
(0, _reactRelay.commitMutation)(environment, {
|
|
180
|
-
mutation: (_StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash !== "
|
|
323
|
+
mutation: (_StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash !== "a41e423a93ba20f15ebbe826dd802514" && console.error("The definition of 'StoreModalUnifiedCheckoutUpdateCustomerMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default),
|
|
181
324
|
variables,
|
|
182
|
-
onCompleted: (res, errors) => onCompleted(res, errors, onSuccess),
|
|
325
|
+
onCompleted: (res, errors) => onCompleted(res, errors, onSuccess, onErrorCallback),
|
|
183
326
|
onError
|
|
184
327
|
});
|
|
185
328
|
}, [environment]);
|
|
@@ -187,21 +330,82 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
187
330
|
(0, _reactRelay.commitMutation)(environment, {
|
|
188
331
|
mutation: (_StoreModalUnifiedCheckoutUpdateOrderMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateOrderMutation2.default.hash !== "189cd7ac579c6898dca2f4b6e07861d1" && console.error("The definition of 'StoreModalUnifiedCheckoutUpdateOrderMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutUpdateOrderMutation2.default),
|
|
189
332
|
variables,
|
|
190
|
-
onCompleted: (res, errors) => onCompleted(res, errors, onSuccess),
|
|
333
|
+
onCompleted: (res, errors) => onCompleted(res, errors, onSuccess, onError),
|
|
191
334
|
onError
|
|
192
335
|
});
|
|
193
336
|
}, [environment]);
|
|
337
|
+
|
|
338
|
+
// Update country order variable when licensee address country changes
|
|
339
|
+
(0, _react.useEffect)(() => {
|
|
340
|
+
if (!licenseeIdentity.country || !order.orderVariableSelections) return;
|
|
341
|
+
|
|
342
|
+
// Find country-type order variable
|
|
343
|
+
const countryVariableSelection = order.orderVariableSelections.find(selection => selection.orderVariable.variableType === 'country');
|
|
344
|
+
if (!countryVariableSelection) return;
|
|
345
|
+
|
|
346
|
+
// Only update if the country has actually changed
|
|
347
|
+
if (countryVariableSelection.countryCode === licenseeIdentity.country) return;
|
|
348
|
+
|
|
349
|
+
// Build updated selections array
|
|
350
|
+
const updatedSelections = order.orderVariableSelections.map(selection => {
|
|
351
|
+
var _selection$orderVaria;
|
|
352
|
+
return {
|
|
353
|
+
orderVariableId: selection.orderVariable.id,
|
|
354
|
+
orderVariableOptionId: ((_selection$orderVaria = selection.orderVariableOption) === null || _selection$orderVaria === void 0 ? void 0 : _selection$orderVaria.id) ?? null,
|
|
355
|
+
countryCode: selection.orderVariable.variableType === 'country' ? licenseeIdentity.country : selection.countryCode ?? null
|
|
356
|
+
};
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Update the order with new country via callback
|
|
360
|
+
onUpdateOrderVariableSelections(updatedSelections);
|
|
361
|
+
}, [licenseeIdentity.country, order.orderVariableSelections, onUpdateOrderVariableSelections]);
|
|
362
|
+
|
|
363
|
+
// When a country mismatch exists, force licenseeIsBillingIdentity to false
|
|
364
|
+
// This ensures we always collect licensee information for orders with mismatched country
|
|
365
|
+
(0, _react.useEffect)(() => {
|
|
366
|
+
if (hasCountryMismatch && (order.licenseeIsBillingIdentity ?? true)) {
|
|
367
|
+
// Update order to force separate licensee collection
|
|
368
|
+
updateOrder({
|
|
369
|
+
input: {
|
|
370
|
+
licenseeIsBillingIdentity: false
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}, [hasCountryMismatch, order.licenseeIsBillingIdentity, updateOrder]);
|
|
375
|
+
|
|
376
|
+
// Auto-save billing identity when complete (for fontdue tax system only)
|
|
377
|
+
// This ensures taxes are calculated before showing the payment element
|
|
378
|
+
(0, _react.useEffect)(() => {
|
|
379
|
+
const taxSystem = viewer.settings.taxSystem;
|
|
380
|
+
const canUseEmbeddedCheckout = taxSystem === 'stripe';
|
|
381
|
+
|
|
382
|
+
// Only for fontdue tax system (not Stripe Tax/embedded checkout)
|
|
383
|
+
if (!canUseEmbeddedCheckout && order.customer && !isBillingIdentitySaved) {
|
|
384
|
+
// Check if the Stripe Address Element reports as complete AND email is filled
|
|
385
|
+
const isComplete = billingAddressComplete;
|
|
386
|
+
if (isComplete) {
|
|
387
|
+
// Debounce the update to avoid sending on every character change
|
|
388
|
+
const timeoutId = setTimeout(() => {
|
|
389
|
+
// Save billing identity to backend for tax calculation
|
|
390
|
+
updateOrder({
|
|
391
|
+
input: {
|
|
392
|
+
billingIdentity
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}, 500); // 500ms debounce
|
|
396
|
+
|
|
397
|
+
return () => clearTimeout(timeoutId);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}, [billingIdentity, isBillingIdentitySaved, billingAddressComplete, order.customer, updateOrder, viewer.settings]);
|
|
194
401
|
let initialEditingState = null;
|
|
195
402
|
// set initial state depending on if checkout is already in progress
|
|
196
|
-
if (!order.billingIdentity) initialEditingState = 'billing';
|
|
197
|
-
if (order.licenseeIsBillingIdentity === false && !order.licenseeIdentity) {
|
|
198
|
-
initialEditingState = 'licensee';
|
|
199
|
-
}
|
|
200
403
|
if (!order.customer) initialEditingState = 'customer';
|
|
201
404
|
const [editing, setEditing] = (0, _react.useState)(initialEditingState);
|
|
202
405
|
const handleCustomerSubmit = _ref3 => {
|
|
203
406
|
let {
|
|
204
|
-
onSuccess
|
|
407
|
+
onSuccess,
|
|
408
|
+
onError
|
|
205
409
|
} = _ref3;
|
|
206
410
|
if (!billingIdentity.name && !billingIdentity.email) {
|
|
207
411
|
setBillingIdentity({
|
|
@@ -215,140 +419,192 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
215
419
|
}, () => {
|
|
216
420
|
onSuccess();
|
|
217
421
|
setEditing(null);
|
|
218
|
-
|
|
219
|
-
if (!order.billingIdentity) setEditing('billing');
|
|
220
|
-
} else {
|
|
221
|
-
if (!order.licenseeIdentity) setEditing('licensee');
|
|
222
|
-
}
|
|
223
|
-
});
|
|
422
|
+
}, onError);
|
|
224
423
|
};
|
|
225
424
|
const handleLicenseeIsBillingIdentityChange = (0, _react.useCallback)(value => {
|
|
226
425
|
updateOrder({
|
|
227
426
|
input: {
|
|
228
427
|
licenseeIsBillingIdentity: value
|
|
229
428
|
}
|
|
230
|
-
}, () => {
|
|
231
|
-
if (!value && !order.licenseeIdentity) {
|
|
232
|
-
setEditing('licensee');
|
|
233
|
-
}
|
|
234
|
-
if (value && !order.billingIdentity) {
|
|
235
|
-
setEditing('billing');
|
|
236
|
-
}
|
|
237
429
|
});
|
|
238
|
-
}, [updateOrder
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
430
|
+
}, [updateOrder]);
|
|
431
|
+
const handleBillingChange = (0, _react.useCallback)((value, complete) => {
|
|
432
|
+
setError(null);
|
|
433
|
+
setErrorsObject(currentValue => {
|
|
434
|
+
if (currentValue !== null && currentValue !== void 0 && currentValue.billingIdentity) {
|
|
435
|
+
const keys = Object.keys(value);
|
|
436
|
+
return {
|
|
437
|
+
...currentValue,
|
|
438
|
+
billingIdentity: {
|
|
439
|
+
...currentValue.billingIdentity,
|
|
440
|
+
...keys.reduce((acc, field) => {
|
|
441
|
+
acc[field] = null;
|
|
442
|
+
return acc;
|
|
443
|
+
}, {})
|
|
444
|
+
}
|
|
445
|
+
};
|
|
247
446
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
} = _ref5;
|
|
258
|
-
updateOrder({
|
|
259
|
-
input: {
|
|
260
|
-
billingIdentity
|
|
447
|
+
return currentValue;
|
|
448
|
+
});
|
|
449
|
+
setBillingIdentity(currentValue => {
|
|
450
|
+
const newValue = {
|
|
451
|
+
...currentValue,
|
|
452
|
+
...value
|
|
453
|
+
};
|
|
454
|
+
if (typeof complete === 'boolean') {
|
|
455
|
+
setBillingAddressComplete(complete);
|
|
261
456
|
}
|
|
262
|
-
|
|
263
|
-
onSuccess();
|
|
264
|
-
setEditing(null);
|
|
457
|
+
return newValue;
|
|
265
458
|
});
|
|
266
|
-
};
|
|
459
|
+
}, [order === null || order === void 0 ? void 0 : order.billingIdentity]);
|
|
267
460
|
const stripe = (0, _reactStripeJs.useStripe)();
|
|
268
461
|
const elements = (0, _reactStripeJs.useElements)();
|
|
269
462
|
const [completing, setCompleting] = (0, _react.useState)(false);
|
|
463
|
+
const [checkingOut, setCheckingOut] = (0, _react.useState)(false);
|
|
270
464
|
const dispatch = (0, _reactRedux.useDispatch)();
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
465
|
+
|
|
466
|
+
// When a country mismatch exists, always show licensee section (force collection)
|
|
467
|
+
// Otherwise, only show when user has selected "Your client" option
|
|
468
|
+
const showLicenseeSection = order.customer && (hasCountryMismatch || !(order.licenseeIsBillingIdentity ?? false));
|
|
469
|
+
const handleCheckout = (0, _react.useCallback)(async () => {
|
|
470
|
+
// Validate Stripe elements first
|
|
471
|
+
if (elements) {
|
|
472
|
+
const result = await elements.submit();
|
|
473
|
+
if (result.error) {
|
|
474
|
+
// Stripe will show validation errors in the UI
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// If licensee section is shown, save licensee data before navigating to checkout
|
|
480
|
+
if (showLicenseeSection) {
|
|
481
|
+
setCheckingOut(true);
|
|
482
|
+
updateOrder({
|
|
483
|
+
input: {
|
|
484
|
+
licenseeIdentity
|
|
485
|
+
}
|
|
486
|
+
}, () => {
|
|
487
|
+
setCheckingOut(false);
|
|
488
|
+
dispatch({
|
|
489
|
+
type: 'STORE_MODAL_NAVIGATE',
|
|
490
|
+
route: 'checkout'
|
|
491
|
+
});
|
|
492
|
+
}, () => {
|
|
493
|
+
setCheckingOut(false);
|
|
494
|
+
});
|
|
495
|
+
} else {
|
|
496
|
+
dispatch({
|
|
497
|
+
type: 'STORE_MODAL_NAVIGATE',
|
|
498
|
+
route: 'checkout'
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}, [showLicenseeSection, licenseeIdentity, updateOrder, dispatch, elements]);
|
|
502
|
+
const handleComplete = async e => {
|
|
279
503
|
e.preventDefault();
|
|
280
504
|
if (!order) return;
|
|
281
505
|
if (!billingIdentity) {
|
|
282
506
|
console.error('No billing identity, required for payment');
|
|
283
507
|
return;
|
|
284
508
|
}
|
|
509
|
+
|
|
510
|
+
// Validate Stripe elements first
|
|
511
|
+
if (elements) {
|
|
512
|
+
const result = await elements.submit();
|
|
513
|
+
if (result.error) {
|
|
514
|
+
// Stripe will show validation errors in the UI
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// If billing identity is not saved yet, don't proceed with payment
|
|
520
|
+
// The validation above will show errors for incomplete fields
|
|
521
|
+
if (!isBillingIdentitySaved) {
|
|
522
|
+
setError('Please complete all billing information above');
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
285
525
|
setCompleting(true);
|
|
286
526
|
setError(null);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
527
|
+
const processPayment = () => {
|
|
528
|
+
var _billingIdentity$stre, _billingIdentity$stre2;
|
|
529
|
+
if (order.canCompleteWithCoupon) {
|
|
530
|
+
(0, _reactRelay.commitMutation)(environment, {
|
|
531
|
+
mutation: (_StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash && _StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash !== "ea880419670573334e55529f454f8026" && console.error("The definition of 'StoreModalUnifiedCheckoutCompleteOrderMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutCompleteOrderMutation2.default),
|
|
532
|
+
variables: {},
|
|
533
|
+
onCompleted: (_response, errors) => {
|
|
534
|
+
if (errors && errors.length > 0) {
|
|
535
|
+
setCompleting(false);
|
|
536
|
+
setError(errors[0].message);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
window.location.href = order.completeUrl;
|
|
296
540
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
postal_code: billingIdentity.zip ?? ''
|
|
541
|
+
});
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (!stripe || !elements) return;
|
|
545
|
+
stripe === null || stripe === void 0 ? void 0 : stripe.confirmPayment({
|
|
546
|
+
elements,
|
|
547
|
+
confirmParams: {
|
|
548
|
+
return_url: order.completeUrl,
|
|
549
|
+
payment_method_data: {
|
|
550
|
+
billing_details: {
|
|
551
|
+
email: billingIdentity.email,
|
|
552
|
+
name: billingIdentity.name,
|
|
553
|
+
phone: billingIdentity.phone,
|
|
554
|
+
address: {
|
|
555
|
+
line1: (_billingIdentity$stre = billingIdentity.street) === null || _billingIdentity$stre === void 0 ? void 0 : _billingIdentity$stre.split(/\n/)[0],
|
|
556
|
+
line2: ((_billingIdentity$stre2 = billingIdentity.street) === null || _billingIdentity$stre2 === void 0 ? void 0 : _billingIdentity$stre2.split(/\n/)[1]) ?? '',
|
|
557
|
+
city: billingIdentity.locality ?? '',
|
|
558
|
+
state: billingIdentity.administrativeArea ?? '',
|
|
559
|
+
country: billingIdentity.country,
|
|
560
|
+
postal_code: billingIdentity.zip ?? ''
|
|
561
|
+
}
|
|
319
562
|
}
|
|
320
563
|
}
|
|
321
564
|
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
565
|
+
}).then(result => {
|
|
566
|
+
if ('error' in result) {
|
|
567
|
+
setCompleting(false);
|
|
568
|
+
setError(result.error.message ?? 'Payment failed. Please try another payment method.');
|
|
569
|
+
}
|
|
570
|
+
}).catch(error => {
|
|
571
|
+
console.log(error);
|
|
325
572
|
setCompleting(false);
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
573
|
+
});
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
// Save both licensee (if shown) and billing info before processing payment
|
|
577
|
+
const orderInput = {
|
|
578
|
+
billingIdentity
|
|
579
|
+
};
|
|
580
|
+
if (showLicenseeSection) {
|
|
581
|
+
orderInput.licenseeIdentity = licenseeIdentity;
|
|
582
|
+
}
|
|
583
|
+
updateOrder({
|
|
584
|
+
input: orderInput
|
|
585
|
+
}, () => {
|
|
586
|
+
processPayment();
|
|
587
|
+
}, () => {
|
|
330
588
|
setCompleting(false);
|
|
331
589
|
});
|
|
332
590
|
};
|
|
333
591
|
const taxSystem = viewer.settings.taxSystem;
|
|
334
592
|
const canUseEmbeddedCheckout = taxSystem === 'stripe';
|
|
335
|
-
const
|
|
336
|
-
const hasLicensee = order.licenseeIsBillingIdentity ? true : Boolean(order.licenseeIdentity);
|
|
337
|
-
const showBillingSection = !canUseEmbeddedCheckout && (order.customer && hasLicensee || order.billingIdentity);
|
|
593
|
+
const showBillingSection = !canUseEmbeddedCheckout && order.customer;
|
|
338
594
|
|
|
339
595
|
// billing info will be handled by embedded checkout
|
|
340
596
|
const showCheckoutButton = canUseEmbeddedCheckout && order.customer;
|
|
341
597
|
const zeroOrder = order.canCompleteWithCoupon;
|
|
342
|
-
const showPaymentSection = !canUseEmbeddedCheckout && order.customer
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}, error), /*#__PURE__*/_react.default.createElement(EditableSection, {
|
|
598
|
+
const showPaymentSection = !canUseEmbeddedCheckout && order.customer;
|
|
599
|
+
const billingComplete = IDENTITY_REQUIRED_FIELDS.every(key => Boolean(billingIdentity[key]));
|
|
600
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(EditableSection, {
|
|
346
601
|
editing: editing === 'customer',
|
|
347
602
|
disabled: false,
|
|
348
603
|
onEdit: () => setEditing('customer'),
|
|
349
604
|
onSubmit: handleCustomerSubmit,
|
|
350
|
-
disableSubmit:
|
|
605
|
+
disableSubmit: false
|
|
351
606
|
}, {
|
|
607
|
+
save: canUseEmbeddedCheckout ? order.customer ? 'Save' : 'Continue' : 'Checkout',
|
|
352
608
|
show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
|
|
353
609
|
className: "store-modal__cart__checkout-section-title"
|
|
354
610
|
}, "Contact information"), order.customer ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, order.customer.name, /*#__PURE__*/_react.default.createElement("br", null), order.customer.email) : 'Loading...'),
|
|
@@ -357,11 +613,12 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
357
613
|
}, "Contact information"), /*#__PURE__*/_react.default.createElement(_CustomerFields.default, {
|
|
358
614
|
value: customer,
|
|
359
615
|
onChange: handleCustomerChange,
|
|
360
|
-
optInLabel: (_viewer$settings = viewer.settings) === null || _viewer$settings === void 0 ? void 0 : _viewer$settings.newsletterOptInLabel
|
|
616
|
+
optInLabel: (_viewer$settings = viewer.settings) === null || _viewer$settings === void 0 ? void 0 : _viewer$settings.newsletterOptInLabel,
|
|
617
|
+
errors: customerErrorsObject
|
|
361
618
|
}))
|
|
362
|
-
}), order.customer ? /*#__PURE__*/_react.default.createElement(_StoreModalLicenseeIsBillingIdentityElement.default, {
|
|
619
|
+
}), order.customer && !hasCountryMismatch ? /*#__PURE__*/_react.default.createElement(_StoreModalLicenseeIsBillingIdentityElement.default, {
|
|
363
620
|
disabled: false,
|
|
364
|
-
value: order.licenseeIsBillingIdentity,
|
|
621
|
+
value: order.licenseeIsBillingIdentity ?? false,
|
|
365
622
|
onChange: handleLicenseeIsBillingIdentityChange
|
|
366
623
|
}, {
|
|
367
624
|
label: /*#__PURE__*/_react.default.createElement("div", {
|
|
@@ -369,72 +626,42 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
369
626
|
__html: ((_viewer$settings2 = viewer.settings) === null || _viewer$settings2 === void 0 ? void 0 : _viewer$settings2.storeModalSelectLicenseeLabel) ?? ''
|
|
370
627
|
}
|
|
371
628
|
})
|
|
372
|
-
}) : null, showLicenseeSection ? /*#__PURE__*/_react.default.createElement(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
className: "store-modal__cart__identity-fields"
|
|
386
|
-
}, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
|
|
387
|
-
viewer: viewer,
|
|
388
|
-
value: licenseeIdentity,
|
|
389
|
-
onChange: handleLicenseeChange,
|
|
390
|
-
errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.licenseeIdentity,
|
|
391
|
-
identityType: "licensee"
|
|
392
|
-
}))),
|
|
393
|
-
show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
|
|
394
|
-
className: "store-modal__cart__checkout-section-title"
|
|
395
|
-
}, "Licensee information (your client)"), order.licenseeIdentity ? /*#__PURE__*/_react.default.createElement("div", {
|
|
396
|
-
className: "store-modal__cart__identity"
|
|
397
|
-
}, /*#__PURE__*/_react.default.createElement(_StoreModalReviewIdentity.default, {
|
|
398
|
-
identity: order.licenseeIdentity
|
|
399
|
-
})) : 'Loading...')
|
|
400
|
-
}) : null, showBillingSection ? /*#__PURE__*/_react.default.createElement(EditableSection, {
|
|
401
|
-
disabled: false,
|
|
402
|
-
editing: editing === 'billing',
|
|
403
|
-
onEdit: () => setEditing('billing'),
|
|
404
|
-
disableSubmit: Object.keys(billingIdentity).some(key => {
|
|
405
|
-
if (IDENTITY_REQUIRED_FIELDS.includes(key)) return Boolean(billingIdentity[key]) === false;
|
|
406
|
-
return false;
|
|
407
|
-
}),
|
|
408
|
-
onSubmit: handleBillingSubmit
|
|
409
|
-
}, {
|
|
410
|
-
edit: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h3", {
|
|
411
|
-
className: "store-modal__cart__checkout-section-title"
|
|
412
|
-
}, "Billing information"), /*#__PURE__*/_react.default.createElement("div", {
|
|
413
|
-
className: "store-modal__cart__identity-fields"
|
|
414
|
-
}, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
|
|
415
|
-
viewer: viewer,
|
|
416
|
-
value: billingIdentity,
|
|
417
|
-
onChange: handleBillingChange,
|
|
418
|
-
errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.billingIdentity,
|
|
419
|
-
identityType: "billing"
|
|
420
|
-
}))),
|
|
421
|
-
show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
|
|
422
|
-
className: "store-modal__cart__checkout-section-title"
|
|
423
|
-
}, "Billing information"), order.billingIdentity ? /*#__PURE__*/_react.default.createElement("div", {
|
|
424
|
-
className: "store-modal__cart__identity"
|
|
425
|
-
}, /*#__PURE__*/_react.default.createElement(_StoreModalReviewIdentity.default, {
|
|
426
|
-
identity: order.billingIdentity
|
|
427
|
-
})) : 'Loading...')
|
|
428
|
-
}) : null, showCheckoutButton ? /*#__PURE__*/_react.default.createElement("div", {
|
|
629
|
+
}) : null, showLicenseeSection ? /*#__PURE__*/_react.default.createElement("div", {
|
|
630
|
+
className: "store-modal__cart__checkout-section"
|
|
631
|
+
}, /*#__PURE__*/_react.default.createElement("h3", {
|
|
632
|
+
className: "store-modal__cart__checkout-section-title"
|
|
633
|
+
}, hasCountryMismatch ? 'Licensee information' : 'Licensee information (your client)'), /*#__PURE__*/_react.default.createElement("div", {
|
|
634
|
+
className: "store-modal__cart__identity-fields"
|
|
635
|
+
}, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
|
|
636
|
+
viewer: viewer,
|
|
637
|
+
value: licenseeIdentity,
|
|
638
|
+
onChange: handleLicenseeChange,
|
|
639
|
+
errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.licenseeIdentity,
|
|
640
|
+
identityType: "licensee"
|
|
641
|
+
}))) : null, showBillingSection ? /*#__PURE__*/_react.default.createElement("div", {
|
|
429
642
|
className: "store-modal__cart__checkout-section",
|
|
430
|
-
"data-disabled":
|
|
643
|
+
"data-disabled": !order.customer
|
|
644
|
+
}, /*#__PURE__*/_react.default.createElement("h3", {
|
|
645
|
+
className: "store-modal__cart__checkout-section-title"
|
|
646
|
+
}, "Billing information"), /*#__PURE__*/_react.default.createElement("div", {
|
|
647
|
+
className: "store-modal__cart__identity-fields"
|
|
648
|
+
}, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
|
|
649
|
+
viewer: viewer,
|
|
650
|
+
value: billingIdentity,
|
|
651
|
+
onChange: handleBillingChange,
|
|
652
|
+
errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.billingIdentity,
|
|
653
|
+
identityType: "billing"
|
|
654
|
+
}))) : null, showCheckoutButton ? /*#__PURE__*/_react.default.createElement("div", {
|
|
655
|
+
className: "store-modal__cart__checkout-section",
|
|
656
|
+
"data-disabled": false
|
|
431
657
|
}, /*#__PURE__*/_react.default.createElement("button", {
|
|
432
658
|
type: "button",
|
|
433
659
|
className: "store-modal__cart__button",
|
|
434
|
-
onClick: handleCheckout
|
|
435
|
-
|
|
660
|
+
onClick: handleCheckout,
|
|
661
|
+
disabled: checkingOut
|
|
662
|
+
}, checkingOut ? 'Submitting...' : 'Checkout')) : null, showPaymentSection ? /*#__PURE__*/_react.default.createElement("div", {
|
|
436
663
|
className: "store-modal__cart__checkout-section",
|
|
437
|
-
"data-disabled":
|
|
664
|
+
"data-disabled": false
|
|
438
665
|
}, /*#__PURE__*/_react.default.createElement("form", {
|
|
439
666
|
onSubmit: handleComplete
|
|
440
667
|
}, !zeroOrder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h3", {
|
|
@@ -447,7 +674,7 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
447
674
|
rel: "noopener"
|
|
448
675
|
}, "Powered by ", /*#__PURE__*/_react.default.createElement(_StripeLogo.default, null)))), /*#__PURE__*/_react.default.createElement("div", {
|
|
449
676
|
className: "store-modal__cart__payment"
|
|
450
|
-
}, /*#__PURE__*/_react.default.createElement(
|
|
677
|
+
}, /*#__PURE__*/_react.default.createElement(Sentry.ErrorBoundary, {
|
|
451
678
|
fallback: /*#__PURE__*/_react.default.createElement("div", null, "Something went wrong")
|
|
452
679
|
}, /*#__PURE__*/_react.default.createElement(_reactStripeJs.PaymentElement, {
|
|
453
680
|
options: {
|
|
@@ -456,21 +683,11 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
456
683
|
defaultCollapsed: false,
|
|
457
684
|
radios: true,
|
|
458
685
|
spacedAccordionItems: true
|
|
459
|
-
},
|
|
460
|
-
defaultValues: {
|
|
461
|
-
billingDetails: {
|
|
462
|
-
name: order.customer.name ?? undefined,
|
|
463
|
-
email: order.customer.email ?? undefined,
|
|
464
|
-
phone: order.billingIdentity.phone ?? undefined
|
|
465
|
-
}
|
|
466
|
-
},
|
|
467
|
-
fields: {
|
|
468
|
-
billingDetails: {
|
|
469
|
-
address: 'never'
|
|
470
|
-
}
|
|
471
686
|
}
|
|
472
687
|
}
|
|
473
|
-
})))), /*#__PURE__*/_react.default.createElement("div", {
|
|
688
|
+
})))), error && /*#__PURE__*/_react.default.createElement("div", {
|
|
689
|
+
className: "store-modal__cart__error"
|
|
690
|
+
}, error), /*#__PURE__*/_react.default.createElement("div", {
|
|
474
691
|
className: "store-modal__cart__agreement"
|
|
475
692
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
476
693
|
className: "checkbox"
|