summit-registration-lite 7.0.6 → 7.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.js +85 -32
- package/dist/components/index.js.map +1 -1
- package/dist/components/registration-form.js +85 -32
- package/dist/components/registration-form.js.map +1 -1
- package/dist/components/registration-modal.js +85 -32
- package/dist/components/registration-modal.js.map +1 -1
- package/dist/index.js +85 -32
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/.claude/rules/summit-registration-lite-component-props.md +0 -95
- package/.claude/rules/summit-registration-lite-i18n.md +0 -62
- package/.claude/rules/summit-registration-lite-payment-providers.md +0 -69
- package/.claude/rules/summit-registration-lite-project.md +0 -80
- package/.claude/rules/summit-registration-lite-redux-actions.md +0 -65
- package/.claude/rules/summit-registration-lite-step-flow.md +0 -77
- package/.claude/rules/summit-registration-lite-testing.md +0 -97
- package/.claude/rules/summit-registration-lite-utils.md +0 -71
- package/.claude/skills/summit-registration-lite-add-provider/SKILL.md +0 -155
- package/.claude/skills/summit-registration-lite-dev-setup/SKILL.md +0 -67
- package/.claude/skills/summit-registration-lite-publish/SKILL.md +0 -64
- package/.claude/skills/summit-registration-lite-scaffold-component/SKILL.md +0 -152
- package/.codegraph/config.json +0 -141
- package/.codegraph/daemon.pid +0 -6
|
@@ -1487,10 +1487,12 @@ const usePromoCode = ({
|
|
|
1487
1487
|
//
|
|
1488
1488
|
// Note on concurrency: the two call sites (early-auto-apply effect and
|
|
1489
1489
|
// onTicketSelected's auto-apply branch) operate on disjoint states by design
|
|
1490
|
-
// (the effect requires `!
|
|
1491
|
-
//
|
|
1492
|
-
//
|
|
1493
|
-
//
|
|
1490
|
+
// (the effect requires `!isApplied`, the branch fires only on a user-driven
|
|
1491
|
+
// ticket selection — by which point isApplied is already true if early
|
|
1492
|
+
// auto-apply ran), so a true concurrent invocation is unreachable in
|
|
1493
|
+
// practice. If a future change makes that overlap possible, gate this body
|
|
1494
|
+
// with a ref-tracked in-flight flag rather than `applyingCode` (which is
|
|
1495
|
+
// captured stale here).
|
|
1494
1496
|
|
|
1495
1497
|
const tryAutoApply = (0,external_react_.useCallback)(async ticket => {
|
|
1496
1498
|
setIsAutoApplied(true);
|
|
@@ -1518,8 +1520,14 @@ const usePromoCode = ({
|
|
|
1518
1520
|
}
|
|
1519
1521
|
}, [discoveredPromoCode, applyPromoCode, onRevalidate, handleValidationError]);
|
|
1520
1522
|
const onTicketSelected = (0,external_react_.useCallback)(async ticket => {
|
|
1521
|
-
const qualifies = discoveredPromoCode && isCodeValidForTicket(ticket);
|
|
1522
|
-
|
|
1523
|
+
const qualifies = discoveredPromoCode && isCodeValidForTicket(ticket); // Only turn the suggestion on when the current ticket qualifies; don't
|
|
1524
|
+
// turn it off otherwise. With auto-switch-on-Apply, the suggestion is
|
|
1525
|
+
// still useful when the user has a non-qualifying ticket selected
|
|
1526
|
+
// (Apply will switch them to the qualifying one). The status logic
|
|
1527
|
+
// hides the banner whenever a code is applied, so leaving this true
|
|
1528
|
+
// doesn't surface a stale suggestion.
|
|
1529
|
+
|
|
1530
|
+
if (qualifies) setSuggestionActive(true);
|
|
1523
1531
|
setSuggestionDismissed(false);
|
|
1524
1532
|
setManualError(null); // Manual (non-discovered) code is applied: re-validate for new ticket
|
|
1525
1533
|
|
|
@@ -1528,17 +1536,15 @@ const usePromoCode = ({
|
|
|
1528
1536
|
return;
|
|
1529
1537
|
}
|
|
1530
1538
|
|
|
1531
|
-
if (!discoveredPromoCode) return; // Discovered code is currently applied
|
|
1539
|
+
if (!discoveredPromoCode) return; // Discovered code is currently applied — re-validate against the new
|
|
1540
|
+
// ticket. The backend rejects if the code doesn't apply, surfacing
|
|
1541
|
+
// INVALID to the user (they can then choose to Remove or pick another
|
|
1542
|
+
// ticket). Previously we silently removed the code on a non-qualifying
|
|
1543
|
+
// pick, which hid the rejection.
|
|
1532
1544
|
|
|
1533
1545
|
if (isDiscoveredCode) {
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
removePromoCode();
|
|
1537
|
-
} else {
|
|
1538
|
-
const valid = await onRevalidate(ticket, 1);
|
|
1539
|
-
if (!valid) setIsAutoApplied(false);
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1546
|
+
const valid = await onRevalidate(ticket, 1);
|
|
1547
|
+
if (!valid) setIsAutoApplied(false);
|
|
1542
1548
|
return;
|
|
1543
1549
|
} // No code applied, ticket qualifies, auto-apply configured, single code only
|
|
1544
1550
|
|
|
@@ -1546,19 +1552,20 @@ const usePromoCode = ({
|
|
|
1546
1552
|
if (!isApplied && qualifies && discoveredPromoCode.auto_apply && !userRemovedAutoApply && discoveredPromoCodes.length === 1) {
|
|
1547
1553
|
await tryAutoApply(ticket);
|
|
1548
1554
|
}
|
|
1549
|
-
}, [discoveredPromoCode, isApplied, isDiscoveredCode, userRemovedAutoApply, discoveredPromoCodes, isCodeValidForTicket,
|
|
1550
|
-
//
|
|
1551
|
-
//
|
|
1555
|
+
}, [discoveredPromoCode, isApplied, isDiscoveredCode, userRemovedAutoApply, discoveredPromoCodes, isCodeValidForTicket, onRevalidate, tryAutoApply]); // Early auto-apply on load (per SDS: silently apply a discovered single
|
|
1556
|
+
// auto_apply code when no code is currently applied). Wait on
|
|
1557
|
+
// ticketDataLoaded only to avoid racing the initial fetch. On failure,
|
|
1558
|
+
// mark as removed to prevent re-fire loops.
|
|
1552
1559
|
|
|
1553
1560
|
(0,external_react_.useEffect)(() => {
|
|
1554
1561
|
if (userRemovedAutoApply || isApplied) return;
|
|
1555
|
-
if (!ticketDataLoaded
|
|
1562
|
+
if (!ticketDataLoaded) return;
|
|
1556
1563
|
if (!discoveredPromoCode?.auto_apply) return;
|
|
1557
1564
|
if (discoveredPromoCodes.length !== 1) return;
|
|
1558
1565
|
tryAutoApply(null).then(success => {
|
|
1559
1566
|
if (!success) setUserRemovedAutoApply(true);
|
|
1560
1567
|
});
|
|
1561
|
-
}, [userRemovedAutoApply, ticketDataLoaded,
|
|
1568
|
+
}, [userRemovedAutoApply, ticketDataLoaded, discoveredPromoCode, discoveredPromoCodes, isApplied, tryAutoApply]);
|
|
1562
1569
|
const onApply = (0,external_react_.useCallback)(async (code, ticket, quantity) => {
|
|
1563
1570
|
setManualError(null);
|
|
1564
1571
|
setApplyingCode(true);
|
|
@@ -1597,11 +1604,20 @@ const usePromoCode = ({
|
|
|
1597
1604
|
status,
|
|
1598
1605
|
isReady,
|
|
1599
1606
|
validationError,
|
|
1607
|
+
// True while applyPromoCode is in flight (covers the window where
|
|
1608
|
+
// promoCode is set but the refreshed ticketTypes haven't landed
|
|
1609
|
+
// yet). Callers should defer ticket-list-driven side effects
|
|
1610
|
+
// until this clears to avoid acting on a stale list.
|
|
1611
|
+
applyingCode,
|
|
1600
1612
|
// Applied code origin
|
|
1601
1613
|
isDiscoveredCode,
|
|
1602
1614
|
isAutoApplied,
|
|
1603
1615
|
// Discovery / suggestion
|
|
1604
1616
|
suggestedCode,
|
|
1617
|
+
// Predicate the caller can use to find a ticket the discovered
|
|
1618
|
+
// promo applies to (auto-selection after auto-apply, ticket
|
|
1619
|
+
// switching on Apply).
|
|
1620
|
+
isCodeValidForTicket,
|
|
1605
1621
|
// Quantity caps from the active discovered code
|
|
1606
1622
|
maxQuantityFromPromo,
|
|
1607
1623
|
perAccountLimit
|
|
@@ -2892,6 +2908,7 @@ const PromoCodeInput = ({
|
|
|
2892
2908
|
promoCode,
|
|
2893
2909
|
suggestedCode,
|
|
2894
2910
|
isAutoApplied,
|
|
2911
|
+
isCurrentTicketQualifying,
|
|
2895
2912
|
onApply,
|
|
2896
2913
|
onRemove,
|
|
2897
2914
|
onInputChange,
|
|
@@ -2924,12 +2941,16 @@ const PromoCodeInput = ({
|
|
|
2924
2941
|
return undefined;
|
|
2925
2942
|
|
|
2926
2943
|
case constants.PROMO_STATUS.SUGGESTED:
|
|
2927
|
-
|
|
2944
|
+
// The suggestion banner stays visible across non-qualifying ticket
|
|
2945
|
+
// picks (so the "Apply will switch you" affordance persists). Swap
|
|
2946
|
+
// the copy so it stays accurate: tell the user the code applies to
|
|
2947
|
+
// a different ticket and that Apply will switch them.
|
|
2948
|
+
return isCurrentTicketQualifying ? external_i18n_react_default().translate('promo_code.suggestion_label') : external_i18n_react_default().translate('promo_code.suggestion_label_switch');
|
|
2928
2949
|
|
|
2929
2950
|
default:
|
|
2930
2951
|
return undefined;
|
|
2931
2952
|
}
|
|
2932
|
-
}, [promoStatus, isAutoApplied]);
|
|
2953
|
+
}, [promoStatus, isAutoApplied, isCurrentTicketQualifying]);
|
|
2933
2954
|
const canApply = !isLocked && !!inputValue;
|
|
2934
2955
|
|
|
2935
2956
|
const handleInputChange = value => {
|
|
@@ -3130,9 +3151,19 @@ const TicketTypeComponent = ({
|
|
|
3130
3151
|
// When promo code changes, the API returns updated ticket types with/without discount.
|
|
3131
3152
|
// Sync the selected ticket with the refreshed data.
|
|
3132
3153
|
if (!ticket) {
|
|
3133
|
-
// Auto-select
|
|
3134
|
-
|
|
3135
|
-
|
|
3154
|
+
// Auto-select after a promo code is applied. Defer while applyingCode is
|
|
3155
|
+
// true: the reducer sets promoCode synchronously before the refreshed
|
|
3156
|
+
// ticketTypes land, so acting now would auto-select from a stale list.
|
|
3157
|
+
// Once apply settles, prefer the first ticket the discovered code applies
|
|
3158
|
+
// to (so per-ticket validation succeeds); fall back to the only ticket
|
|
3159
|
+
// when there's a single option.
|
|
3160
|
+
// Scan allowedTicketTypes (date-filtered) so we never auto-select
|
|
3161
|
+
// a ticket the user couldn't have picked themselves from the dropdown.
|
|
3162
|
+
if (promoCode && !promoState.applyingCode && allowedTicketTypes.length > 0) {
|
|
3163
|
+
const isValid = promoState.isCodeValidForTicket;
|
|
3164
|
+
const qualifying = isValid && allowedTicketTypes.find(isValid);
|
|
3165
|
+
const toSelect = qualifying || (allowedTicketTypes.length === 1 ? allowedTicketTypes[0] : null);
|
|
3166
|
+
if (toSelect) handleTicketChange(toSelect);
|
|
3136
3167
|
}
|
|
3137
3168
|
|
|
3138
3169
|
return;
|
|
@@ -3149,7 +3180,7 @@ const TicketTypeComponent = ({
|
|
|
3149
3180
|
setTicket(null);
|
|
3150
3181
|
setQuantity(minQuantity);
|
|
3151
3182
|
}
|
|
3152
|
-
}, [promoCode, originalTicketTypes]);
|
|
3183
|
+
}, [promoCode, promoState.applyingCode, allowedTicketTypes, originalTicketTypes]);
|
|
3153
3184
|
const showTicketSelector = allowedTicketTypes.length > 0;
|
|
3154
3185
|
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
|
|
3155
3186
|
|
|
@@ -3200,7 +3231,24 @@ const TicketTypeComponent = ({
|
|
|
3200
3231
|
const decrementQuantity = () => setQuantity(quantity - 1);
|
|
3201
3232
|
|
|
3202
3233
|
const handleApplyPromoCode = async code => {
|
|
3203
|
-
|
|
3234
|
+
// If the user applies the suggested/discovered code while a
|
|
3235
|
+
// non-qualifying ticket is selected, deselect first. The qualifying
|
|
3236
|
+
// ticket may not yet be in originalTicketTypes (it's revealed by the
|
|
3237
|
+
// code-filtered refetch inside applyPromoCode). After apply resolves,
|
|
3238
|
+
// the post-apply effect picks the qualifying ticket from the
|
|
3239
|
+
// refreshed list. Manual non-discovered codes still validate against
|
|
3240
|
+
// the current ticket — backend decides.
|
|
3241
|
+
const isDiscovered = code === promoState.suggestedCode;
|
|
3242
|
+
const isValid = promoState.isCodeValidForTicket;
|
|
3243
|
+
let targetTicket = ticket;
|
|
3244
|
+
|
|
3245
|
+
if (isDiscovered && isValid && ticket && !isValid(ticket)) {
|
|
3246
|
+
setTicket(null);
|
|
3247
|
+
setQuantity(minQuantity);
|
|
3248
|
+
targetTicket = null;
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
await promoActions.onApply(code, targetTicket, quantity);
|
|
3204
3252
|
};
|
|
3205
3253
|
|
|
3206
3254
|
return /*#__PURE__*/external_react_default().createElement("div", {
|
|
@@ -3310,6 +3358,7 @@ const TicketTypeComponent = ({
|
|
|
3310
3358
|
promoCode: promoCode,
|
|
3311
3359
|
suggestedCode: promoState.suggestedCode,
|
|
3312
3360
|
isAutoApplied: promoState.isAutoApplied,
|
|
3361
|
+
isCurrentTicketQualifying: promoState.isCodeValidForTicket(ticket),
|
|
3313
3362
|
onInputChange: promoActions.onInputChange,
|
|
3314
3363
|
onApply: handleApplyPromoCode,
|
|
3315
3364
|
onRemove: promoActions.onRemove,
|
|
@@ -3915,14 +3964,18 @@ const RegistrationFormContent = _ref => {
|
|
|
3915
3964
|
} = promo; // Error rendered in the promo notice slot — form-level warning layered on top
|
|
3916
3965
|
// of the hook's own validation error (API rejection or status-derived).
|
|
3917
3966
|
|
|
3918
|
-
const ticketStepError = unappliedCodeWarning ?? promoState.validationError; // Clear the unapplied-code warning once
|
|
3919
|
-
//
|
|
3967
|
+
const ticketStepError = unappliedCodeWarning ?? promoState.validationError; // Clear the unapplied-code warning once it's no longer the right message to show.
|
|
3968
|
+
// The hook's own validationError takes precedence: if the user actually clicked
|
|
3969
|
+
// Apply and the backend rejected, surfacing "you didn't apply" would mask the
|
|
3970
|
+
// specific rejection reason. Depending on validationError (rather than on
|
|
3971
|
+
// applyPromoCode's brief Redux promoCode=truthy window) keeps the cleanup
|
|
3972
|
+
// robust against refactors of the apply action's sequencing.
|
|
3920
3973
|
|
|
3921
3974
|
(0,external_react_.useEffect)(() => {
|
|
3922
|
-
if (!formValues?.promoCode || promoCode || promoState.status === constants.PROMO_STATUS.SUGGESTED) {
|
|
3975
|
+
if (!formValues?.promoCode || promoCode || promoState.status === constants.PROMO_STATUS.SUGGESTED || promoState.validationError) {
|
|
3923
3976
|
setUnappliedCodeWarning(null);
|
|
3924
3977
|
}
|
|
3925
|
-
}, [formValues?.promoCode, promoCode, promoState.status]);
|
|
3978
|
+
}, [formValues?.promoCode, promoCode, promoState.status, promoState.validationError]);
|
|
3926
3979
|
const [ref, {
|
|
3927
3980
|
height
|
|
3928
3981
|
}] = (0,external_react_use_namespaceObject.useMeasure)();
|
|
@@ -5161,7 +5214,7 @@ module.exports = require("sweetalert2");
|
|
|
5161
5214
|
/***/ ((module) => {
|
|
5162
5215
|
|
|
5163
5216
|
"use strict";
|
|
5164
|
-
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."}}');
|
|
5217
|
+
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:","suggestion_label_switch":"Following promo code applies to a different ticket. Apply to switch.","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."}}');
|
|
5165
5218
|
|
|
5166
5219
|
/***/ })
|
|
5167
5220
|
|