summit-registration-lite 7.0.1 → 7.0.2
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/.codegraph/config.json +141 -0
- package/.github/workflows/ci.yml +54 -0
- package/dist/components/index.css +12 -27
- package/dist/components/index.css.map +1 -1
- package/dist/components/index.js +795 -247
- package/dist/components/index.js.map +1 -1
- package/dist/components/login-passwordless.css +1 -2
- package/dist/components/login-passwordless.js +21 -4
- package/dist/components/login-passwordless.js.map +1 -1
- package/dist/components/login.css +1 -2
- package/dist/components/login.js +69 -2
- package/dist/components/login.js.map +1 -1
- package/dist/components/registration-form.css +12 -26
- package/dist/components/registration-form.css.map +1 -1
- package/dist/components/registration-form.js +790 -243
- package/dist/components/registration-form.js.map +1 -1
- package/dist/components/registration-modal.css +12 -27
- package/dist/components/registration-modal.css.map +1 -1
- package/dist/components/registration-modal.js +794 -246
- package/dist/components/registration-modal.js.map +1 -1
- package/dist/index.css +12 -27
- package/dist/index.css.map +1 -1
- package/dist/index.js +794 -246
- package/dist/index.js.map +1 -1
- package/dist/utils/constants.js +11 -1
- package/dist/utils/constants.js.map +1 -1
- package/e2e/fixtures.js +84 -0
- package/e2e/promo-code-discovery.spec.js +364 -0
- package/package.json +12 -4
- package/playwright.config.js +26 -0
|
@@ -25,6 +25,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
25
25
|
"t$": () => (/* binding */ CLEAR_WIDGET_STATE),
|
|
26
26
|
"rr": () => (/* binding */ CREATE_RESERVATION_SUCCESS),
|
|
27
27
|
"bz": () => (/* binding */ DELETE_RESERVATION_SUCCESS),
|
|
28
|
+
"dQ": () => (/* binding */ DISCOVER_PROMO_CODES_SUCCESS),
|
|
28
29
|
"Cw": () => (/* binding */ GET_MY_INVITATION),
|
|
29
30
|
"bx": () => (/* binding */ GET_TAX_TYPES),
|
|
30
31
|
"HC": () => (/* binding */ GET_TICKET_TYPES),
|
|
@@ -40,9 +41,14 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
40
41
|
"Vx": () => (/* binding */ START_WIDGET_LOADING),
|
|
41
42
|
"sC": () => (/* binding */ STOP_WIDGET_LOADING),
|
|
42
43
|
"VH": () => (/* binding */ UPDATE_CLOCK),
|
|
44
|
+
"j6": () => (/* binding */ VALIDATE_PROMO_CODE),
|
|
45
|
+
"o5": () => (/* binding */ VALIDATE_PROMO_CODE_ERROR),
|
|
46
|
+
"Tk": () => (/* binding */ VALIDATE_PROMO_CODE_RATE_LIMITED),
|
|
47
|
+
"w6": () => (/* binding */ VALIDATE_PROMO_CODE_SUCCESS),
|
|
43
48
|
"gs": () => (/* binding */ applyPromoCode),
|
|
44
49
|
"sz": () => (/* binding */ changeStep),
|
|
45
50
|
"YS": () => (/* binding */ clearWidgetState),
|
|
51
|
+
"kM": () => (/* binding */ discoverPromoCodes),
|
|
46
52
|
"aH": () => (/* binding */ getLoginCode),
|
|
47
53
|
"q1": () => (/* binding */ getMyInvitation),
|
|
48
54
|
"xu": () => (/* binding */ getTicketTypesAndTaxes),
|
|
@@ -61,7 +67,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
61
67
|
"jn": () => (/* binding */ validatePromoCode)
|
|
62
68
|
});
|
|
63
69
|
|
|
64
|
-
// UNUSED EXPORTS: CREATE_RESERVATION, CREATE_RESERVATION_ERROR, DELETE_RESERVATION, DELETE_RESERVATION_ERROR,
|
|
70
|
+
// UNUSED EXPORTS: CREATE_RESERVATION, CREATE_RESERVATION_ERROR, DELETE_RESERVATION, DELETE_RESERVATION_ERROR, DISCOVER_PROMO_CODES
|
|
65
71
|
|
|
66
72
|
;// CONCATENATED MODULE: external "openstack-uicore-foundation/lib/utils/actions"
|
|
67
73
|
const actions_namespaceObject = require("openstack-uicore-foundation/lib/utils/actions");
|
|
@@ -397,6 +403,11 @@ const LOAD_PROFILE_DATA = 'LOAD_PROFILE_DATA';
|
|
|
397
403
|
const SET_CURRENT_PROMO_CODE = 'SET_CURRENT_PROMO_CODE';
|
|
398
404
|
const CLEAR_CURRENT_PROMO_CODE = 'CLEAR_CURRENT_PROMO_CODE';
|
|
399
405
|
const VALIDATE_PROMO_CODE = 'VALIDATE_PROMO_CODE';
|
|
406
|
+
const VALIDATE_PROMO_CODE_SUCCESS = 'VALIDATE_PROMO_CODE_SUCCESS';
|
|
407
|
+
const VALIDATE_PROMO_CODE_ERROR = 'VALIDATE_PROMO_CODE_ERROR';
|
|
408
|
+
const VALIDATE_PROMO_CODE_RATE_LIMITED = 'VALIDATE_PROMO_CODE_RATE_LIMITED';
|
|
409
|
+
const DISCOVER_PROMO_CODES = 'DISCOVER_PROMO_CODES';
|
|
410
|
+
const DISCOVER_PROMO_CODES_SUCCESS = 'DISCOVER_PROMO_CODES_SUCCESS';
|
|
400
411
|
const startWidgetLoading = (0,actions_namespaceObject.createAction)(START_WIDGET_LOADING);
|
|
401
412
|
const stopWidgetLoading = (0,actions_namespaceObject.createAction)(STOP_WIDGET_LOADING);
|
|
402
413
|
const loadSession = settings => dispatch => {
|
|
@@ -409,6 +420,23 @@ const clearWidgetState = () => dispatch => {
|
|
|
409
420
|
dispatch((0,actions_namespaceObject.createAction)(CLEAR_WIDGET_STATE)({}));
|
|
410
421
|
};
|
|
411
422
|
|
|
423
|
+
const promoCodeErrorHandler = (err, res) => (dispatch, state) => {
|
|
424
|
+
// 404: promo code or ticket type not found
|
|
425
|
+
// 412: promo code invalid for this ticket type/qty
|
|
426
|
+
if (res && [404, 412].includes(res.statusCode)) {
|
|
427
|
+
dispatch((0,actions_namespaceObject.createAction)(VALIDATE_PROMO_CODE_ERROR)({}));
|
|
428
|
+
return;
|
|
429
|
+
} // 429: rate limited - transient, preserve current promo state
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
if (res && res.statusCode === 429) {
|
|
433
|
+
dispatch((0,actions_namespaceObject.createAction)(VALIDATE_PROMO_CODE_RATE_LIMITED)({}));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return (0,actions_namespaceObject.authErrorHandler)(err, res)(dispatch, state);
|
|
438
|
+
};
|
|
439
|
+
|
|
412
440
|
const customErrorHandler = (err, res) => (dispatch, state) => {
|
|
413
441
|
if (err.timeout) {
|
|
414
442
|
return err;
|
|
@@ -426,13 +454,35 @@ const customErrorHandler = (err, res) => (dispatch, state) => {
|
|
|
426
454
|
};
|
|
427
455
|
/*********************************************************************************/
|
|
428
456
|
|
|
457
|
+
/* PROMO CODE DISCOVERY */
|
|
458
|
+
|
|
459
|
+
/*********************************************************************************/
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
const discoverPromoCodes = summitId => async (dispatch, getState, {
|
|
463
|
+
apiBaseUrl,
|
|
464
|
+
getAccessToken
|
|
465
|
+
}) => {
|
|
466
|
+
try {
|
|
467
|
+
const accessToken = await getAccessToken();
|
|
468
|
+
return (0,actions_namespaceObject.getRequest)((0,actions_namespaceObject.createAction)(DISCOVER_PROMO_CODES), (0,actions_namespaceObject.createAction)(DISCOVER_PROMO_CODES_SUCCESS), `${apiBaseUrl}/api/v1/summits/${summitId}/promo-codes/all/discover`, // Discovery is non-blocking - errors silently ignored.
|
|
469
|
+
// Auth errors will surface on the next user-initiated action.
|
|
470
|
+
null)({
|
|
471
|
+
access_token: accessToken
|
|
472
|
+
})(dispatch);
|
|
473
|
+
} catch (e) {
|
|
474
|
+
console.log(e);
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
/*********************************************************************************/
|
|
479
|
+
|
|
429
480
|
/* TICKETS */
|
|
430
481
|
|
|
431
482
|
/*********************************************************************************/
|
|
432
483
|
// api/v1/summits/{id}/ticket-types/allowed
|
|
433
484
|
// api/v1/summits/{id}/tax-types
|
|
434
485
|
|
|
435
|
-
|
|
436
486
|
const getTicketTypesAndTaxes = summitId => async dispatch => {
|
|
437
487
|
return Promise.all([dispatch(getTicketTypes(summitId)), dispatch(getTaxesTypes(summitId))]).then(values => {
|
|
438
488
|
return values;
|
|
@@ -504,22 +554,23 @@ const getTaxesTypes = summitId => async (dispatch, getState, {
|
|
|
504
554
|
}
|
|
505
555
|
};
|
|
506
556
|
|
|
507
|
-
const applyPromoCode = currentPromoCode => (dispatch, getState) => {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
summitId
|
|
513
|
-
}
|
|
557
|
+
const applyPromoCode = currentPromoCode => async (dispatch, getState) => {
|
|
558
|
+
const {
|
|
559
|
+
registrationLiteState: {
|
|
560
|
+
settings: {
|
|
561
|
+
summitId
|
|
514
562
|
}
|
|
515
|
-
}
|
|
563
|
+
}
|
|
564
|
+
} = getState();
|
|
516
565
|
|
|
566
|
+
try {
|
|
517
567
|
dispatch((0,actions_namespaceObject.createAction)(SET_CURRENT_PROMO_CODE)({
|
|
518
568
|
currentPromoCode
|
|
519
569
|
}));
|
|
520
|
-
dispatch(getTicketTypes(summitId));
|
|
570
|
+
await dispatch(getTicketTypes(summitId));
|
|
521
571
|
} catch (e) {
|
|
522
|
-
|
|
572
|
+
dispatch((0,actions_namespaceObject.createAction)(CLEAR_CURRENT_PROMO_CODE)({}));
|
|
573
|
+
throw e;
|
|
523
574
|
}
|
|
524
575
|
};
|
|
525
576
|
const removePromoCode = () => (dispatch, getState) => {
|
|
@@ -539,9 +590,13 @@ const removePromoCode = () => (dispatch, getState) => {
|
|
|
539
590
|
return Promise.reject(e);
|
|
540
591
|
}
|
|
541
592
|
};
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
593
|
+
/**
|
|
594
|
+
* Validates promo code for a specific ticket selection.
|
|
595
|
+
* Stores allows_to_reassign in Redux state.
|
|
596
|
+
* Returns response or throws error - caller handles UI concerns.
|
|
597
|
+
*/
|
|
598
|
+
|
|
599
|
+
const validatePromoCode = ticketData => async (dispatch, getState, {
|
|
545
600
|
apiBaseUrl,
|
|
546
601
|
getAccessToken
|
|
547
602
|
}) => {
|
|
@@ -552,61 +607,24 @@ const validatePromoCode = (ticketData, {
|
|
|
552
607
|
},
|
|
553
608
|
promoCode: currentPromoCode
|
|
554
609
|
}
|
|
555
|
-
} = getState();
|
|
556
|
-
const {
|
|
557
|
-
promoCode: formPromoCode
|
|
558
|
-
} = ticketData;
|
|
559
|
-
|
|
560
|
-
if (formPromoCode && !currentPromoCode) {
|
|
561
|
-
const defaultMessage = `You entered a promo code but it hasn't been applied. Make sure to click the 'Apply' button or remove it before continuing.`;
|
|
562
|
-
const notAppliedCodeError = {
|
|
563
|
-
body: {
|
|
564
|
-
errors: [defaultMessage]
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
|
-
return onError(null, notAppliedCodeError);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
if (summitId && currentPromoCode) {
|
|
571
|
-
dispatch(startWidgetLoading());
|
|
572
|
-
const {
|
|
573
|
-
ticketQuantity,
|
|
574
|
-
id,
|
|
575
|
-
sub_type
|
|
576
|
-
} = ticketData;
|
|
577
|
-
const access_token = await getAccessToken();
|
|
578
|
-
let apiUrl = external_urijs_default()(`${apiBaseUrl}/api/v1/summits/${summitId}/promo-codes/${currentPromoCode}/apply`);
|
|
579
|
-
apiUrl.addQuery('access_token', access_token);
|
|
580
|
-
apiUrl.addQuery('filter[]', `ticket_type_id==${id}`);
|
|
581
|
-
apiUrl.addQuery('filter[]', `ticket_type_qty==${ticketQuantity}`);
|
|
582
|
-
apiUrl.addQuery('filter[]', `ticket_type_subtype==${sub_type}`);
|
|
583
|
-
|
|
584
|
-
const errorHandler = (err, res) => (dispatch, state) => {
|
|
585
|
-
if (res && res.statusCode === 404 && onError) return onError(err, res);
|
|
586
|
-
if (res && res.statusCode === 412 && onError) return onError(err, res);
|
|
587
|
-
if (res && res.statusCode === 429 && onError) return onError(err, res);
|
|
588
|
-
|
|
589
|
-
if (res && res.statusCode === 500) {
|
|
590
|
-
const defaultMessage = 'Server Error';
|
|
591
|
-
const msg = res?.body?.message || defaultMessage;
|
|
592
|
-
external_sweetalert2_default().fire("Server Error", msg, "error");
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
610
|
+
} = getState(); // Nothing to validate if no promo code applied
|
|
595
611
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
return (0,actions_namespaceObject.getRequest)(null, (0,actions_namespaceObject.createAction)(VALIDATE_PROMO_CODE), `${apiUrl}`, errorHandler)({})(dispatch).then(res => {
|
|
600
|
-
dispatch(changeStep(constants.STEP_PERSONAL_INFO));
|
|
601
|
-
dispatch(stopWidgetLoading());
|
|
602
|
-
return res;
|
|
603
|
-
}).catch(error => {
|
|
604
|
-
dispatch(stopWidgetLoading());
|
|
605
|
-
return Promise.reject(error);
|
|
606
|
-
});
|
|
612
|
+
if (!summitId || !currentPromoCode) {
|
|
613
|
+
return null;
|
|
607
614
|
}
|
|
608
615
|
|
|
609
|
-
|
|
616
|
+
const {
|
|
617
|
+
ticketQuantity = 1,
|
|
618
|
+
id,
|
|
619
|
+
sub_type
|
|
620
|
+
} = ticketData;
|
|
621
|
+
const access_token = await getAccessToken();
|
|
622
|
+
let apiUrl = external_urijs_default()(`${apiBaseUrl}/api/v1/summits/${summitId}/promo-codes/${currentPromoCode}/apply`);
|
|
623
|
+
apiUrl.addQuery('access_token', access_token);
|
|
624
|
+
apiUrl.addQuery('filter[]', `ticket_type_id==${id}`);
|
|
625
|
+
apiUrl.addQuery('filter[]', `ticket_type_qty==${ticketQuantity}`);
|
|
626
|
+
apiUrl.addQuery('filter[]', `ticket_type_subtype==${sub_type}`);
|
|
627
|
+
return (0,actions_namespaceObject.getRequest)((0,actions_namespaceObject.createAction)(VALIDATE_PROMO_CODE), (0,actions_namespaceObject.createAction)(VALIDATE_PROMO_CODE_SUCCESS), `${apiUrl}`, promoCodeErrorHandler)({})(dispatch);
|
|
610
628
|
};
|
|
611
629
|
const reserveTicket = ({
|
|
612
630
|
provider,
|
|
@@ -1407,10 +1425,16 @@ var formatErrorMessage = __webpack_require__(104);
|
|
|
1407
1425
|
var utils = __webpack_require__(452);
|
|
1408
1426
|
;// CONCATENATED MODULE: ./src/helpers/getTicketMaxQuantity.js
|
|
1409
1427
|
|
|
1410
|
-
const getTicketMaxQuantity = ticket => {
|
|
1428
|
+
const getTicketMaxQuantity = (ticket, remainingQuantityPerAccount) => {
|
|
1411
1429
|
if (!ticket) return 0;
|
|
1412
1430
|
if ((0,utils/* isPrePaidTicketType */.B6)(ticket)) return 1;
|
|
1413
|
-
|
|
1431
|
+
let max = Math.min((ticket.quantity_2_sell ?? Number.MAX_SAFE_INTEGER) - ticket.quantity_sold, ticket.max_quantity_per_order ?? Number.MAX_SAFE_INTEGER);
|
|
1432
|
+
|
|
1433
|
+
if (remainingQuantityPerAccount != null) {
|
|
1434
|
+
max = Math.min(max, remainingQuantityPerAccount);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
return max;
|
|
1414
1438
|
};
|
|
1415
1439
|
;// CONCATENATED MODULE: ./src/helpers/index.js
|
|
1416
1440
|
|
|
@@ -1438,6 +1462,7 @@ const getTicketMaxQuantity = ticket => {
|
|
|
1438
1462
|
/* harmony export */ "ORDER_STATUS_PAID": () => (/* binding */ ORDER_STATUS_PAID),
|
|
1439
1463
|
/* harmony export */ "PAYMENT_PROVIDER_LAWPAY": () => (/* binding */ PAYMENT_PROVIDER_LAWPAY),
|
|
1440
1464
|
/* harmony export */ "PAYMENT_PROVIDER_STRIPE": () => (/* binding */ PAYMENT_PROVIDER_STRIPE),
|
|
1465
|
+
/* harmony export */ "PROMO_STATUS": () => (/* binding */ PROMO_STATUS),
|
|
1441
1466
|
/* harmony export */ "PURCHASE_COMPLETE": () => (/* binding */ PURCHASE_COMPLETE),
|
|
1442
1467
|
/* harmony export */ "RESEND_TIME": () => (/* binding */ RESEND_TIME),
|
|
1443
1468
|
/* harmony export */ "STEP_COMPLETE": () => (/* binding */ STEP_COMPLETE),
|
|
@@ -1491,7 +1516,16 @@ const PURCHASE_COMPLETE = 'purchase_complete'; // ERRORS
|
|
|
1491
1516
|
|
|
1492
1517
|
const ERROR_TYPE_ERROR = 'error_type_error';
|
|
1493
1518
|
const ERROR_TYPE_VALIDATION = 'error_type_validation';
|
|
1494
|
-
const ERROR_TYPE_PAYMENT = 'error_type_payment'; //
|
|
1519
|
+
const ERROR_TYPE_PAYMENT = 'error_type_payment'; // PROMO CODE STATUS
|
|
1520
|
+
|
|
1521
|
+
const PROMO_STATUS = {
|
|
1522
|
+
IDLE: 'idle',
|
|
1523
|
+
SUGGESTED: 'suggested',
|
|
1524
|
+
APPLYING: 'applying',
|
|
1525
|
+
VALIDATING: 'validating',
|
|
1526
|
+
VALID: 'valid',
|
|
1527
|
+
INVALID: 'invalid'
|
|
1528
|
+
}; // PROVIDERS
|
|
1495
1529
|
|
|
1496
1530
|
const PAYMENT_PROVIDER_STRIPE = 'Stripe';
|
|
1497
1531
|
const PAYMENT_PROVIDER_LAWPAY = 'LawPay';
|
|
@@ -1755,7 +1789,11 @@ const DEFAULT_STATE = {
|
|
|
1755
1789
|
userProfile: null
|
|
1756
1790
|
},
|
|
1757
1791
|
nowUtc: localNowUtc,
|
|
1758
|
-
promoCode: ''
|
|
1792
|
+
promoCode: '',
|
|
1793
|
+
promoCodeVerified: null,
|
|
1794
|
+
promoCodeValidating: false,
|
|
1795
|
+
promoCodeAllowsReassign: true,
|
|
1796
|
+
discoveredPromoCodes: []
|
|
1759
1797
|
};
|
|
1760
1798
|
|
|
1761
1799
|
const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
@@ -1763,7 +1801,6 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1763
1801
|
type,
|
|
1764
1802
|
payload
|
|
1765
1803
|
} = action;
|
|
1766
|
-
console.log(action);
|
|
1767
1804
|
|
|
1768
1805
|
switch (type) {
|
|
1769
1806
|
case actions/* CLEAR_WIDGET_STATE */.t$:
|
|
@@ -1806,6 +1843,10 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1806
1843
|
requestedTicketTypes: false,
|
|
1807
1844
|
taxTypes: [],
|
|
1808
1845
|
invitation: null,
|
|
1846
|
+
promoCode: '',
|
|
1847
|
+
promoCodeVerified: null,
|
|
1848
|
+
promoCodeAllowsReassign: true,
|
|
1849
|
+
discoveredPromoCodes: [],
|
|
1809
1850
|
passwordless: _objectSpread({}, DEFAULT_STATE.passwordless),
|
|
1810
1851
|
settings: _objectSpread(_objectSpread({}, DEFAULT_STATE.settings), {}, {
|
|
1811
1852
|
summitId: summitData.id,
|
|
@@ -1910,7 +1951,11 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1910
1951
|
{
|
|
1911
1952
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
1912
1953
|
reservation: null,
|
|
1913
|
-
promoCode: ''
|
|
1954
|
+
promoCode: '',
|
|
1955
|
+
promoCodeVerified: null,
|
|
1956
|
+
promoCodeValidating: false,
|
|
1957
|
+
promoCodeAllowsReassign: true,
|
|
1958
|
+
discoveredPromoCodes: []
|
|
1914
1959
|
});
|
|
1915
1960
|
}
|
|
1916
1961
|
|
|
@@ -1921,7 +1966,11 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1921
1966
|
reservation: null,
|
|
1922
1967
|
userProfile: null,
|
|
1923
1968
|
invitation: null,
|
|
1924
|
-
promoCode: ''
|
|
1969
|
+
promoCode: '',
|
|
1970
|
+
promoCodeVerified: null,
|
|
1971
|
+
promoCodeValidating: false,
|
|
1972
|
+
promoCodeAllowsReassign: true,
|
|
1973
|
+
discoveredPromoCodes: []
|
|
1925
1974
|
});
|
|
1926
1975
|
}
|
|
1927
1976
|
|
|
@@ -1952,7 +2001,10 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1952
2001
|
case actions/* CLEAR_CURRENT_PROMO_CODE */.ZD:
|
|
1953
2002
|
{
|
|
1954
2003
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
1955
|
-
promoCode: ''
|
|
2004
|
+
promoCode: '',
|
|
2005
|
+
promoCodeVerified: null,
|
|
2006
|
+
promoCodeValidating: false,
|
|
2007
|
+
promoCodeAllowsReassign: true
|
|
1956
2008
|
});
|
|
1957
2009
|
}
|
|
1958
2010
|
|
|
@@ -1962,7 +2014,52 @@ const RegistrationLiteReducer = (state = DEFAULT_STATE, action) => {
|
|
|
1962
2014
|
currentPromoCode
|
|
1963
2015
|
} = payload;
|
|
1964
2016
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
1965
|
-
promoCode: currentPromoCode
|
|
2017
|
+
promoCode: currentPromoCode,
|
|
2018
|
+
promoCodeVerified: null,
|
|
2019
|
+
promoCodeValidating: false,
|
|
2020
|
+
promoCodeAllowsReassign: true
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
case actions/* VALIDATE_PROMO_CODE */.j6:
|
|
2025
|
+
{
|
|
2026
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
2027
|
+
promoCodeValidating: true
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
case actions/* VALIDATE_PROMO_CODE_SUCCESS */.w6:
|
|
2032
|
+
{
|
|
2033
|
+
const {
|
|
2034
|
+
allows_to_reassign
|
|
2035
|
+
} = payload.response;
|
|
2036
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
2037
|
+
promoCodeVerified: true,
|
|
2038
|
+
promoCodeValidating: false,
|
|
2039
|
+
promoCodeAllowsReassign: allows_to_reassign ?? true
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
case actions/* VALIDATE_PROMO_CODE_ERROR */.o5:
|
|
2044
|
+
{
|
|
2045
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
2046
|
+
promoCodeVerified: false,
|
|
2047
|
+
promoCodeValidating: false,
|
|
2048
|
+
promoCodeAllowsReassign: true
|
|
2049
|
+
});
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
case actions/* VALIDATE_PROMO_CODE_RATE_LIMITED */.Tk:
|
|
2053
|
+
{
|
|
2054
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
2055
|
+
promoCodeValidating: false
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
case actions/* DISCOVER_PROMO_CODES_SUCCESS */.dQ:
|
|
2060
|
+
{
|
|
2061
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
2062
|
+
discoveredPromoCodes: payload.response?.data || []
|
|
1966
2063
|
});
|
|
1967
2064
|
}
|
|
1968
2065
|
|
|
@@ -2080,13 +2177,6 @@ module.exports = "data:image/svg+xml,%3c!-- Generator: Adobe Illustrator 25.4.1,
|
|
|
2080
2177
|
|
|
2081
2178
|
/***/ }),
|
|
2082
2179
|
|
|
2083
|
-
/***/ 60:
|
|
2084
|
-
/***/ ((module) => {
|
|
2085
|
-
|
|
2086
|
-
module.exports = "data:image/svg+xml,%3csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3cpath d='M8.11475 2.60519C9.64837 2.25868 11.2529 2.41721 12.6891 3.05713C13.0978 3.23923 13.5767 3.05555 13.7588 2.64686C13.9409 2.23817 13.7572 1.75925 13.3485 1.57714C11.5932 0.795024 9.6321 0.601267 7.75767 1.02477C5.88325 1.44827 4.19593 2.46634 2.94738 3.92714C1.69883 5.38795 0.955938 7.21321 0.829498 9.13072C0.703058 11.0482 1.19985 12.9552 2.24577 14.5673C3.2917 16.1794 4.83072 17.4103 6.6333 18.0762C8.43589 18.7422 10.4055 18.8076 12.2483 18.2627C14.0911 17.7179 15.7084 16.5919 16.859 15.0528C18.0096 13.5137 18.6319 11.6438 18.633 9.72216V8.97638C18.633 8.52896 18.2703 8.16625 17.8228 8.16625C17.3754 8.16625 17.0127 8.52896 17.0127 8.97638V9.72123C17.0118 11.2935 16.5027 12.8234 15.5613 14.0827C14.6199 15.342 13.2966 16.2632 11.7889 16.709C10.2811 17.1548 8.66965 17.1012 7.19481 16.5564C5.71996 16.0115 4.46077 15.0045 3.60501 13.6855C2.74925 12.3665 2.34279 10.8062 2.44624 9.23733C2.54969 7.66846 3.15751 6.17506 4.17905 4.97986C5.2006 3.78465 6.58112 2.95169 8.11475 2.60519Z' fill='%2392CD76'/%3e %3cpath d='M18.396 3.81325C18.7122 3.49672 18.7119 2.98378 18.3954 2.66756C18.0789 2.35134 17.5659 2.3516 17.2497 2.66813L9.72129 10.2041L7.86404 8.34683C7.54767 8.03046 7.03472 8.03046 6.71835 8.34683C6.40197 8.66321 6.40197 9.17615 6.71835 9.49253L9.14873 11.9229C9.30071 12.0749 9.50685 12.1602 9.72178 12.1602C9.93671 12.1601 10.1428 12.0747 10.2947 11.9226L18.396 3.81325Z' fill='%2392CD76'/%3e %3c/svg%3e"
|
|
2087
|
-
|
|
2088
|
-
/***/ }),
|
|
2089
|
-
|
|
2090
2180
|
/***/ 267:
|
|
2091
2181
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
2092
2182
|
|
|
@@ -2152,7 +2242,7 @@ module.exports = require("sweetalert2");
|
|
|
2152
2242
|
/***/ ((module) => {
|
|
2153
2243
|
|
|
2154
2244
|
"use strict";
|
|
2155
|
-
module.exports = JSON.parse('{"purchase_complete_step":{"title":" Your order is complete","initial_order_complete_1st_paragraph_label":"A ticket has been assigned to {attendee}. To complete {adv} additional ticket details, please click the \\"{button}\\" button.","initial_order_complete_button":"Finish Now","order_complete_1st_paragraph_label":"You may visit the \\"My Orders/Tickets\\" tab in the top right-hand corner of the navigation bar to\\n assign/reassign tickets or to complete any required ticket details.","order_complete_button":"View My Orders/Tickets","access_event_button":"Access Event Now","initial_order_footer_label":"If you wish to transfer your assigned ticket, close this window and visit the \\"My Orders/Tickets\\" tab in the top navigation bar. ","footer_assistance_text":"For further assistance, please email <a href=\\"mailto:{supportEmail}\\">{supportEmail}</a>","event_will_start_text":"The event will start on {date} at {time} {time_zone_label}"},"ticket_type":{"ticket_quantity_tooltip":"Only one ticket type can be selected per order. To purchase multiple ticket types, please place a separate registration order for each ticket type."},"promo_code":{"promo_code_tooltip":"Only one promo code can be used per order; the code will be applied to all tickets in this order. If you\'d like to use multiple promo codes, please place a separate registration order for each promo code."}}');
|
|
2245
|
+
module.exports = JSON.parse('{"purchase_complete_step":{"title":" Your order is complete","initial_order_complete_1st_paragraph_label":"A ticket has been assigned to {attendee}. To complete {adv} additional ticket details, please click the \\"{button}\\" button.","initial_order_complete_button":"Finish Now","order_complete_1st_paragraph_label":"You may visit the \\"My Orders/Tickets\\" tab in the top right-hand corner of the navigation bar to\\n assign/reassign tickets or to complete any required ticket details.","order_complete_button":"View My Orders/Tickets","access_event_button":"Access Event Now","initial_order_footer_label":"If you wish to transfer your assigned ticket, close this window and visit the \\"My Orders/Tickets\\" tab in the top navigation bar. ","footer_assistance_text":"For further assistance, please email <a href=\\"mailto:{supportEmail}\\">{supportEmail}</a>","event_will_start_text":"The event will start on {date} at {time} {time_zone_label}"},"ticket_type":{"ticket_quantity_tooltip":"Only one ticket type can be selected per order. To purchase multiple ticket types, please place a separate registration order for each ticket type.","no_tickets_available":"There are no tickets currently available for purchase. If you have a promo code, enter it below to check for eligible tickets.","max_per_order_one":"This ticket type is limited to 1 per order.","max_per_order_other":"This ticket type is limited to {limit} per order."},"promo_code":{"promo_code_tooltip":"Only one promo code can be used per order; the code will be applied to all tickets in this order. If you\'d like to use multiple promo codes, please place a separate registration order for each promo code.","default_label":"Do you have a promo code?","auto_applied_label":"Following promo code was automatically applied:","applied_label":"Applied promo code:","applying_label":"Applying promo code...","suggestion_label":"You qualify for the following promo code:","per_account_limit_one":"Promo code limits {limit} ticket per account.","per_account_limit_other":"Promo code limits {limit} tickets per account.","non_transferable":"This ticket will be automatically assigned to you and cannot be reassigned.","unapplied_code_warning":"You entered a promo code but it hasn\'t been applied. Make sure to click the \'Apply\' button or remove it before continuing.","invalid_code":"Promo code entered is not valid.","validation_error":"An error occurred while validating the promo code."}}');
|
|
2156
2246
|
|
|
2157
2247
|
/***/ })
|
|
2158
2248
|
|
|
@@ -2255,6 +2345,256 @@ const external_react_use_namespaceObject = require("react-use");
|
|
|
2255
2345
|
const constants_namespaceObject = require("openstack-uicore-foundation/lib/security/constants");
|
|
2256
2346
|
// EXTERNAL MODULE: ./src/actions.js + 5 modules
|
|
2257
2347
|
var actions = __webpack_require__(595);
|
|
2348
|
+
;// CONCATENATED MODULE: external "i18n-react"
|
|
2349
|
+
const external_i18n_react_namespaceObject = require("i18n-react");
|
|
2350
|
+
var external_i18n_react_default = /*#__PURE__*/__webpack_require__.n(external_i18n_react_namespaceObject);
|
|
2351
|
+
// EXTERNAL MODULE: ./src/utils/constants.js
|
|
2352
|
+
var constants = __webpack_require__(243);
|
|
2353
|
+
;// CONCATENATED MODULE: ./src/hooks/usePromoCode.js
|
|
2354
|
+
|
|
2355
|
+
|
|
2356
|
+
|
|
2357
|
+
|
|
2358
|
+
const usePromoCode = ({
|
|
2359
|
+
// Redux state
|
|
2360
|
+
discoveredPromoCodes,
|
|
2361
|
+
promoCode,
|
|
2362
|
+
promoCodeVerified,
|
|
2363
|
+
promoCodeValidating,
|
|
2364
|
+
// Redux dispatchers
|
|
2365
|
+
applyPromoCode,
|
|
2366
|
+
removePromoCode,
|
|
2367
|
+
validatePromoCode,
|
|
2368
|
+
// Form integration
|
|
2369
|
+
ticketDataLoaded = false,
|
|
2370
|
+
hasTickets = false,
|
|
2371
|
+
setFormPromoCode
|
|
2372
|
+
}) => {
|
|
2373
|
+
// Per-session lock: once the user removes (or auto-apply fails for) a
|
|
2374
|
+
// discovered code, don't re-apply it on this widget mount. Never reset.
|
|
2375
|
+
const [userRemovedAutoApply, setUserRemovedAutoApply] = (0,external_react_.useState)(false);
|
|
2376
|
+
const [isAutoApplied, setIsAutoApplied] = (0,external_react_.useState)(false);
|
|
2377
|
+
const [suggestionActive, setSuggestionActive] = (0,external_react_.useState)(false);
|
|
2378
|
+
const [suggestionDismissed, setSuggestionDismissed] = (0,external_react_.useState)(false); // Error written by handleValidationError (API) or the form (unapplied-code warning).
|
|
2379
|
+
// The user-facing `validationError` is computed below by merging this with the
|
|
2380
|
+
// status-derived INVALID message.
|
|
2381
|
+
|
|
2382
|
+
const [manualError, setManualError] = (0,external_react_.useState)(null);
|
|
2383
|
+
const [applyingCode, setApplyingCode] = (0,external_react_.useState)(false); // Pick first auto_apply code, or first code if none has auto_apply
|
|
2384
|
+
|
|
2385
|
+
const discoveredPromoCode = (0,external_react_.useMemo)(() => {
|
|
2386
|
+
if (!discoveredPromoCodes?.length) return null;
|
|
2387
|
+
return discoveredPromoCodes.find(c => c.auto_apply) || discoveredPromoCodes[0];
|
|
2388
|
+
}, [discoveredPromoCodes]);
|
|
2389
|
+
const isApplied = !!promoCode;
|
|
2390
|
+
const isDiscoveredCode = isApplied && discoveredPromoCode?.code === promoCode; // --- Status ---
|
|
2391
|
+
|
|
2392
|
+
const status = (0,external_react_.useMemo)(() => {
|
|
2393
|
+
if (isApplied) {
|
|
2394
|
+
if (promoCodeValidating) return constants.PROMO_STATUS.VALIDATING;
|
|
2395
|
+
if (promoCodeVerified === true) return constants.PROMO_STATUS.VALID;
|
|
2396
|
+
if (promoCodeVerified === false) return constants.PROMO_STATUS.INVALID; // Applied but no tickets returned and not currently applying: code is invalid
|
|
2397
|
+
|
|
2398
|
+
if (!applyingCode && ticketDataLoaded && !hasTickets) return constants.PROMO_STATUS.INVALID;
|
|
2399
|
+
return constants.PROMO_STATUS.APPLYING;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
if (suggestionActive && !suggestionDismissed) return constants.PROMO_STATUS.SUGGESTED;
|
|
2403
|
+
return constants.PROMO_STATUS.IDLE;
|
|
2404
|
+
}, [isApplied, promoCodeVerified, promoCodeValidating, suggestionActive, suggestionDismissed, applyingCode, ticketDataLoaded, hasTickets]); // Hook's own validation error. Composed from the in-flight API error (if any)
|
|
2405
|
+
// and the status-derived "invalid code" message when status is INVALID.
|
|
2406
|
+
// Consumers may layer their own warning on top before display.
|
|
2407
|
+
|
|
2408
|
+
const validationError = manualError ?? (status === constants.PROMO_STATUS.INVALID ? external_i18n_react_default().translate('promo_code.invalid_code') : null); // --- Derived values ---
|
|
2409
|
+
|
|
2410
|
+
const suggestedCode = discoveredPromoCode?.code || null;
|
|
2411
|
+
const activeDiscoveredCode = status === constants.PROMO_STATUS.VALID && isDiscoveredCode ? discoveredPromoCode : null;
|
|
2412
|
+
const perAccountLimit = activeDiscoveredCode?.quantity_per_account > 0 ? activeDiscoveredCode.remaining_quantity_per_account : null; // Tightest promo-code-level quantity cap for the stepper (discovered codes only).
|
|
2413
|
+
// Both cap sources use `!= null` so a value of 0 (sold-out / no remaining) caps the
|
|
2414
|
+
// stepper at 0 instead of being silently ignored.
|
|
2415
|
+
|
|
2416
|
+
const maxQuantityFromPromo = (0,external_react_.useMemo)(() => {
|
|
2417
|
+
if (!activeDiscoveredCode) return null;
|
|
2418
|
+
const caps = [];
|
|
2419
|
+
if (activeDiscoveredCode.remaining_quantity_per_account != null) caps.push(activeDiscoveredCode.remaining_quantity_per_account);
|
|
2420
|
+
if (activeDiscoveredCode.quantity_available != null) caps.push(activeDiscoveredCode.quantity_available);
|
|
2421
|
+
return caps.length > 0 ? Math.min(...caps) : null;
|
|
2422
|
+
}, [activeDiscoveredCode]); // True when the user can safely advance from the ticket step
|
|
2423
|
+
// (no in-flight promo apply/validate and no INVALID state to block on).
|
|
2424
|
+
|
|
2425
|
+
const isReady = status === constants.PROMO_STATUS.IDLE || status === constants.PROMO_STATUS.SUGGESTED || status === constants.PROMO_STATUS.VALID; // --- Discovery: ticket qualification ---
|
|
2426
|
+
|
|
2427
|
+
const isCodeValidForTicket = (0,external_react_.useCallback)(ticket => {
|
|
2428
|
+
if (!discoveredPromoCode || !ticket) return false;
|
|
2429
|
+
const allowed = discoveredPromoCode.allowed_ticket_types || [];
|
|
2430
|
+
if (allowed.length === 0) return true;
|
|
2431
|
+
return allowed.some(tt => (typeof tt === 'object' ? tt.id : tt) === ticket.id);
|
|
2432
|
+
}, [discoveredPromoCode]); // --- Helpers ---
|
|
2433
|
+
|
|
2434
|
+
const handleValidationError = (0,external_react_.useCallback)(e => {
|
|
2435
|
+
if (e?.res?.body) {
|
|
2436
|
+
const errors = e.res.body.errors || [e.res.body.message || external_i18n_react_default().translate('promo_code.validation_error')];
|
|
2437
|
+
const first = errors[0];
|
|
2438
|
+
const firstStr = typeof first === 'string' ? first : first?.message ?? String(first);
|
|
2439
|
+
const msg = /is not a valid code/i.test(firstStr) ? external_i18n_react_default().translate('promo_code.invalid_code') : firstStr;
|
|
2440
|
+
setManualError(msg);
|
|
2441
|
+
} else {
|
|
2442
|
+
setManualError(external_i18n_react_default().translate('promo_code.validation_error'));
|
|
2443
|
+
}
|
|
2444
|
+
}, []); // --- Actions ---
|
|
2445
|
+
|
|
2446
|
+
const onRevalidate = (0,external_react_.useCallback)(async (ticket, quantity) => {
|
|
2447
|
+
setManualError(null);
|
|
2448
|
+
|
|
2449
|
+
try {
|
|
2450
|
+
await validatePromoCode({
|
|
2451
|
+
id: ticket.id,
|
|
2452
|
+
ticketQuantity: quantity,
|
|
2453
|
+
sub_type: ticket.sub_type
|
|
2454
|
+
});
|
|
2455
|
+
return true;
|
|
2456
|
+
} catch (e) {
|
|
2457
|
+
handleValidationError(e);
|
|
2458
|
+
return false;
|
|
2459
|
+
}
|
|
2460
|
+
}, [validatePromoCode, handleValidationError]); // Shared auto-apply flow. Caller is responsible for the gating conditions
|
|
2461
|
+
// (auto_apply / single code / not already applied / not user-removed) so each
|
|
2462
|
+
// call site keeps its own trigger logic. Returns true if the code was applied
|
|
2463
|
+
// and (if a ticket was passed) successfully revalidated.
|
|
2464
|
+
//
|
|
2465
|
+
// Note on concurrency: the two call sites (early-auto-apply effect and
|
|
2466
|
+
// onTicketSelected's auto-apply branch) operate on disjoint states by design
|
|
2467
|
+
// (the effect requires `!hasTickets`, the branch requires a selected ticket),
|
|
2468
|
+
// so a true concurrent invocation is unreachable in practice. If a future
|
|
2469
|
+
// change makes that overlap possible, gate this body with a ref-tracked
|
|
2470
|
+
// in-flight flag rather than `applyingCode` (which is captured stale here).
|
|
2471
|
+
|
|
2472
|
+
const tryAutoApply = (0,external_react_.useCallback)(async ticket => {
|
|
2473
|
+
setIsAutoApplied(true);
|
|
2474
|
+
setApplyingCode(true);
|
|
2475
|
+
|
|
2476
|
+
try {
|
|
2477
|
+
await applyPromoCode(discoveredPromoCode.code);
|
|
2478
|
+
|
|
2479
|
+
if (ticket) {
|
|
2480
|
+
const valid = await onRevalidate(ticket, 1);
|
|
2481
|
+
|
|
2482
|
+
if (!valid) {
|
|
2483
|
+
setIsAutoApplied(false);
|
|
2484
|
+
return false;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
return true;
|
|
2489
|
+
} catch (e) {
|
|
2490
|
+
setIsAutoApplied(false);
|
|
2491
|
+
handleValidationError(e);
|
|
2492
|
+
return false;
|
|
2493
|
+
} finally {
|
|
2494
|
+
setApplyingCode(false);
|
|
2495
|
+
}
|
|
2496
|
+
}, [discoveredPromoCode, applyPromoCode, onRevalidate, handleValidationError]);
|
|
2497
|
+
const onTicketSelected = (0,external_react_.useCallback)(async ticket => {
|
|
2498
|
+
const qualifies = discoveredPromoCode && isCodeValidForTicket(ticket);
|
|
2499
|
+
setSuggestionActive(qualifies);
|
|
2500
|
+
setSuggestionDismissed(false);
|
|
2501
|
+
setManualError(null); // Manual (non-discovered) code is applied: re-validate for new ticket
|
|
2502
|
+
|
|
2503
|
+
if (isApplied && !isDiscoveredCode) {
|
|
2504
|
+
await onRevalidate(ticket, 1);
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
if (!discoveredPromoCode) return; // Discovered code is currently applied
|
|
2509
|
+
|
|
2510
|
+
if (isDiscoveredCode) {
|
|
2511
|
+
if (!qualifies) {
|
|
2512
|
+
setIsAutoApplied(false);
|
|
2513
|
+
removePromoCode();
|
|
2514
|
+
} else {
|
|
2515
|
+
const valid = await onRevalidate(ticket, 1);
|
|
2516
|
+
if (!valid) setIsAutoApplied(false);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
return;
|
|
2520
|
+
} // No code applied, ticket qualifies, auto-apply configured, single code only
|
|
2521
|
+
|
|
2522
|
+
|
|
2523
|
+
if (!isApplied && qualifies && discoveredPromoCode.auto_apply && !userRemovedAutoApply && discoveredPromoCodes.length === 1) {
|
|
2524
|
+
await tryAutoApply(ticket);
|
|
2525
|
+
}
|
|
2526
|
+
}, [discoveredPromoCode, isApplied, isDiscoveredCode, userRemovedAutoApply, discoveredPromoCodes, isCodeValidForTicket, removePromoCode, onRevalidate, tryAutoApply]); // Early auto-apply: when no tickets are available and a single auto_apply code
|
|
2527
|
+
// was discovered, apply it so the API returns WithPromoCode ticket types.
|
|
2528
|
+
// On failure, mark as removed to prevent re-fire loops.
|
|
2529
|
+
|
|
2530
|
+
(0,external_react_.useEffect)(() => {
|
|
2531
|
+
if (userRemovedAutoApply || isApplied) return;
|
|
2532
|
+
if (!ticketDataLoaded || hasTickets) return;
|
|
2533
|
+
if (!discoveredPromoCode?.auto_apply) return;
|
|
2534
|
+
if (discoveredPromoCodes.length !== 1) return;
|
|
2535
|
+
tryAutoApply(null).then(success => {
|
|
2536
|
+
if (!success) setUserRemovedAutoApply(true);
|
|
2537
|
+
});
|
|
2538
|
+
}, [userRemovedAutoApply, ticketDataLoaded, hasTickets, discoveredPromoCode, discoveredPromoCodes, isApplied, tryAutoApply]);
|
|
2539
|
+
const onApply = (0,external_react_.useCallback)(async (code, ticket, quantity) => {
|
|
2540
|
+
setManualError(null);
|
|
2541
|
+
setApplyingCode(true);
|
|
2542
|
+
|
|
2543
|
+
try {
|
|
2544
|
+
await applyPromoCode(code);
|
|
2545
|
+
} catch (e) {
|
|
2546
|
+
handleValidationError(e);
|
|
2547
|
+
setApplyingCode(false);
|
|
2548
|
+
return;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
if (ticket) {
|
|
2552
|
+
await onRevalidate(ticket, quantity);
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
setApplyingCode(false);
|
|
2556
|
+
}, [applyPromoCode, onRevalidate, handleValidationError]);
|
|
2557
|
+
const onRemove = (0,external_react_.useCallback)(() => {
|
|
2558
|
+
if (isAutoApplied || isDiscoveredCode) setUserRemovedAutoApply(true);
|
|
2559
|
+
setIsAutoApplied(false);
|
|
2560
|
+
setManualError(null);
|
|
2561
|
+
setSuggestionDismissed(false);
|
|
2562
|
+
if (discoveredPromoCode) setSuggestionActive(true);
|
|
2563
|
+
setFormPromoCode('');
|
|
2564
|
+
removePromoCode();
|
|
2565
|
+
}, [isAutoApplied, isDiscoveredCode, discoveredPromoCode, removePromoCode, setFormPromoCode]);
|
|
2566
|
+
const onInputChange = (0,external_react_.useCallback)(value => {
|
|
2567
|
+
setManualError(null);
|
|
2568
|
+
setSuggestionDismissed(value !== discoveredPromoCode?.code);
|
|
2569
|
+
setFormPromoCode(value);
|
|
2570
|
+
}, [discoveredPromoCode, setFormPromoCode]);
|
|
2571
|
+
return {
|
|
2572
|
+
state: {
|
|
2573
|
+
// Status (what's happening with the applied/suggested code)
|
|
2574
|
+
status,
|
|
2575
|
+
isReady,
|
|
2576
|
+
validationError,
|
|
2577
|
+
// Applied code origin
|
|
2578
|
+
isDiscoveredCode,
|
|
2579
|
+
isAutoApplied,
|
|
2580
|
+
// Discovery / suggestion
|
|
2581
|
+
suggestedCode,
|
|
2582
|
+
// Quantity caps from the active discovered code
|
|
2583
|
+
maxQuantityFromPromo,
|
|
2584
|
+
perAccountLimit
|
|
2585
|
+
},
|
|
2586
|
+
actions: {
|
|
2587
|
+
// Ordered by lifecycle: input → apply → ticket change → revalidate → remove
|
|
2588
|
+
onInputChange,
|
|
2589
|
+
onApply,
|
|
2590
|
+
onTicketSelected,
|
|
2591
|
+
onRevalidate,
|
|
2592
|
+
onRemove
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
};
|
|
2596
|
+
|
|
2597
|
+
/* harmony default export */ const hooks_usePromoCode = (usePromoCode);
|
|
2258
2598
|
;// CONCATENATED MODULE: external "openstack-uicore-foundation/lib/components/ajaxloader"
|
|
2259
2599
|
const ajaxloader_namespaceObject = require("openstack-uicore-foundation/lib/components/ajaxloader");
|
|
2260
2600
|
var ajaxloader_default = /*#__PURE__*/__webpack_require__.n(ajaxloader_namespaceObject);
|
|
@@ -2276,8 +2616,6 @@ const methods_namespaceObject = require("openstack-uicore-foundation/lib/utils/m
|
|
|
2276
2616
|
;// CONCATENATED MODULE: ./src/components/lawpay-form/index.module.scss
|
|
2277
2617
|
// extracted by mini-css-extract-plugin
|
|
2278
2618
|
/* harmony default export */ const lawpay_form_index_module = ({"form":"form___zXb7s","fieldWrapper":"fieldWrapper___G4Wqw","inputWrapper":"inputWrapper___Yz5zB","fieldRow":"fieldRow___NfZdJ","addressField":"addressField___vmAQh","lawpayWrapper":"lawpayWrapper___hpUBf","dateWrapper":"dateWrapper___XDfqs","dropdown":"dropdown___l3_bk","fieldError":"fieldError___Igq3U"});
|
|
2279
|
-
// EXTERNAL MODULE: ./src/utils/constants.js
|
|
2280
|
-
var constants = __webpack_require__(243);
|
|
2281
2619
|
;// CONCATENATED MODULE: ./src/components/lawpay-form/index.js
|
|
2282
2620
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2283
2621
|
|
|
@@ -3022,7 +3360,7 @@ var company_input_v2_default = /*#__PURE__*/__webpack_require__.n(company_input_
|
|
|
3022
3360
|
var helpers = __webpack_require__(499);
|
|
3023
3361
|
;// CONCATENATED MODULE: ./src/components/personal-information/index.module.scss
|
|
3024
3362
|
// extracted by mini-css-extract-plugin
|
|
3025
|
-
/* harmony default export */ const personal_information_index_module = ({"title":"title___ECoNz","form":"form___lDFka","fieldWrapper":"fieldWrapper___Mi_nL","fieldWrapperRadio":"fieldWrapperRadio___x18VG","inputWrapper":"inputWrapper___PEQFR","readOnly":"readOnly___WRazF","fieldError":"fieldError___ksJVe","moreInfo":"moreInfo___cQYdZ","moreInfoTooltip":"moreInfoTooltip___lslgT","ticketQuantityNotice":"ticketQuantityNotice___L6gis","formErrors":"formErrors___dQQMe"});
|
|
3363
|
+
/* harmony default export */ const personal_information_index_module = ({"title":"title___ECoNz","form":"form___lDFka","fieldWrapper":"fieldWrapper___Mi_nL","fieldWrapperRadio":"fieldWrapperRadio___x18VG","form-check-label":"form-check-label___MgGSC","inputWrapper":"inputWrapper___PEQFR","readOnly":"readOnly___WRazF","fieldError":"fieldError___ksJVe","moreInfo":"moreInfo___cQYdZ","moreInfoTooltip":"moreInfoTooltip___lslgT","ticketQuantityNotice":"ticketQuantityNotice___L6gis","formErrors":"formErrors___dQQMe"});
|
|
3026
3364
|
;// CONCATENATED MODULE: ./src/components/personal-information/index.js
|
|
3027
3365
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
3028
3366
|
|
|
@@ -3063,20 +3401,27 @@ const PersonalInfoComponent = ({
|
|
|
3063
3401
|
summitId,
|
|
3064
3402
|
handleCompanyError,
|
|
3065
3403
|
formValues,
|
|
3066
|
-
formErrors =
|
|
3404
|
+
formErrors = [],
|
|
3067
3405
|
invitation,
|
|
3068
3406
|
showCompanyInput = true,
|
|
3069
3407
|
companyDDLPlaceholder,
|
|
3070
3408
|
showCompanyInputDefaultOptions,
|
|
3071
|
-
companyDDLOptions2Show
|
|
3409
|
+
companyDDLOptions2Show,
|
|
3410
|
+
promoCodeAllowsReassign = true
|
|
3072
3411
|
}) => {
|
|
3073
3412
|
const initialFirstName = userProfile.given_name || (invitation ? invitation.first_name : '');
|
|
3074
3413
|
const initialLastName = userProfile.family_name || (invitation ? invitation.last_name : '');
|
|
3075
3414
|
const [ticketOwnerOption, setTicketOwnerOption] = (0,external_react_.useState)('');
|
|
3076
|
-
const [ticketOwnerError, setTicketOwnerError] = (0,external_react_.useState)(false); // if there's only one ticket on the order and there is no invitation available,
|
|
3415
|
+
const [ticketOwnerError, setTicketOwnerError] = (0,external_react_.useState)(false); // if there's only one ticket on the order and there is no invitation available, handle ticket assignment
|
|
3416
|
+
|
|
3417
|
+
const isSingleTicketOrder = formValues.ticketQuantity === 1 && !invitation && !(0,utils/* isPrePaidTicketType */.B6)(formValues.ticketType); // check if reassignment is allowed by both promo code AND ticket type
|
|
3077
3418
|
|
|
3078
|
-
const
|
|
3419
|
+
const ticketTypeAllowsReassign = formValues.ticketType?.allows_to_reassign !== false;
|
|
3420
|
+
const canReassign = promoCodeAllowsReassign && ticketTypeAllowsReassign; // show radio options only if reassignment is allowed by both sources
|
|
3079
3421
|
|
|
3422
|
+
const shouldDisplayTicketAssignment = isSingleTicketOrder && canReassign; // show notice when ticket is non-transferable (either promo code or ticket type disallows)
|
|
3423
|
+
|
|
3424
|
+
const isNonTransferable = isSingleTicketOrder && !canReassign;
|
|
3080
3425
|
const radioListOptions = [{
|
|
3081
3426
|
label: "Myself",
|
|
3082
3427
|
value: constants.TICKET_OWNER_MYSELF
|
|
@@ -3119,7 +3464,7 @@ const PersonalInfoComponent = ({
|
|
|
3119
3464
|
email: reservation.owner_email ? reservation.owner_email : personalInfo.email,
|
|
3120
3465
|
company: {
|
|
3121
3466
|
id: null,
|
|
3122
|
-
name: reservation.owner_company
|
|
3467
|
+
name: reservation.owner_company || personalInfo.company?.name || ''
|
|
3123
3468
|
}
|
|
3124
3469
|
});
|
|
3125
3470
|
}
|
|
@@ -3135,12 +3480,21 @@ const PersonalInfoComponent = ({
|
|
|
3135
3480
|
};
|
|
3136
3481
|
|
|
3137
3482
|
const onSubmit = data => {
|
|
3138
|
-
if (!personalInfo.company
|
|
3483
|
+
if (!personalInfo.company?.name && showCompanyInput) {
|
|
3139
3484
|
setCompanyError(true);
|
|
3140
3485
|
return;
|
|
3141
3486
|
}
|
|
3142
3487
|
|
|
3143
|
-
if (
|
|
3488
|
+
if (isNonTransferable) {
|
|
3489
|
+
// auto-assign to purchaser when ticket is non-transferable
|
|
3490
|
+
data = personal_information_objectSpread(personal_information_objectSpread({}, data), {}, {
|
|
3491
|
+
attendee: {
|
|
3492
|
+
firstName: data.firstName,
|
|
3493
|
+
lastName: data.lastName,
|
|
3494
|
+
email: data.email
|
|
3495
|
+
}
|
|
3496
|
+
});
|
|
3497
|
+
} else if (shouldDisplayTicketAssignment) {
|
|
3144
3498
|
if (!ticketOwnerOption) {
|
|
3145
3499
|
setTicketOwnerError(true);
|
|
3146
3500
|
return;
|
|
@@ -3237,7 +3591,7 @@ const PersonalInfoComponent = ({
|
|
|
3237
3591
|
className: personal_information_index_module.title
|
|
3238
3592
|
}, /*#__PURE__*/external_react_default().createElement("span", null, "Purchaser Information"), !isActive && /*#__PURE__*/external_react_default().createElement("div", {
|
|
3239
3593
|
"data-testid": "personal-info"
|
|
3240
|
-
}, /*#__PURE__*/external_react_default().createElement("span", null, `${personalInfo.firstName} ${personalInfo.lastName}${personalInfo.company
|
|
3594
|
+
}, /*#__PURE__*/external_react_default().createElement("span", null, `${personalInfo.firstName} ${personalInfo.lastName}${personalInfo.company?.name ? ` - ${personalInfo.company.name}` : ''}`), /*#__PURE__*/external_react_default().createElement("br", null), /*#__PURE__*/external_react_default().createElement("span", null, personalInfo.email))), /*#__PURE__*/external_react_default().createElement(external_react_spring_namespaceObject.animated.div, {
|
|
3241
3595
|
style: personal_information_objectSpread({
|
|
3242
3596
|
overflow: `${isActive ? '' : 'hidden'}`
|
|
3243
3597
|
}, toggleAnimation)
|
|
@@ -3332,7 +3686,7 @@ const PersonalInfoComponent = ({
|
|
|
3332
3686
|
}), companyError && /*#__PURE__*/external_react_default().createElement("div", {
|
|
3333
3687
|
className: personal_information_index_module.fieldError,
|
|
3334
3688
|
"data-testid": "company-error"
|
|
3335
|
-
}, "This field is required."))), shouldDisplayTicketAssignment
|
|
3689
|
+
}, "This field is required."))), shouldDisplayTicketAssignment && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3336
3690
|
className: personal_information_index_module.fieldWrapperRadio
|
|
3337
3691
|
}, /*#__PURE__*/external_react_default().createElement("label", null, "Ticket is for:"), /*#__PURE__*/external_react_default().createElement(components_namespaceObject.RadioList, {
|
|
3338
3692
|
id: `ticket-self-radio`,
|
|
@@ -3400,12 +3754,9 @@ const PersonalInfoComponent = ({
|
|
|
3400
3754
|
;// CONCATENATED MODULE: external "openstack-uicore-foundation/lib/components/raw-html"
|
|
3401
3755
|
const raw_html_namespaceObject = require("openstack-uicore-foundation/lib/components/raw-html");
|
|
3402
3756
|
var raw_html_default = /*#__PURE__*/__webpack_require__.n(raw_html_namespaceObject);
|
|
3403
|
-
;// CONCATENATED MODULE: external "i18n-react"
|
|
3404
|
-
const external_i18n_react_namespaceObject = require("i18n-react");
|
|
3405
|
-
var external_i18n_react_default = /*#__PURE__*/__webpack_require__.n(external_i18n_react_namespaceObject);
|
|
3406
3757
|
;// CONCATENATED MODULE: ./src/components/ticket-type/index.module.scss
|
|
3407
3758
|
// extracted by mini-css-extract-plugin
|
|
3408
|
-
/* harmony default export */ const ticket_type_index_module = ({"title":"title___DNZyl","summary":"summary___quWdZ","promoCode":"promoCode___bqTCw","crossOut":"crossOut___QZ7dy","discount":"discount___sEK_Q","
|
|
3759
|
+
/* harmony default export */ const ticket_type_index_module = ({"title":"title___DNZyl","summary":"summary___quWdZ","promoCode":"promoCode___bqTCw","crossOut":"crossOut___QZ7dy","discount":"discount___sEK_Q","taxes":"taxes___fe8oJ","promo":"promo___F8lPO","form":"form___aoo7w","dropdown":"dropdown____HWg0","quantity":"quantity___SIEQZ","soldOut":"soldOut___Hatfr","moreInfo":"moreInfo___LmwOe","moreInfoTooltip":"moreInfoTooltip___nOBf1","inPersonDisclaimer":"inPersonDisclaimer___PXGTz"});
|
|
3409
3760
|
;// CONCATENATED MODULE: external "lodash/isEqual"
|
|
3410
3761
|
const isEqual_namespaceObject = require("lodash/isEqual");
|
|
3411
3762
|
var isEqual_default = /*#__PURE__*/__webpack_require__.n(isEqual_namespaceObject);
|
|
@@ -3450,7 +3801,7 @@ const TicketDropdownComponent = ({
|
|
|
3450
3801
|
(0,external_react_.useEffect)(() => {
|
|
3451
3802
|
const prevTicketTypes = prevTicketTypesRef.current;
|
|
3452
3803
|
|
|
3453
|
-
if (!isEqual_default()(
|
|
3804
|
+
if (!isEqual_default()(prevTicketTypes, ticketTypes)) {
|
|
3454
3805
|
setCurrentTicketTypes(ticketTypes);
|
|
3455
3806
|
}
|
|
3456
3807
|
|
|
@@ -3493,12 +3844,9 @@ const TicketDropdownComponent = ({
|
|
|
3493
3844
|
;// CONCATENATED MODULE: external "react-tooltip"
|
|
3494
3845
|
const external_react_tooltip_namespaceObject = require("react-tooltip");
|
|
3495
3846
|
var external_react_tooltip_default = /*#__PURE__*/__webpack_require__.n(external_react_tooltip_namespaceObject);
|
|
3496
|
-
// EXTERNAL MODULE: ./src/assets/icon-check-circle.svg
|
|
3497
|
-
var icon_check_circle = __webpack_require__(60);
|
|
3498
|
-
var icon_check_circle_default = /*#__PURE__*/__webpack_require__.n(icon_check_circle);
|
|
3499
3847
|
;// CONCATENATED MODULE: ./src/components/promocode-input/index.module.scss
|
|
3500
3848
|
// extracted by mini-css-extract-plugin
|
|
3501
|
-
/* harmony default export */ const promocode_input_index_module = ({"promoCodeWrapper":"promoCodeWrapper___aw3Zx","promoCodeInput":"promoCodeInput___rDiET","promoCodeActive":"promoCodeActive___j7xnn","codeButtonWrapper":"codeButtonWrapper___jVZh5","noCode":"noCode___YUmVy","
|
|
3849
|
+
/* harmony default export */ const promocode_input_index_module = ({"promoCodeWrapper":"promoCodeWrapper___aw3Zx","promoCodeInput":"promoCodeInput___rDiET","promoCodeActive":"promoCodeActive___j7xnn","codeButtonWrapper":"codeButtonWrapper___jVZh5","noCode":"noCode___YUmVy","statusIcon":"statusIcon___l1uV0","valid":"valid___pDUq_","invalid":"invalid___UO9dX","spinner":"spinner___SKEJg","spin":"spin___wP5uK","moreInfo":"moreInfo___Ru3Rv","moreInfoTooltip":"moreInfoTooltip___eaYWm"});
|
|
3502
3850
|
;// CONCATENATED MODULE: ./src/components/promocode-input/index.js
|
|
3503
3851
|
/**
|
|
3504
3852
|
* Copyright 2020 OpenStack Foundation
|
|
@@ -3520,56 +3868,101 @@ var icon_check_circle_default = /*#__PURE__*/__webpack_require__.n(icon_check_ci
|
|
|
3520
3868
|
|
|
3521
3869
|
|
|
3522
3870
|
const PromoCodeInput = ({
|
|
3523
|
-
|
|
3871
|
+
promoStatus,
|
|
3524
3872
|
promoCode,
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3873
|
+
suggestedCode,
|
|
3874
|
+
isAutoApplied,
|
|
3875
|
+
onApply,
|
|
3876
|
+
onRemove,
|
|
3877
|
+
onInputChange,
|
|
3878
|
+
showMultipleTicketTexts
|
|
3528
3879
|
}) => {
|
|
3529
|
-
const [
|
|
3880
|
+
const [userTypedValue, setUserTypedValue] = (0,external_react_.useState)('');
|
|
3881
|
+
(0,external_react_.useEffect)(() => {
|
|
3882
|
+
if (!promoCode) setUserTypedValue('');
|
|
3883
|
+
}, [promoCode]); // Lock the input + show Remove (instead of Apply) whenever a code is in flight
|
|
3884
|
+
// or has settled (valid or invalid). The user must explicitly Remove to edit again.
|
|
3885
|
+
|
|
3886
|
+
const isLocked = promoStatus === constants.PROMO_STATUS.APPLYING || promoStatus === constants.PROMO_STATUS.VALIDATING || promoStatus === constants.PROMO_STATUS.VALID || promoStatus === constants.PROMO_STATUS.INVALID;
|
|
3887
|
+
const inputValue = (0,external_react_.useMemo)(() => {
|
|
3888
|
+
if (promoCode) return promoCode;
|
|
3889
|
+
if (promoStatus === constants.PROMO_STATUS.SUGGESTED) return suggestedCode || '';
|
|
3890
|
+
return userTypedValue;
|
|
3891
|
+
}, [promoCode, promoStatus, suggestedCode, userTypedValue]);
|
|
3892
|
+
const label = (0,external_react_.useMemo)(() => {
|
|
3893
|
+
switch (promoStatus) {
|
|
3894
|
+
case constants.PROMO_STATUS.VALID:
|
|
3895
|
+
if (isAutoApplied) return external_i18n_react_default().translate('promo_code.auto_applied_label');
|
|
3896
|
+
return external_i18n_react_default().translate('promo_code.applied_label');
|
|
3897
|
+
|
|
3898
|
+
case constants.PROMO_STATUS.APPLYING:
|
|
3899
|
+
case constants.PROMO_STATUS.VALIDATING:
|
|
3900
|
+
if (isAutoApplied) return external_i18n_react_default().translate('promo_code.auto_applied_label');
|
|
3901
|
+
return external_i18n_react_default().translate('promo_code.applying_label');
|
|
3902
|
+
|
|
3903
|
+
case constants.PROMO_STATUS.INVALID:
|
|
3904
|
+
return undefined;
|
|
3905
|
+
|
|
3906
|
+
case constants.PROMO_STATUS.SUGGESTED:
|
|
3907
|
+
return external_i18n_react_default().translate('promo_code.suggestion_label');
|
|
3908
|
+
|
|
3909
|
+
default:
|
|
3910
|
+
return undefined;
|
|
3911
|
+
}
|
|
3912
|
+
}, [promoStatus, isAutoApplied]);
|
|
3913
|
+
const canApply = !isLocked && !!inputValue;
|
|
3530
3914
|
|
|
3531
|
-
const
|
|
3532
|
-
|
|
3533
|
-
|
|
3915
|
+
const handleInputChange = value => {
|
|
3916
|
+
setUserTypedValue(value);
|
|
3917
|
+
onInputChange(value);
|
|
3534
3918
|
};
|
|
3535
3919
|
|
|
3536
|
-
(0,external_react_.useEffect)(() => {
|
|
3537
|
-
if ((0,utils/* isEmptyString */.ke)(promoCode)) handlePromoCodeChange(promoCode);
|
|
3538
|
-
}, [promoCode]);
|
|
3539
3920
|
return /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3540
3921
|
className: promocode_input_index_module.promoCodeWrapper
|
|
3541
|
-
}, /*#__PURE__*/external_react_default().createElement("span",
|
|
3922
|
+
}, /*#__PURE__*/external_react_default().createElement("span", {
|
|
3923
|
+
style: {
|
|
3924
|
+
display: 'flex',
|
|
3925
|
+
justifyContent: 'space-between',
|
|
3926
|
+
alignItems: 'center'
|
|
3927
|
+
}
|
|
3928
|
+
}, /*#__PURE__*/external_react_default().createElement("span", null, label || external_i18n_react_default().translate('promo_code.default_label')), showMultipleTicketTexts && /*#__PURE__*/external_react_default().createElement("a", {
|
|
3929
|
+
"data-tip": true,
|
|
3930
|
+
"data-for": "promo-code-info",
|
|
3931
|
+
className: promocode_input_index_module.moreInfo,
|
|
3932
|
+
style: {
|
|
3933
|
+
margin: 0
|
|
3934
|
+
}
|
|
3935
|
+
}, /*#__PURE__*/external_react_default().createElement("i", {
|
|
3936
|
+
className: "glyphicon glyphicon-info-sign",
|
|
3937
|
+
"aria-hidden": "true"
|
|
3938
|
+
}), ` `, "Have multiple promo codes?")), /*#__PURE__*/external_react_default().createElement("div", {
|
|
3542
3939
|
className: promocode_input_index_module.promoCodeInput
|
|
3543
3940
|
}, /*#__PURE__*/external_react_default().createElement("input", {
|
|
3544
|
-
className: `${
|
|
3941
|
+
className: `${isLocked ? promocode_input_index_module.promoCodeActive : ''}`,
|
|
3545
3942
|
type: "text",
|
|
3546
|
-
value:
|
|
3547
|
-
onChange: ev =>
|
|
3943
|
+
value: inputValue,
|
|
3944
|
+
onChange: ev => handleInputChange(ev.target.value),
|
|
3548
3945
|
placeholder: "Enter your promo code",
|
|
3549
3946
|
onKeyDown: e => {
|
|
3550
|
-
if (e.key === "Enter")
|
|
3947
|
+
if (e.key === "Enter" && canApply) onApply(inputValue);
|
|
3551
3948
|
},
|
|
3552
|
-
readOnly:
|
|
3553
|
-
}),
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3949
|
+
readOnly: isLocked
|
|
3950
|
+
}), (promoStatus === constants.PROMO_STATUS.VALIDATING || promoStatus === constants.PROMO_STATUS.APPLYING) && /*#__PURE__*/external_react_default().createElement("span", {
|
|
3951
|
+
className: `${promocode_input_index_module.statusIcon} ${promocode_input_index_module.spinner}`
|
|
3952
|
+
}), promoStatus === constants.PROMO_STATUS.VALID && /*#__PURE__*/external_react_default().createElement("span", {
|
|
3953
|
+
className: `${promocode_input_index_module.statusIcon} ${promocode_input_index_module.valid}`
|
|
3954
|
+
}, "\u2713"), promoStatus === constants.PROMO_STATUS.INVALID && /*#__PURE__*/external_react_default().createElement("span", {
|
|
3955
|
+
className: `${promocode_input_index_module.statusIcon} ${promocode_input_index_module.invalid}`
|
|
3956
|
+
}, "\u2715"), /*#__PURE__*/external_react_default().createElement("div", {
|
|
3957
|
+
className: `${promocode_input_index_module.codeButtonWrapper} ${inputValue ? '' : promocode_input_index_module.noCode}`
|
|
3958
|
+
}, isLocked ? /*#__PURE__*/external_react_default().createElement("button", {
|
|
3959
|
+
onClick: onRemove
|
|
3560
3960
|
}, "Remove") : /*#__PURE__*/external_react_default().createElement("button", {
|
|
3561
|
-
disabled: !
|
|
3562
|
-
onClick: () =>
|
|
3563
|
-
}, "Apply"))),
|
|
3564
|
-
className: promocode_input_index_module.moreInfo
|
|
3565
|
-
}, /*#__PURE__*/external_react_default().createElement("a", {
|
|
3566
|
-
"data-tip": true,
|
|
3567
|
-
"data-for": "promo-code-info"
|
|
3568
|
-
}, /*#__PURE__*/external_react_default().createElement("i", {
|
|
3569
|
-
className: "glyphicon glyphicon-info-sign",
|
|
3570
|
-
"aria-hidden": "true"
|
|
3571
|
-
}), ` `, "Have multiple promo codes?"))), /*#__PURE__*/external_react_default().createElement((external_react_tooltip_default()), {
|
|
3961
|
+
disabled: !canApply,
|
|
3962
|
+
onClick: () => onApply(inputValue)
|
|
3963
|
+
}, "Apply")))), /*#__PURE__*/external_react_default().createElement((external_react_tooltip_default()), {
|
|
3572
3964
|
id: "promo-code-info",
|
|
3965
|
+
place: "bottom",
|
|
3573
3966
|
overridePosition: utils/* avoidTooltipOverflow */.kb
|
|
3574
3967
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3575
3968
|
className: promocode_input_index_module.moreInfoTooltip
|
|
@@ -3577,6 +3970,32 @@ const PromoCodeInput = ({
|
|
|
3577
3970
|
};
|
|
3578
3971
|
|
|
3579
3972
|
/* harmony default export */ const promocode_input = (PromoCodeInput);
|
|
3973
|
+
;// CONCATENATED MODULE: ./src/components/ticket-notice/index.module.scss
|
|
3974
|
+
// extracted by mini-css-extract-plugin
|
|
3975
|
+
/* harmony default export */ const ticket_notice_index_module = ({"notice":"notice____Pa2z","error":"error___WzZms","info":"info___WFfzs","icon":"icon___YWZms"});
|
|
3976
|
+
;// CONCATENATED MODULE: ./src/components/ticket-notice/index.js
|
|
3977
|
+
|
|
3978
|
+
// `message` is either a single string or an array of strings. Arrays render
|
|
3979
|
+
// stacked consecutively inside the same notice box. Returns null when the
|
|
3980
|
+
// message is empty/unset so callers can pass conditional arrays without an
|
|
3981
|
+
// outer guard.
|
|
3982
|
+
|
|
3983
|
+
const TicketNotice = ({
|
|
3984
|
+
message,
|
|
3985
|
+
variant = 'info'
|
|
3986
|
+
}) => {
|
|
3987
|
+
const items = Array.isArray(message) ? message : message ? [message] : [];
|
|
3988
|
+
if (items.length === 0) return null;
|
|
3989
|
+
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
3990
|
+
className: `${ticket_notice_index_module.notice} ${ticket_notice_index_module[variant]}`
|
|
3991
|
+
}, variant === 'error' && /*#__PURE__*/external_react_default().createElement("span", {
|
|
3992
|
+
className: ticket_notice_index_module.icon
|
|
3993
|
+
}, "\u26A0"), items.map((m, i) => /*#__PURE__*/external_react_default().createElement("div", {
|
|
3994
|
+
key: i
|
|
3995
|
+
}, m)));
|
|
3996
|
+
};
|
|
3997
|
+
|
|
3998
|
+
/* harmony default export */ const ticket_notice = (TicketNotice);
|
|
3580
3999
|
;// CONCATENATED MODULE: ./src/components/ticket-type/index.js
|
|
3581
4000
|
function ticket_type_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
3582
4001
|
|
|
@@ -3611,6 +4030,7 @@ function ticket_type_defineProperty(obj, key, value) { if (key in obj) { Object.
|
|
|
3611
4030
|
|
|
3612
4031
|
|
|
3613
4032
|
|
|
4033
|
+
|
|
3614
4034
|
const TicketTypeComponent = ({
|
|
3615
4035
|
allowedTicketTypes,
|
|
3616
4036
|
originalTicketTypes,
|
|
@@ -3618,20 +4038,35 @@ const TicketTypeComponent = ({
|
|
|
3618
4038
|
taxTypes,
|
|
3619
4039
|
isActive,
|
|
3620
4040
|
changeForm,
|
|
3621
|
-
formErrors,
|
|
3622
4041
|
reservation,
|
|
3623
4042
|
inPersonDisclaimer,
|
|
3624
4043
|
showMultipleTicketTexts,
|
|
3625
4044
|
allowPromoCodes,
|
|
3626
|
-
|
|
3627
|
-
|
|
4045
|
+
promo = {},
|
|
4046
|
+
validationError,
|
|
3628
4047
|
promoCode,
|
|
3629
|
-
|
|
4048
|
+
promoCodeAllowsReassign = true,
|
|
4049
|
+
trackViewItem,
|
|
4050
|
+
noTicketsAvailableMessage
|
|
3630
4051
|
}) => {
|
|
4052
|
+
const {
|
|
4053
|
+
state: promoState = {},
|
|
4054
|
+
actions: promoActions = {}
|
|
4055
|
+
} = promo;
|
|
3631
4056
|
const [ticket, setTicket] = (0,external_react_.useState)(null);
|
|
3632
4057
|
const [quantity, setQuantity] = (0,external_react_.useState)(1);
|
|
3633
4058
|
const minQuantity = 1;
|
|
3634
|
-
const maxQuantity = (0,helpers/* getTicketMaxQuantity */.UE)(ticket);
|
|
4059
|
+
const maxQuantity = (0,helpers/* getTicketMaxQuantity */.UE)(ticket, promoState.maxQuantityFromPromo); // Clamp quantity when max changes (e.g. per-account limit kicks in after auto-apply).
|
|
4060
|
+
// If the cap drops below minQuantity (e.g. cap of 0), use the cap directly rather
|
|
4061
|
+
// than flooring at minQuantity, otherwise quantity would end up above the cap.
|
|
4062
|
+
|
|
4063
|
+
(0,external_react_.useEffect)(() => {
|
|
4064
|
+
if (!ticket) return;
|
|
4065
|
+
|
|
4066
|
+
if (quantity > maxQuantity) {
|
|
4067
|
+
setQuantity(maxQuantity < minQuantity ? 0 : maxQuantity);
|
|
4068
|
+
}
|
|
4069
|
+
}, [maxQuantity, quantity, ticket]);
|
|
3635
4070
|
const [ref, {
|
|
3636
4071
|
height
|
|
3637
4072
|
}] = (0,external_react_use_namespaceObject.useMeasure)();
|
|
@@ -3655,17 +4090,25 @@ const TicketTypeComponent = ({
|
|
|
3655
4090
|
}
|
|
3656
4091
|
}, []);
|
|
3657
4092
|
(0,external_react_.useEffect)(() => {
|
|
4093
|
+
const ticketSelectionValid = !!ticket && quantity >= minQuantity && quantity <= maxQuantity;
|
|
3658
4094
|
changeForm({
|
|
3659
4095
|
ticketType: ticket,
|
|
3660
|
-
ticketQuantity: quantity
|
|
4096
|
+
ticketQuantity: quantity,
|
|
4097
|
+
ticketSelectionValid
|
|
3661
4098
|
});
|
|
3662
|
-
}, [ticket, quantity]);
|
|
4099
|
+
}, [ticket, quantity, maxQuantity]);
|
|
3663
4100
|
(0,external_react_.useEffect)(() => {
|
|
3664
|
-
//
|
|
3665
|
-
//
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
4101
|
+
// When promo code changes, the API returns updated ticket types with/without discount.
|
|
4102
|
+
// Sync the selected ticket with the refreshed data.
|
|
4103
|
+
if (!ticket) {
|
|
4104
|
+
// Auto-select if only one ticket type available after promo code applied
|
|
4105
|
+
if (promoCode && originalTicketTypes.length === 1) {
|
|
4106
|
+
handleTicketChange(originalTicketTypes[0]);
|
|
4107
|
+
}
|
|
4108
|
+
|
|
4109
|
+
return;
|
|
4110
|
+
}
|
|
4111
|
+
|
|
3669
4112
|
const updatedCurrentTicket = originalTicketTypes.find(t => t?.id === ticket.id);
|
|
3670
4113
|
|
|
3671
4114
|
if (updatedCurrentTicket) {
|
|
@@ -3673,35 +4116,62 @@ const TicketTypeComponent = ({
|
|
|
3673
4116
|
ticketType: updatedCurrentTicket
|
|
3674
4117
|
});
|
|
3675
4118
|
setTicket(updatedCurrentTicket);
|
|
4119
|
+
} else {
|
|
4120
|
+
setTicket(null);
|
|
4121
|
+
setQuantity(minQuantity);
|
|
3676
4122
|
}
|
|
3677
|
-
|
|
3678
|
-
if (!promoCode) changeForm({
|
|
3679
|
-
promoCode: ''
|
|
3680
|
-
});
|
|
3681
4123
|
}, [promoCode, originalTicketTypes]);
|
|
3682
|
-
const
|
|
4124
|
+
const showTicketSelector = allowedTicketTypes.length > 0;
|
|
4125
|
+
const isPrePaidReservation = (0,external_react_.useMemo)(() => reservation ? (0,utils/* isPrePaidOrder */.xm)(reservation) : false, [reservation]); // check if reassignment is allowed by both promo code AND ticket type
|
|
4126
|
+
|
|
4127
|
+
const ticketTypeAllowsReassign = ticket?.allows_to_reassign !== false;
|
|
4128
|
+
const canReassign = promoCodeAllowsReassign && ticketTypeAllowsReassign; // Per-order cap is interesting only when it's tighter than what inventory
|
|
4129
|
+
// would otherwise allow (i.e. the binding constraint on the stepper).
|
|
4130
|
+
|
|
4131
|
+
const ticketPerOrderLimit = (0,external_react_.useMemo)(() => {
|
|
4132
|
+
if (!ticket) return null;
|
|
4133
|
+
const cap = ticket.max_quantity_per_order;
|
|
4134
|
+
const inventory = (ticket.quantity_2_sell ?? Number.MAX_SAFE_INTEGER) - (ticket.quantity_sold ?? 0);
|
|
4135
|
+
return cap != null && cap > 0 && cap < inventory ? cap : null;
|
|
4136
|
+
}, [ticket]); // Messages composed for the info notice (stacked in display order):
|
|
4137
|
+
// (1) promo per-account cap, (2) ticket-type per-order cap, (3) non-transferable.
|
|
4138
|
+
|
|
4139
|
+
const infoMessage = (0,external_react_.useMemo)(() => {
|
|
4140
|
+
if (!ticket) return [];
|
|
4141
|
+
const lines = [];
|
|
4142
|
+
|
|
4143
|
+
if (promoState.perAccountLimit != null) {
|
|
4144
|
+
lines.push(external_i18n_react_default().translate(promoState.perAccountLimit === 1 ? 'promo_code.per_account_limit_one' : 'promo_code.per_account_limit_other', {
|
|
4145
|
+
limit: promoState.perAccountLimit
|
|
4146
|
+
}));
|
|
4147
|
+
}
|
|
4148
|
+
|
|
4149
|
+
if (ticketPerOrderLimit != null) {
|
|
4150
|
+
lines.push(external_i18n_react_default().translate(ticketPerOrderLimit === 1 ? 'ticket_type.max_per_order_one' : 'ticket_type.max_per_order_other', {
|
|
4151
|
+
limit: ticketPerOrderLimit
|
|
4152
|
+
}));
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4155
|
+
if (!canReassign) {
|
|
4156
|
+
lines.push(external_i18n_react_default().translate('promo_code.non_transferable'));
|
|
4157
|
+
}
|
|
3683
4158
|
|
|
3684
|
-
|
|
4159
|
+
return lines;
|
|
4160
|
+
}, [ticket, promoState.perAccountLimit, ticketPerOrderLimit, canReassign]);
|
|
4161
|
+
|
|
4162
|
+
const handleTicketChange = async t => {
|
|
3685
4163
|
setTicket(t);
|
|
3686
4164
|
setQuantity(minQuantity);
|
|
3687
4165
|
trackViewItem(t);
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
const handlePromoCodeChange = code => {
|
|
3691
|
-
changeForm({
|
|
3692
|
-
promoCode: code
|
|
3693
|
-
});
|
|
4166
|
+
await promoActions.onTicketSelected(t);
|
|
3694
4167
|
};
|
|
3695
4168
|
|
|
3696
4169
|
const incrementQuantity = () => setQuantity(quantity + 1);
|
|
3697
4170
|
|
|
3698
4171
|
const decrementQuantity = () => setQuantity(quantity - 1);
|
|
3699
4172
|
|
|
3700
|
-
const
|
|
3701
|
-
|
|
3702
|
-
const handleRemovePromoCode = () => {
|
|
3703
|
-
setTicket(null);
|
|
3704
|
-
removePromoCode();
|
|
4173
|
+
const handleApplyPromoCode = async code => {
|
|
4174
|
+
await promoActions.onApply(code, ticket, quantity);
|
|
3705
4175
|
};
|
|
3706
4176
|
|
|
3707
4177
|
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
@@ -3710,9 +4180,26 @@ const TicketTypeComponent = ({
|
|
|
3710
4180
|
className: ticket_type_index_module.innerWrapper
|
|
3711
4181
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3712
4182
|
className: ticket_type_index_module.title
|
|
3713
|
-
}, /*#__PURE__*/external_react_default().createElement("span",
|
|
4183
|
+
}, /*#__PURE__*/external_react_default().createElement("span", {
|
|
4184
|
+
style: isActive ? {
|
|
4185
|
+
display: 'flex',
|
|
4186
|
+
justifyContent: 'space-between',
|
|
4187
|
+
alignItems: 'center',
|
|
4188
|
+
width: '100%'
|
|
4189
|
+
} : {}
|
|
4190
|
+
}, /*#__PURE__*/external_react_default().createElement("span", null, "Ticket"), isActive && showMultipleTicketTexts && /*#__PURE__*/external_react_default().createElement("a", {
|
|
4191
|
+
className: ticket_type_index_module.moreInfo,
|
|
4192
|
+
"data-tip": true,
|
|
4193
|
+
"data-for": "ticket-quantity-info",
|
|
4194
|
+
style: {
|
|
4195
|
+
margin: 0
|
|
4196
|
+
}
|
|
4197
|
+
}, /*#__PURE__*/external_react_default().createElement("i", {
|
|
4198
|
+
className: "glyphicon glyphicon-info-sign",
|
|
4199
|
+
"aria-hidden": "true"
|
|
4200
|
+
}), ` `, "Need multiple ticket types?")), /*#__PURE__*/external_react_default().createElement("div", {
|
|
3714
4201
|
className: ticket_type_index_module.summary
|
|
3715
|
-
}, /*#__PURE__*/external_react_default().createElement("span", null, ticket && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, `${ticket.name} (${quantity}): `, /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, (0,utils/* getTicketCost */.fX)(ticket, quantity)), `${(0,utils/* getTicketTaxes */.h5)(ticket, taxTypes)}`, !isActive && reservation?.discount_amount > 0 && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement("br", null), /*#__PURE__*/external_react_default().createElement("span", {
|
|
4202
|
+
}, /*#__PURE__*/external_react_default().createElement("span", null, !isActive && ticket && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, `${ticket.name} (${quantity}): `, /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, (0,utils/* getTicketCost */.fX)(ticket, quantity)), `${(0,utils/* getTicketTaxes */.h5)(ticket, taxTypes)}`, !isActive && reservation?.discount_amount > 0 && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement("br", null), /*#__PURE__*/external_react_default().createElement("span", {
|
|
3716
4203
|
className: ticket_type_index_module.promoCode
|
|
3717
4204
|
}, "Promo code\xA0", /*#__PURE__*/external_react_default().createElement("abbr", {
|
|
3718
4205
|
title: reservation.promo_code
|
|
@@ -3734,13 +4221,13 @@ const TicketTypeComponent = ({
|
|
|
3734
4221
|
})} ${ticket.currency}`), /*#__PURE__*/external_react_default().createElement("br", null));
|
|
3735
4222
|
})), !isActive && reservation && !isPrePaidReservation && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement("br", null), "Total: ", `${(0,helpers/* formatCurrency */.xG)(reservation.amount, {
|
|
3736
4223
|
currency: ticket.currency
|
|
3737
|
-
})} ${ticket.currency}`))
|
|
4224
|
+
})} ${ticket.currency}`))))), /*#__PURE__*/external_react_default().createElement(external_react_spring_namespaceObject.animated.div, {
|
|
3738
4225
|
style: ticket_type_objectSpread({
|
|
3739
4226
|
overflow: 'hidden'
|
|
3740
4227
|
}, toggleAnimation)
|
|
3741
4228
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3742
4229
|
ref: ref
|
|
3743
|
-
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
4230
|
+
}, showTicketSelector && /*#__PURE__*/external_react_default().createElement("div", {
|
|
3744
4231
|
className: ticket_type_index_module.form
|
|
3745
4232
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3746
4233
|
className: ticket_type_index_module.dropdown
|
|
@@ -3779,28 +4266,31 @@ const TicketTypeComponent = ({
|
|
|
3779
4266
|
disabled: maxQuantity === 0 || quantity >= maxQuantity
|
|
3780
4267
|
}, /*#__PURE__*/external_react_default().createElement("i", {
|
|
3781
4268
|
className: "fa fa-plus"
|
|
3782
|
-
}))))))),
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
removePromoCode: handleRemovePromoCode,
|
|
3787
|
-
onPromoCodeChange: handlePromoCodeChange
|
|
3788
|
-
}), promoCodeError && Object.values(promoCodeError).map((er, index) => /*#__PURE__*/external_react_default().createElement("div", {
|
|
3789
|
-
key: `error-${index}`,
|
|
3790
|
-
className: `${ticket_type_index_module.promocodeError} alert alert-danger`
|
|
3791
|
-
}, er))), showMultipleTicketTexts && /*#__PURE__*/external_react_default().createElement("a", {
|
|
3792
|
-
className: ticket_type_index_module.moreInfo,
|
|
3793
|
-
"data-tip": true,
|
|
3794
|
-
"data-for": "ticket-quantity-info"
|
|
3795
|
-
}, /*#__PURE__*/external_react_default().createElement("i", {
|
|
3796
|
-
className: "glyphicon glyphicon-info-sign",
|
|
3797
|
-
"aria-hidden": "true"
|
|
3798
|
-
}), ` `, "Need multiple ticket types?"), /*#__PURE__*/external_react_default().createElement((external_react_tooltip_default()), {
|
|
4269
|
+
}))))))), !showTicketSelector && /*#__PURE__*/external_react_default().createElement(ticket_notice, {
|
|
4270
|
+
message: noTicketsAvailableMessage || external_i18n_react_default().translate("ticket_type.no_tickets_available"),
|
|
4271
|
+
variant: "info"
|
|
4272
|
+
}), /*#__PURE__*/external_react_default().createElement((external_react_tooltip_default()), {
|
|
3799
4273
|
id: "ticket-quantity-info",
|
|
4274
|
+
place: "bottom",
|
|
3800
4275
|
overridePosition: utils/* avoidTooltipOverflow */.kb
|
|
3801
4276
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
3802
4277
|
className: ticket_type_index_module.moreInfoTooltip
|
|
3803
|
-
}, external_i18n_react_default().translate("ticket_type.ticket_quantity_tooltip")))
|
|
4278
|
+
}, external_i18n_react_default().translate("ticket_type.ticket_quantity_tooltip"))), allowPromoCodes && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, /*#__PURE__*/external_react_default().createElement(promocode_input, {
|
|
4279
|
+
promoStatus: promoState.status,
|
|
4280
|
+
promoCode: promoCode,
|
|
4281
|
+
suggestedCode: promoState.suggestedCode,
|
|
4282
|
+
isAutoApplied: promoState.isAutoApplied,
|
|
4283
|
+
onInputChange: promoActions.onInputChange,
|
|
4284
|
+
onApply: handleApplyPromoCode,
|
|
4285
|
+
onRemove: promoActions.onRemove,
|
|
4286
|
+
showMultipleTicketTexts: showMultipleTicketTexts
|
|
4287
|
+
})), /*#__PURE__*/external_react_default().createElement(ticket_notice, {
|
|
4288
|
+
message: validationError,
|
|
4289
|
+
variant: "error"
|
|
4290
|
+
}), /*#__PURE__*/external_react_default().createElement(ticket_notice, {
|
|
4291
|
+
message: infoMessage,
|
|
4292
|
+
variant: "info"
|
|
4293
|
+
}))), inPersonDisclaimer && ticket && (0,actions/* isInPersonTicketType */.Qc)(ticket) && /*#__PURE__*/external_react_default().createElement("div", {
|
|
3804
4294
|
className: ticket_type_index_module.inPersonDisclaimer
|
|
3805
4295
|
}, /*#__PURE__*/external_react_default().createElement((raw_html_default()), null, inPersonDisclaimer)))));
|
|
3806
4296
|
};
|
|
@@ -3836,16 +4326,16 @@ function button_bar_defineProperty(obj, key, value) { if (key in obj) { Object.d
|
|
|
3836
4326
|
const ButtonBarComponent = ({
|
|
3837
4327
|
step,
|
|
3838
4328
|
changeStep,
|
|
3839
|
-
|
|
3840
|
-
onValidateError,
|
|
4329
|
+
onNextStep,
|
|
3841
4330
|
formValues,
|
|
3842
4331
|
removeReservedTicket,
|
|
3843
|
-
inPersonDisclaimer
|
|
4332
|
+
inPersonDisclaimer,
|
|
4333
|
+
promoIsReady
|
|
3844
4334
|
}) => {
|
|
3845
4335
|
const {
|
|
3846
4336
|
ticketType,
|
|
3847
4337
|
ticketQuantity,
|
|
3848
|
-
|
|
4338
|
+
ticketSelectionValid
|
|
3849
4339
|
} = formValues || {};
|
|
3850
4340
|
const nextButtonText = inPersonDisclaimer && ticketType && (0,actions/* isInPersonTicketType */.Qc)(ticketType) ? 'Accept' : 'Next';
|
|
3851
4341
|
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
@@ -3863,12 +4353,11 @@ const ButtonBarComponent = ({
|
|
|
3863
4353
|
className: `${button_bar_index_module.button} button`,
|
|
3864
4354
|
onClick: () => removeReservedTicket()
|
|
3865
4355
|
}, "< Back"), step === constants.STEP_SELECT_TICKET_TYPE && /*#__PURE__*/external_react_default().createElement("button", {
|
|
3866
|
-
disabled: !
|
|
4356
|
+
disabled: !ticketSelectionValid || !promoIsReady,
|
|
3867
4357
|
className: `${button_bar_index_module.button} button`,
|
|
3868
|
-
onClick: () =>
|
|
3869
|
-
ticketQuantity
|
|
3870
|
-
|
|
3871
|
-
}), onValidateError)
|
|
4358
|
+
onClick: () => onNextStep(button_bar_objectSpread(button_bar_objectSpread({}, ticketType), {}, {
|
|
4359
|
+
ticketQuantity
|
|
4360
|
+
}))
|
|
3872
4361
|
}, nextButtonText), step === constants.STEP_PERSONAL_INFO && ticketType?.cost === 0 && /*#__PURE__*/external_react_default().createElement("button", {
|
|
3873
4362
|
className: `${button_bar_index_module.button} button`,
|
|
3874
4363
|
type: "submit",
|
|
@@ -4134,10 +4623,10 @@ const TicketOwnedComponent = ({
|
|
|
4134
4623
|
const NoAllowedTickets = ({
|
|
4135
4624
|
noAllowedTicketsMessage
|
|
4136
4625
|
}) => {
|
|
4137
|
-
return /*#__PURE__*/
|
|
4138
|
-
className:
|
|
4139
|
-
}, /*#__PURE__*/
|
|
4140
|
-
className: `${
|
|
4626
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
4627
|
+
className: styles.noAllowedWrapper
|
|
4628
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
4629
|
+
className: `${styles.alert} alert alert-warning`,
|
|
4141
4630
|
role: "alert",
|
|
4142
4631
|
dangerouslySetInnerHTML: {
|
|
4143
4632
|
__html: noAllowedTicketsMessage
|
|
@@ -4145,7 +4634,7 @@ const NoAllowedTickets = ({
|
|
|
4145
4634
|
}));
|
|
4146
4635
|
};
|
|
4147
4636
|
|
|
4148
|
-
/* harmony default export */ const no_allowed_tickets = (NoAllowedTickets);
|
|
4637
|
+
/* harmony default export */ const no_allowed_tickets = ((/* unused pure expression or super */ null && (NoAllowedTickets)));
|
|
4149
4638
|
;// CONCATENATED MODULE: ./src/components/ticket-taxes-error/index.module.scss
|
|
4150
4639
|
// extracted by mini-css-extract-plugin
|
|
4151
4640
|
/* harmony default export */ const ticket_taxes_error_index_module = ({"ticketTaxesErrorWrapper":"ticketTaxesErrorWrapper___ldztd","alert":"alert___AM17V"});
|
|
@@ -4185,7 +4674,7 @@ const TicketTaxesError = ({
|
|
|
4185
4674
|
|
|
4186
4675
|
/* harmony default export */ const ticket_taxes_error = (TicketTaxesError);
|
|
4187
4676
|
;// CONCATENATED MODULE: ./src/components/registration-form/index.js
|
|
4188
|
-
const registration_form_excluded = ["loadSession", "setMarketingSettings", "changeStep", "removeReservedTicket", "reserveTicket", "payTicketWithProvider", "trackEvent", "onPurchaseComplete", "getTicketTypesAndTaxes", "getLoginCode", "passwordlessLogin", "goToLogin", "loginOptions", "allowsNativeAuth", "allowsOtpAuth", "reservation", "checkout", "ticketTypes", "taxTypes", "step", "passwordlessCodeSent", "passwordlessEmail", "passwordlessCode", "passwordlessCodeLifeTime", "getPasswordlessCode", "passwordlessCodeError", "loginWithCode", "goToExtraQuestions", "goToMyOrders", "goToEvent", "profileData", "summitData", "supportEmail", "ticketOwned", "ownedTickets", "widgetLoading", "loading", "inPersonDisclaimer", "userProfile", "handleCompanyError", "providerOptions", "invitation", "loginInitialEmailInputValue", "getMyInvitation", "showMultipleTicketTexts", "noAllowedTicketsMessage", "ticketTaxesErrorMessage", "authErrorCallback", "clearWidgetState", "allowPromoCodes", "showCompanyInput", "companyDDLPlaceholder", "nowUtc", "updateClock", "completedExtraQuestions", "loadProfileData", "closeWidget", "hasVirtualAccessLevel", "hidePostalCode", "onError", "successfulPaymentReturnUrl", "idpLogoLight", "idpLogoDark", "idpLogoAlt", "showCompanyInputDefaultOptions", "companyDDLOptions2Show", "promoCode", "hasDiscount", "getTicketDiscount", "removePromoCode", "applyPromoCode", "validatePromoCode", "closeHandlerRef"];
|
|
4677
|
+
const registration_form_excluded = ["loadSession", "setMarketingSettings", "changeStep", "removeReservedTicket", "reserveTicket", "payTicketWithProvider", "trackEvent", "onPurchaseComplete", "getTicketTypesAndTaxes", "getLoginCode", "passwordlessLogin", "goToLogin", "loginOptions", "allowsNativeAuth", "allowsOtpAuth", "reservation", "checkout", "ticketTypes", "taxTypes", "step", "passwordlessCodeSent", "passwordlessEmail", "passwordlessCode", "passwordlessCodeLifeTime", "getPasswordlessCode", "passwordlessCodeError", "loginWithCode", "goToExtraQuestions", "goToMyOrders", "goToEvent", "profileData", "summitData", "supportEmail", "ticketOwned", "ownedTickets", "widgetLoading", "loading", "inPersonDisclaimer", "userProfile", "handleCompanyError", "providerOptions", "invitation", "loginInitialEmailInputValue", "getMyInvitation", "showMultipleTicketTexts", "noAllowedTicketsMessage", "noTicketsAvailableMessage", "ticketTaxesErrorMessage", "authErrorCallback", "clearWidgetState", "allowPromoCodes", "showCompanyInput", "companyDDLPlaceholder", "nowUtc", "updateClock", "completedExtraQuestions", "loadProfileData", "closeWidget", "hasVirtualAccessLevel", "hidePostalCode", "onError", "successfulPaymentReturnUrl", "idpLogoLight", "idpLogoDark", "idpLogoAlt", "showCompanyInputDefaultOptions", "companyDDLOptions2Show", "promoCode", "promoCodeVerified", "promoCodeValidating", "promoCodeAllowsReassign", "discoveredPromoCodes", "hasDiscount", "getTicketDiscount", "removePromoCode", "applyPromoCode", "validatePromoCode", "discoverPromoCodes", "startWidgetLoading", "stopWidgetLoading", "closeHandlerRef"];
|
|
4189
4678
|
|
|
4190
4679
|
function registration_form_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
4191
4680
|
|
|
@@ -4234,6 +4723,7 @@ function registration_form_objectWithoutPropertiesLoose(source, excluded) { if (
|
|
|
4234
4723
|
|
|
4235
4724
|
|
|
4236
4725
|
|
|
4726
|
+
|
|
4237
4727
|
|
|
4238
4728
|
|
|
4239
4729
|
let language = (0,utils/* getCurrentUserLanguage */.AS)();
|
|
@@ -4297,6 +4787,7 @@ const RegistrationFormContent = _ref => {
|
|
|
4297
4787
|
getMyInvitation,
|
|
4298
4788
|
showMultipleTicketTexts,
|
|
4299
4789
|
noAllowedTicketsMessage,
|
|
4790
|
+
noTicketsAvailableMessage,
|
|
4300
4791
|
ticketTaxesErrorMessage,
|
|
4301
4792
|
authErrorCallback,
|
|
4302
4793
|
clearWidgetState,
|
|
@@ -4318,11 +4809,18 @@ const RegistrationFormContent = _ref => {
|
|
|
4318
4809
|
showCompanyInputDefaultOptions,
|
|
4319
4810
|
companyDDLOptions2Show,
|
|
4320
4811
|
promoCode,
|
|
4812
|
+
promoCodeVerified,
|
|
4813
|
+
promoCodeValidating,
|
|
4814
|
+
promoCodeAllowsReassign,
|
|
4815
|
+
discoveredPromoCodes,
|
|
4321
4816
|
hasDiscount,
|
|
4322
4817
|
getTicketDiscount,
|
|
4323
4818
|
removePromoCode,
|
|
4324
4819
|
applyPromoCode,
|
|
4325
4820
|
validatePromoCode,
|
|
4821
|
+
discoverPromoCodes,
|
|
4822
|
+
startWidgetLoading,
|
|
4823
|
+
stopWidgetLoading,
|
|
4326
4824
|
closeHandlerRef
|
|
4327
4825
|
} = _ref,
|
|
4328
4826
|
rest = registration_form_objectWithoutProperties(_ref, registration_form_excluded);
|
|
@@ -4339,19 +4837,17 @@ const RegistrationFormContent = _ref => {
|
|
|
4339
4837
|
});
|
|
4340
4838
|
const [ticketDataError, setTicketDataError] = (0,external_react_.useState)(false);
|
|
4341
4839
|
const [ticketDataLoaded, setTicketDataLoaded] = (0,external_react_.useState)(false);
|
|
4840
|
+
const [unappliedCodeWarning, setUnappliedCodeWarning] = (0,external_react_.useState)(null);
|
|
4342
4841
|
const {
|
|
4343
4842
|
values: formValues,
|
|
4344
4843
|
errors: formErrors
|
|
4345
4844
|
} = registrationForm;
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
})
|
|
4350
|
-
|
|
4351
|
-
const setFormErrors = errors => setRegistrationForm(registration_form_objectSpread(registration_form_objectSpread({}, registrationForm), {}, {
|
|
4845
|
+
const mergeFormValues = (0,external_react_.useCallback)(partial => setRegistrationForm(prev => registration_form_objectSpread(registration_form_objectSpread({}, prev), {}, {
|
|
4846
|
+
values: registration_form_objectSpread(registration_form_objectSpread({}, prev.values), partial)
|
|
4847
|
+
})), []);
|
|
4848
|
+
const setFormErrors = (0,external_react_.useCallback)(errors => setRegistrationForm(prev => registration_form_objectSpread(registration_form_objectSpread({}, prev), {}, {
|
|
4352
4849
|
errors
|
|
4353
|
-
}));
|
|
4354
|
-
|
|
4850
|
+
})), []);
|
|
4355
4851
|
const {
|
|
4356
4852
|
publicKey,
|
|
4357
4853
|
provider
|
|
@@ -4386,7 +4882,43 @@ const RegistrationFormContent = _ref => {
|
|
|
4386
4882
|
}, [registrationForm.values, step]);
|
|
4387
4883
|
(0,external_react_.useEffect)(() => {
|
|
4388
4884
|
setFormErrors([]);
|
|
4389
|
-
}, [step]);
|
|
4885
|
+
}, [step]); // Discovery: fetch qualifying promo codes after auth
|
|
4886
|
+
|
|
4887
|
+
(0,external_react_.useEffect)(() => {
|
|
4888
|
+
if (profileData && summitData?.id) {
|
|
4889
|
+
discoverPromoCodes(summitData.id);
|
|
4890
|
+
}
|
|
4891
|
+
}, [profileData, summitData?.id]);
|
|
4892
|
+
const handleFormPromoCodeChange = (0,external_react_.useCallback)(code => mergeFormValues({
|
|
4893
|
+
promoCode: code
|
|
4894
|
+
}), [mergeFormValues]);
|
|
4895
|
+
const promo = hooks_usePromoCode({
|
|
4896
|
+
discoveredPromoCodes,
|
|
4897
|
+
promoCode,
|
|
4898
|
+
promoCodeVerified,
|
|
4899
|
+
promoCodeValidating,
|
|
4900
|
+
applyPromoCode,
|
|
4901
|
+
removePromoCode,
|
|
4902
|
+
validatePromoCode,
|
|
4903
|
+
setFormPromoCode: handleFormPromoCodeChange,
|
|
4904
|
+
ticketDataLoaded: ticketDataLoaded && !ticketDataError,
|
|
4905
|
+
hasTickets: allowedTicketTypes.length > 0
|
|
4906
|
+
}); // Local destructure for readability at call sites.
|
|
4907
|
+
|
|
4908
|
+
const {
|
|
4909
|
+
state: promoState,
|
|
4910
|
+
actions: promoActions
|
|
4911
|
+
} = promo; // Error rendered in the promo notice slot — form-level warning layered on top
|
|
4912
|
+
// of the hook's own validation error (API rejection or status-derived).
|
|
4913
|
+
|
|
4914
|
+
const ticketStepError = unappliedCodeWarning ?? promoState.validationError; // Clear the unapplied-code warning once the condition that would have raised it
|
|
4915
|
+
// no longer holds (input cleared, code applied, or a suggestion is showing).
|
|
4916
|
+
|
|
4917
|
+
(0,external_react_.useEffect)(() => {
|
|
4918
|
+
if (!formValues?.promoCode || promoCode || promoState.status === constants.PROMO_STATUS.SUGGESTED) {
|
|
4919
|
+
setUnappliedCodeWarning(null);
|
|
4920
|
+
}
|
|
4921
|
+
}, [formValues?.promoCode, promoCode, promoState.status]);
|
|
4390
4922
|
const [ref, {
|
|
4391
4923
|
height
|
|
4392
4924
|
}] = (0,external_react_use_namespaceObject.useMeasure)();
|
|
@@ -4445,12 +4977,28 @@ const RegistrationFormContent = _ref => {
|
|
|
4445
4977
|
});
|
|
4446
4978
|
};
|
|
4447
4979
|
|
|
4448
|
-
const
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4980
|
+
const handleAdvanceFromTicketStep = async data => {
|
|
4981
|
+
if (formValues?.promoCode && !promoCode && promoState.status !== constants.PROMO_STATUS.SUGGESTED) {
|
|
4982
|
+
setUnappliedCodeWarning(external_i18n_react_default().translate('promo_code.unapplied_code_warning'));
|
|
4983
|
+
return;
|
|
4984
|
+
} // Re-validate manual codes with final quantity before advancing
|
|
4985
|
+
|
|
4986
|
+
|
|
4987
|
+
if (promoCode && !promoState.isDiscoveredCode) {
|
|
4988
|
+
startWidgetLoading();
|
|
4989
|
+
let valid = false;
|
|
4990
|
+
|
|
4991
|
+
try {
|
|
4992
|
+
valid = await promoActions.onRevalidate(formValues.ticketType, data.ticketQuantity);
|
|
4993
|
+
} finally {
|
|
4994
|
+
stopWidgetLoading();
|
|
4995
|
+
}
|
|
4996
|
+
|
|
4997
|
+
if (!valid) return;
|
|
4998
|
+
}
|
|
4999
|
+
|
|
5000
|
+
trackAddToCart(data);
|
|
5001
|
+
changeStep(constants.STEP_PERSONAL_INFO);
|
|
4454
5002
|
};
|
|
4455
5003
|
|
|
4456
5004
|
const trackViewItem = data => {
|
|
@@ -4492,8 +5040,6 @@ const RegistrationFormContent = _ref => {
|
|
|
4492
5040
|
}), profileData && ticketDataError && /*#__PURE__*/external_react_default().createElement(ticket_taxes_error, {
|
|
4493
5041
|
ticketTaxesErrorMessage: ticketTaxesErrorMessage,
|
|
4494
5042
|
retryTicketTaxes: () => handleGetTicketTypesAndTaxes(summitData?.id)
|
|
4495
|
-
}), noAvailableTickets && /*#__PURE__*/external_react_default().createElement(no_allowed_tickets, {
|
|
4496
|
-
noAllowedTicketsMessage: noAllowedTicketsMessage
|
|
4497
5043
|
}), !ticketDataError && /*#__PURE__*/external_react_default().createElement((external_react_default()).Fragment, null, !profileData && !passwordlessCodeSent && /*#__PURE__*/external_react_default().createElement(login["default"], {
|
|
4498
5044
|
summitData: summitData,
|
|
4499
5045
|
loginOptions: loginOptions,
|
|
@@ -4526,19 +5072,14 @@ const RegistrationFormContent = _ref => {
|
|
|
4526
5072
|
reservation: reservation,
|
|
4527
5073
|
isActive: step === constants.STEP_SELECT_TICKET_TYPE,
|
|
4528
5074
|
allowPromoCodes: allowPromoCodes,
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
setFormErrors({});
|
|
4532
|
-
setFormValues(registration_form_objectSpread(registration_form_objectSpread({}, formValues), {}, {
|
|
4533
|
-
promoCode: ""
|
|
4534
|
-
}));
|
|
4535
|
-
removePromoCode();
|
|
4536
|
-
},
|
|
5075
|
+
promo: promo,
|
|
5076
|
+
validationError: ticketStepError,
|
|
4537
5077
|
promoCode: promoCode,
|
|
4538
|
-
|
|
4539
|
-
changeForm:
|
|
5078
|
+
promoCodeAllowsReassign: promoCodeAllowsReassign,
|
|
5079
|
+
changeForm: mergeFormValues,
|
|
4540
5080
|
trackViewItem: trackViewItem,
|
|
4541
|
-
showMultipleTicketTexts: showMultipleTicketTexts
|
|
5081
|
+
showMultipleTicketTexts: showMultipleTicketTexts,
|
|
5082
|
+
noTicketsAvailableMessage: noTicketsAvailableMessage
|
|
4542
5083
|
}), /*#__PURE__*/external_react_default().createElement(personal_information, {
|
|
4543
5084
|
isActive: step === constants.STEP_PERSONAL_INFO,
|
|
4544
5085
|
reservation: reservation,
|
|
@@ -4546,9 +5087,9 @@ const RegistrationFormContent = _ref => {
|
|
|
4546
5087
|
invitation: invitation,
|
|
4547
5088
|
summitId: summitData.id,
|
|
4548
5089
|
changeForm: personalInformation => {
|
|
4549
|
-
|
|
5090
|
+
mergeFormValues({
|
|
4550
5091
|
personalInformation
|
|
4551
|
-
})
|
|
5092
|
+
});
|
|
4552
5093
|
reserveTicket({
|
|
4553
5094
|
provider,
|
|
4554
5095
|
personalInformation: personalInformation,
|
|
@@ -4576,7 +5117,8 @@ const RegistrationFormContent = _ref => {
|
|
|
4576
5117
|
showCompanyInput: showCompanyInput,
|
|
4577
5118
|
companyDDLPlaceholder: companyDDLPlaceholder,
|
|
4578
5119
|
showCompanyInputDefaultOptions: showCompanyInputDefaultOptions,
|
|
4579
|
-
companyDDLOptions2Show: companyDDLOptions2Show
|
|
5120
|
+
companyDDLOptions2Show: companyDDLOptions2Show,
|
|
5121
|
+
promoCodeAllowsReassign: promoCodeAllowsReassign
|
|
4580
5122
|
}), /*#__PURE__*/external_react_default().createElement(external_react_spring_namespaceObject.animated.div, {
|
|
4581
5123
|
style: registration_form_objectSpread({}, toggleAnimation)
|
|
4582
5124
|
}, /*#__PURE__*/external_react_default().createElement("div", {
|
|
@@ -4597,11 +5139,9 @@ const RegistrationFormContent = _ref => {
|
|
|
4597
5139
|
step: step,
|
|
4598
5140
|
inPersonDisclaimer: inPersonDisclaimer,
|
|
4599
5141
|
formValues: formValues,
|
|
5142
|
+
promoIsReady: promoState.isReady,
|
|
4600
5143
|
removeReservedTicket: removeReservedTicket,
|
|
4601
|
-
|
|
4602
|
-
onValidateError: {
|
|
4603
|
-
onError: (err, res) => setFormErrors(res.body.errors)
|
|
4604
|
-
},
|
|
5144
|
+
onNextStep: handleAdvanceFromTicketStep,
|
|
4605
5145
|
changeStep: changeStep
|
|
4606
5146
|
})), profileData && step === constants.STEP_COMPLETE && /*#__PURE__*/external_react_default().createElement(purchase_complete, {
|
|
4607
5147
|
checkout: checkout,
|
|
@@ -4644,7 +5184,11 @@ const mapStateToProps = ({
|
|
|
4644
5184
|
passwordlessCodeSent: registrationLiteState.passwordless.code_sent,
|
|
4645
5185
|
passwordlessCodeError: registrationLiteState.passwordless.error,
|
|
4646
5186
|
nowUtc: registrationLiteState.nowUtc,
|
|
4647
|
-
promoCode: registrationLiteState.promoCode
|
|
5187
|
+
promoCode: registrationLiteState.promoCode,
|
|
5188
|
+
promoCodeVerified: registrationLiteState.promoCodeVerified,
|
|
5189
|
+
promoCodeValidating: registrationLiteState.promoCodeValidating,
|
|
5190
|
+
promoCodeAllowsReassign: registrationLiteState.promoCodeAllowsReassign,
|
|
5191
|
+
discoveredPromoCodes: registrationLiteState.discoveredPromoCodes
|
|
4648
5192
|
});
|
|
4649
5193
|
|
|
4650
5194
|
const RegistrationForm = (0,external_react_redux_.connect)(mapStateToProps, {
|
|
@@ -4663,7 +5207,10 @@ const RegistrationForm = (0,external_react_redux_.connect)(mapStateToProps, {
|
|
|
4663
5207
|
loadProfileData: actions/* loadProfileData */.Bi,
|
|
4664
5208
|
applyPromoCode: actions/* applyPromoCode */.gs,
|
|
4665
5209
|
removePromoCode: actions/* removePromoCode */.$r,
|
|
4666
|
-
validatePromoCode: actions/* validatePromoCode */.jn
|
|
5210
|
+
validatePromoCode: actions/* validatePromoCode */.jn,
|
|
5211
|
+
discoverPromoCodes: actions/* discoverPromoCodes */.kM,
|
|
5212
|
+
startWidgetLoading: actions/* startWidgetLoading */.Bq,
|
|
5213
|
+
stopWidgetLoading: actions/* stopWidgetLoading */.Rs
|
|
4667
5214
|
})(RegistrationFormContent);
|
|
4668
5215
|
RegistrationForm.defaultProps = {
|
|
4669
5216
|
loginInitialEmailInputValue: '',
|