@edx/frontend-app-subscription-checkout 1.0.0

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.
Files changed (153) hide show
  1. package/LICENSE +661 -0
  2. package/README.rst +235 -0
  3. package/dist/Main.d.ts +3 -0
  4. package/dist/Main.js +15 -0
  5. package/dist/Main.js.map +1 -0
  6. package/dist/app.d.ts +3 -0
  7. package/dist/app.js +13 -0
  8. package/dist/app.js.map +1 -0
  9. package/dist/checkoutPage/CheckoutPage.d.ts +3 -0
  10. package/dist/checkoutPage/CheckoutPage.js +30 -0
  11. package/dist/checkoutPage/CheckoutPage.js.map +1 -0
  12. package/dist/components/BrandMarks/BrandMarks.d.ts +3 -0
  13. package/dist/components/BrandMarks/BrandMarks.js +9 -0
  14. package/dist/components/BrandMarks/BrandMarks.js.map +1 -0
  15. package/dist/components/CartSummary/CartSummary.d.ts +21 -0
  16. package/dist/components/CartSummary/CartSummary.js +30 -0
  17. package/dist/components/CartSummary/CartSummary.js.map +1 -0
  18. package/dist/components/CartSummary/Messages.d.ts +73 -0
  19. package/dist/components/CartSummary/Messages.js +76 -0
  20. package/dist/components/CartSummary/Messages.js.map +1 -0
  21. package/dist/components/Checkout/Checkout.d.ts +4 -0
  22. package/dist/components/Checkout/Checkout.js +40 -0
  23. package/dist/components/Checkout/Checkout.js.map +1 -0
  24. package/dist/components/CheckoutGate/CheckoutGate.d.ts +7 -0
  25. package/dist/components/CheckoutGate/CheckoutGate.js +35 -0
  26. package/dist/components/CheckoutGate/CheckoutGate.js.map +1 -0
  27. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +9 -0
  28. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +31 -0
  29. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +1 -0
  30. package/dist/components/CourseEnrollmentCard/Messages.d.ts +33 -0
  31. package/dist/components/CourseEnrollmentCard/Messages.js +35 -0
  32. package/dist/components/CourseEnrollmentCard/Messages.js.map +1 -0
  33. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.d.ts +13 -0
  34. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js +11 -0
  35. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js.map +1 -0
  36. package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +15 -0
  37. package/dist/components/EnrollmentSummary/EnrollmentSummary.js +21 -0
  38. package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -0
  39. package/dist/components/EnrollmentSummary/Messages.d.ts +33 -0
  40. package/dist/components/EnrollmentSummary/Messages.js +35 -0
  41. package/dist/components/EnrollmentSummary/Messages.js.map +1 -0
  42. package/dist/components/PaymentFields/PaymentFields.d.ts +9 -0
  43. package/dist/components/PaymentFields/PaymentFields.js +7 -0
  44. package/dist/components/PaymentFields/PaymentFields.js.map +1 -0
  45. package/dist/components/PaymentForm/Messages.d.ts +88 -0
  46. package/dist/components/PaymentForm/Messages.js +95 -0
  47. package/dist/components/PaymentForm/Messages.js.map +1 -0
  48. package/dist/components/PaymentForm/PaymentForm.d.ts +21 -0
  49. package/dist/components/PaymentForm/PaymentForm.js +69 -0
  50. package/dist/components/PaymentForm/PaymentForm.js.map +1 -0
  51. package/dist/components/StatusScreens/Messages.d.ts +103 -0
  52. package/dist/components/StatusScreens/Messages.js +108 -0
  53. package/dist/components/StatusScreens/Messages.js.map +1 -0
  54. package/dist/components/StatusScreens/StatusScreens.d.ts +23 -0
  55. package/dist/components/StatusScreens/StatusScreens.js +25 -0
  56. package/dist/components/StatusScreens/StatusScreens.js.map +1 -0
  57. package/dist/constants.d.ts +59 -0
  58. package/dist/constants.js +276 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/data/hooks/keys.d.ts +14 -0
  61. package/dist/data/hooks/keys.js +15 -0
  62. package/dist/data/hooks/keys.js.map +1 -0
  63. package/dist/data/hooks/useCheckout.d.ts +57 -0
  64. package/dist/data/hooks/useCheckout.js +249 -0
  65. package/dist/data/hooks/useCheckout.js.map +1 -0
  66. package/dist/data/hooks/useCheckoutGate.d.ts +15 -0
  67. package/dist/data/hooks/useCheckoutGate.js +39 -0
  68. package/dist/data/hooks/useCheckoutGate.js.map +1 -0
  69. package/dist/data/hooks/useCheckoutMutations.d.ts +16 -0
  70. package/dist/data/hooks/useCheckoutMutations.js +131 -0
  71. package/dist/data/hooks/useCheckoutMutations.js.map +1 -0
  72. package/dist/data/hooks/useCheckoutQueries.d.ts +30 -0
  73. package/dist/data/hooks/useCheckoutQueries.js +97 -0
  74. package/dist/data/hooks/useCheckoutQueries.js.map +1 -0
  75. package/dist/data/services/subs/urls.d.ts +2 -0
  76. package/dist/data/services/subs/urls.js +4 -0
  77. package/dist/data/services/subs/urls.js.map +1 -0
  78. package/dist/i18n/index.d.ts +1 -0
  79. package/dist/i18n/index.js +2 -0
  80. package/dist/i18n/index.js.map +1 -0
  81. package/dist/index.d.ts +2 -0
  82. package/dist/index.js +3 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/messages.d.ts +8 -0
  85. package/dist/messages.js +10 -0
  86. package/dist/messages.js.map +1 -0
  87. package/dist/routes.d.ts +18 -0
  88. package/dist/routes.js +67 -0
  89. package/dist/routes.js.map +1 -0
  90. package/dist/slots/ExampleSlot/ExampleSlot.d.ts +3 -0
  91. package/dist/slots/ExampleSlot/ExampleSlot.js +6 -0
  92. package/dist/slots/ExampleSlot/ExampleSlot.js.map +1 -0
  93. package/dist/slots.d.ts +3 -0
  94. package/dist/slots.js +7 -0
  95. package/dist/slots.js.map +1 -0
  96. package/dist/style.scss +14 -0
  97. package/dist/styles/components/brandMarks.scss +54 -0
  98. package/dist/styles/components/cartSummary.scss +18 -0
  99. package/dist/styles/components/checkout.scss +29 -0
  100. package/dist/styles/components/checkoutStepper.scss +9 -0
  101. package/dist/styles/components/courseEnrollmentCard.scss +38 -0
  102. package/dist/styles/components/edxUnlimitedBanner.scss +138 -0
  103. package/dist/styles/components/enrollmentSummary.scss +13 -0
  104. package/dist/styles/components/paymentFields.scss +15 -0
  105. package/dist/styles/components/paymentForm.scss +105 -0
  106. package/dist/styles/components/statusScreens.scss +29 -0
  107. package/dist/styles/components/successScreen.scss +0 -0
  108. package/dist/types.d.ts +222 -0
  109. package/dist/types.js +2 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/utils/auth.d.ts +7 -0
  112. package/dist/utils/auth.js +28 -0
  113. package/dist/utils/auth.js.map +1 -0
  114. package/dist/utils/billingDetails.d.ts +30 -0
  115. package/dist/utils/billingDetails.js +47 -0
  116. package/dist/utils/billingDetails.js.map +1 -0
  117. package/dist/utils/bootstrapApi.d.ts +20 -0
  118. package/dist/utils/bootstrapApi.js +142 -0
  119. package/dist/utils/bootstrapApi.js.map +1 -0
  120. package/dist/utils/cartApi.d.ts +16 -0
  121. package/dist/utils/cartApi.js +118 -0
  122. package/dist/utils/cartApi.js.map +1 -0
  123. package/dist/utils/checkout.d.ts +6 -0
  124. package/dist/utils/checkout.js +28 -0
  125. package/dist/utils/checkout.js.map +1 -0
  126. package/dist/utils/fetchActiveSubscriptions.d.ts +4 -0
  127. package/dist/utils/fetchActiveSubscriptions.js +36 -0
  128. package/dist/utils/fetchActiveSubscriptions.js.map +1 -0
  129. package/dist/utils/fetchBillingPlans.d.ts +2 -0
  130. package/dist/utils/fetchBillingPlans.js +48 -0
  131. package/dist/utils/fetchBillingPlans.js.map +1 -0
  132. package/dist/utils/graphqlClient.d.ts +16 -0
  133. package/dist/utils/graphqlClient.js +39 -0
  134. package/dist/utils/graphqlClient.js.map +1 -0
  135. package/dist/utils/index.d.ts +3 -0
  136. package/dist/utils/index.js +17 -0
  137. package/dist/utils/index.js.map +1 -0
  138. package/dist/utils/provision.d.ts +25 -0
  139. package/dist/utils/provision.js +95 -0
  140. package/dist/utils/provision.js.map +1 -0
  141. package/dist/utils/queries.d.ts +35 -0
  142. package/dist/utils/queries.js +168 -0
  143. package/dist/utils/queries.js.map +1 -0
  144. package/dist/utils/stripe.d.ts +7 -0
  145. package/dist/utils/stripe.js +43 -0
  146. package/dist/utils/stripe.js.map +1 -0
  147. package/dist/widgets/ExampleHeader/app.d.ts +3 -0
  148. package/dist/widgets/ExampleHeader/app.js +19 -0
  149. package/dist/widgets/ExampleHeader/app.js.map +1 -0
  150. package/dist/widgets/ExampleHeader/index.d.ts +1 -0
  151. package/dist/widgets/ExampleHeader/index.js +2 -0
  152. package/dist/widgets/ExampleHeader/index.js.map +1 -0
  153. package/package.json +85 -0
@@ -0,0 +1,276 @@
1
+ export const appId = 'org.openedx.frontend.app.subscription.checkout';
2
+ export const subscriptionCheckoutRole = 'org.openedx.frontend.role.subscription.checkout';
3
+ // --- Cart BI state machine ---------------------------------------------------
4
+ export const STATUS = {
5
+ IN_CART: 'IN_CART',
6
+ CONFIRM: 'CONFIRM',
7
+ SANCTION_STARTED: 'SANCTION_STARTED',
8
+ SANCTION_PASSED: 'SANCTION_PASSED',
9
+ SANCTION_BLOCK: 'SANCTION_BLOCK',
10
+ STRIPE_STARTED: 'STRIPE_STARTED',
11
+ STRIPE_SUBSCRIBED: 'STRIPE_SUBSCRIBED',
12
+ STRIPE_CONFIRMATION_REQUIRED: 'STRIPE_CONFIRMATION_REQUIRED',
13
+ STRIPE_FAIL: 'STRIPE_FAIL',
14
+ SUBSCRIPTION_CREATED: 'SUBSCRIPTION_CREATED',
15
+ };
16
+ export const TERMINAL_STATES = [
17
+ STATUS.SUBSCRIPTION_CREATED,
18
+ STATUS.SANCTION_BLOCK,
19
+ STATUS.STRIPE_FAIL,
20
+ ];
21
+ export const STATUS_LABELS = {
22
+ IN_CART: 'Cart created',
23
+ CONFIRM: 'Order confirmed',
24
+ SANCTION_STARTED: 'Checking sanctions…',
25
+ SANCTION_PASSED: 'Sanctions passed — setting up your account…',
26
+ SANCTION_BLOCK: 'Order blocked',
27
+ STRIPE_STARTED: 'Setting up your subscription…',
28
+ STRIPE_CONFIRMATION_REQUIRED: 'Card verification required',
29
+ STRIPE_SUBSCRIBED: 'Card verified — finalizing…',
30
+ STRIPE_FAIL: 'Payment failed',
31
+ SUBSCRIPTION_CREATED: 'Subscription created',
32
+ };
33
+ export const isTerminalStatus = (status) => TERMINAL_STATES.includes(status);
34
+ /** UI phase derived from the raw bpStatus code + cart readiness. */
35
+ export function phaseFor(status, ready) {
36
+ if (status === STATUS.SUBSCRIPTION_CREATED)
37
+ return 'success';
38
+ if (status === STATUS.SANCTION_BLOCK)
39
+ return 'blocked';
40
+ if (status === STATUS.STRIPE_FAIL)
41
+ return 'failed';
42
+ if (status && status !== STATUS.IN_CART)
43
+ return 'processing';
44
+ return ready ? 'ready' : 'init';
45
+ }
46
+ // --- Dev defaults (match the local test harness) -----------------------------
47
+ export const DEFAULTS = {
48
+ apiUrl: '/api/graphql',
49
+ confirmIntentUrl: '/api/stripe/confirm-pi',
50
+ customerUid: '019d2bde-f769-743d-88f9-8bf0d1a7a002',
51
+ salableUid: '019d2ce7-05bc-7dd6-b141-e32df9ac86c1',
52
+ billingPlanUid: '019d2ce7-05c0-7188-81b0-8eb747b41b0f',
53
+ };
54
+ export const LS_KEYS = { biId: 'twou.cartBiId', uid: 'twou.cartUid' };
55
+ // ─── Checkout gate feature flags (dev controls) ───────────────────────────────
56
+ // Set to false during development to bypass the country gate check.
57
+ // Should be true in production. Subscriber access is enforced outside this app.
58
+ /** When false, the country check is skipped — all countries can access checkout. */
59
+ export const GATE_CHECK_COUNTRY = true;
60
+ /**
61
+ * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.
62
+ * Add or remove codes here to open or restrict access by country.
63
+ * e.g. ['US', 'CA', 'GB'] to allow US, Canada, and UK.
64
+ */
65
+ export const ALLOWED_CHECKOUT_COUNTRIES = ['US', 'CA'];
66
+ /**
67
+ * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.
68
+ * Add or remove codes here to control which residents see the second checkbox.
69
+ */
70
+ export const COUNTRIES_REQUIRING_EXTRA_CONFIRM = ['GB', 'CA'];
71
+ export const COUNTRIES = [
72
+ ['AF', 'Afghanistan'],
73
+ ['AL', 'Albania'],
74
+ ['DZ', 'Algeria'],
75
+ ['AD', 'Andorra'],
76
+ ['AO', 'Angola'],
77
+ ['AG', 'Antigua and Barbuda'],
78
+ ['AR', 'Argentina'],
79
+ ['AM', 'Armenia'],
80
+ ['AU', 'Australia'],
81
+ ['AT', 'Austria'],
82
+ ['AZ', 'Azerbaijan'],
83
+ ['BS', 'Bahamas'],
84
+ ['BH', 'Bahrain'],
85
+ ['BD', 'Bangladesh'],
86
+ ['BB', 'Barbados'],
87
+ ['BY', 'Belarus'],
88
+ ['BE', 'Belgium'],
89
+ ['BZ', 'Belize'],
90
+ ['BJ', 'Benin'],
91
+ ['BT', 'Bhutan'],
92
+ ['BO', 'Bolivia'],
93
+ ['BA', 'Bosnia and Herzegovina'],
94
+ ['BW', 'Botswana'],
95
+ ['BR', 'Brazil'],
96
+ ['BN', 'Brunei'],
97
+ ['BG', 'Bulgaria'],
98
+ ['BF', 'Burkina Faso'],
99
+ ['BI', 'Burundi'],
100
+ ['CV', 'Cabo Verde'],
101
+ ['KH', 'Cambodia'],
102
+ ['CM', 'Cameroon'],
103
+ ['CA', 'Canada'],
104
+ ['CF', 'Central African Republic'],
105
+ ['TD', 'Chad'],
106
+ ['CL', 'Chile'],
107
+ ['CN', 'China'],
108
+ ['CO', 'Colombia'],
109
+ ['KM', 'Comoros'],
110
+ ['CG', 'Congo (Congo-Brazzaville)'],
111
+ ['CR', 'Costa Rica'],
112
+ ['HR', 'Croatia'],
113
+ ['CU', 'Cuba'],
114
+ ['CY', 'Cyprus'],
115
+ ['CZ', 'Czechia (Czech Republic)'],
116
+ ['CD', 'Democratic Republic of the Congo'],
117
+ ['DK', 'Denmark'],
118
+ ['DJ', 'Djibouti'],
119
+ ['DM', 'Dominica'],
120
+ ['DO', 'Dominican Republic'],
121
+ ['EC', 'Ecuador'],
122
+ ['EG', 'Egypt'],
123
+ ['SV', 'El Salvador'],
124
+ ['GQ', 'Equatorial Guinea'],
125
+ ['ER', 'Eritrea'],
126
+ ['EE', 'Estonia'],
127
+ ['SZ', 'Eswatini'],
128
+ ['ET', 'Ethiopia'],
129
+ ['FJ', 'Fiji'],
130
+ ['FI', 'Finland'],
131
+ ['FR', 'France'],
132
+ ['GA', 'Gabon'],
133
+ ['GM', 'Gambia'],
134
+ ['GE', 'Georgia'],
135
+ ['DE', 'Germany'],
136
+ ['GH', 'Ghana'],
137
+ ['GR', 'Greece'],
138
+ ['GD', 'Grenada'],
139
+ ['GT', 'Guatemala'],
140
+ ['GN', 'Guinea'],
141
+ ['GW', 'Guinea-Bissau'],
142
+ ['GY', 'Guyana'],
143
+ ['HT', 'Haiti'],
144
+ ['VA', 'Holy See (Vatican City)'],
145
+ ['HN', 'Honduras'],
146
+ ['HU', 'Hungary'],
147
+ ['IS', 'Iceland'],
148
+ ['IN', 'India'],
149
+ ['ID', 'Indonesia'],
150
+ ['IR', 'Iran'],
151
+ ['IQ', 'Iraq'],
152
+ ['IE', 'Ireland'],
153
+ ['IL', 'Israel'],
154
+ ['IT', 'Italy'],
155
+ ['CI', "Ivory Coast (Côte d'Ivoire)"],
156
+ ['JM', 'Jamaica'],
157
+ ['JP', 'Japan'],
158
+ ['JO', 'Jordan'],
159
+ ['KZ', 'Kazakhstan'],
160
+ ['KE', 'Kenya'],
161
+ ['KI', 'Kiribati'],
162
+ ['KW', 'Kuwait'],
163
+ ['KG', 'Kyrgyzstan'],
164
+ ['LA', 'Laos'],
165
+ ['LV', 'Latvia'],
166
+ ['LB', 'Lebanon'],
167
+ ['LS', 'Lesotho'],
168
+ ['LR', 'Liberia'],
169
+ ['LY', 'Libya'],
170
+ ['LI', 'Liechtenstein'],
171
+ ['LT', 'Lithuania'],
172
+ ['LU', 'Luxembourg'],
173
+ ['MG', 'Madagascar'],
174
+ ['MW', 'Malawi'],
175
+ ['MY', 'Malaysia'],
176
+ ['MV', 'Maldives'],
177
+ ['ML', 'Mali'],
178
+ ['MT', 'Malta'],
179
+ ['MH', 'Marshall Islands'],
180
+ ['MR', 'Mauritania'],
181
+ ['MU', 'Mauritius'],
182
+ ['MX', 'Mexico'],
183
+ ['FM', 'Micronesia'],
184
+ ['MD', 'Moldova'],
185
+ ['MC', 'Monaco'],
186
+ ['MN', 'Mongolia'],
187
+ ['ME', 'Montenegro'],
188
+ ['MA', 'Morocco'],
189
+ ['MZ', 'Mozambique'],
190
+ ['MM', 'Myanmar (Burma)'],
191
+ ['NA', 'Namibia'],
192
+ ['NR', 'Nauru'],
193
+ ['NP', 'Nepal'],
194
+ ['NL', 'Netherlands'],
195
+ ['NZ', 'New Zealand'],
196
+ ['NI', 'Nicaragua'],
197
+ ['NE', 'Niger'],
198
+ ['NG', 'Nigeria'],
199
+ ['KP', 'North Korea'],
200
+ ['MK', 'North Macedonia'],
201
+ ['NO', 'Norway'],
202
+ ['OM', 'Oman'],
203
+ ['PK', 'Pakistan'],
204
+ ['PW', 'Palau'],
205
+ ['PS', 'Palestine State'],
206
+ ['PA', 'Panama'],
207
+ ['PG', 'Papua New Guinea'],
208
+ ['PY', 'Paraguay'],
209
+ ['PE', 'Peru'],
210
+ ['PH', 'Philippines'],
211
+ ['PL', 'Poland'],
212
+ ['PT', 'Portugal'],
213
+ ['QA', 'Qatar'],
214
+ ['RO', 'Romania'],
215
+ ['RU', 'Russia'],
216
+ ['RW', 'Rwanda'],
217
+ ['KN', 'Saint Kitts and Nevis'],
218
+ ['LC', 'Saint Lucia'],
219
+ ['VC', 'Saint Vincent and the Grenadines'],
220
+ ['WS', 'Samoa'],
221
+ ['SM', 'San Marino'],
222
+ ['ST', 'Sao Tome and Principe'],
223
+ ['SA', 'Saudi Arabia'],
224
+ ['SN', 'Senegal'],
225
+ ['RS', 'Serbia'],
226
+ ['SC', 'Seychelles'],
227
+ ['SL', 'Sierra Leone'],
228
+ ['SG', 'Singapore'],
229
+ ['SK', 'Slovakia'],
230
+ ['SI', 'Slovenia'],
231
+ ['SB', 'Solomon Islands'],
232
+ ['SO', 'Somalia'],
233
+ ['ZA', 'South Africa'],
234
+ ['KR', 'South Korea'],
235
+ ['SS', 'South Sudan'],
236
+ ['ES', 'Spain'],
237
+ ['LK', 'Sri Lanka'],
238
+ ['SD', 'Sudan'],
239
+ ['SR', 'Suriname'],
240
+ ['SE', 'Sweden'],
241
+ ['CH', 'Switzerland'],
242
+ ['SY', 'Syria'],
243
+ ['TJ', 'Tajikistan'],
244
+ ['TZ', 'Tanzania'],
245
+ ['TH', 'Thailand'],
246
+ ['TL', 'Timor-Leste'],
247
+ ['TG', 'Togo'],
248
+ ['TO', 'Tonga'],
249
+ ['TT', 'Trinidad and Tobago'],
250
+ ['TN', 'Tunisia'],
251
+ ['TR', 'Turkey'],
252
+ ['TM', 'Turkmenistan'],
253
+ ['TV', 'Tuvalu'],
254
+ ['UG', 'Uganda'],
255
+ ['UA', 'Ukraine'],
256
+ ['AE', 'United Arab Emirates'],
257
+ ['GB', 'United Kingdom'],
258
+ ['US', 'United States'],
259
+ ['UY', 'Uruguay'],
260
+ ['UZ', 'Uzbekistan'],
261
+ ['VU', 'Vanuatu'],
262
+ ['VE', 'Venezuela'],
263
+ ['VN', 'Vietnam'],
264
+ ['YE', 'Yemen'],
265
+ ['ZM', 'Zambia'],
266
+ ['ZW', 'Zimbabwe'],
267
+ ];
268
+ // --- Stripe Element presentation ---------------------------------------------
269
+ // A div that hosts a Stripe Element but reads like a Paragon input.
270
+ export const STRIPE_FIELD_STYLE = {
271
+ height: 'auto', minHeight: '2.875rem', display: 'flex', alignItems: 'center',
272
+ };
273
+ export const STRIPE_ELEMENT_OPTS = {
274
+ style: { base: { fontSize: '16px', color: '#1a1a1a', '::placeholder': { color: '#8f8f8f' } } },
275
+ };
276
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CSSProperties } from 'react';\n\nexport const appId = 'org.openedx.frontend.app.subscription.checkout';\nexport const subscriptionCheckoutRole = 'org.openedx.frontend.role.subscription.checkout';\n\n// --- Cart BI state machine ---------------------------------------------------\nexport const STATUS = {\n IN_CART: 'IN_CART',\n CONFIRM: 'CONFIRM',\n SANCTION_STARTED: 'SANCTION_STARTED',\n SANCTION_PASSED: 'SANCTION_PASSED',\n SANCTION_BLOCK: 'SANCTION_BLOCK',\n STRIPE_STARTED: 'STRIPE_STARTED',\n STRIPE_SUBSCRIBED: 'STRIPE_SUBSCRIBED',\n STRIPE_CONFIRMATION_REQUIRED: 'STRIPE_CONFIRMATION_REQUIRED',\n STRIPE_FAIL: 'STRIPE_FAIL',\n SUBSCRIPTION_CREATED: 'SUBSCRIPTION_CREATED',\n} as const;\n\nexport type Status = typeof STATUS[keyof typeof STATUS];\n\nexport type Phase = 'init' | 'ready' | 'processing' | 'threeds' | 'success' | 'blocked' | 'failed';\n\nexport const TERMINAL_STATES: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.SANCTION_BLOCK,\n STATUS.STRIPE_FAIL,\n];\n\nexport const STATUS_LABELS: Record<string, string> = {\n IN_CART: 'Cart created',\n CONFIRM: 'Order confirmed',\n SANCTION_STARTED: 'Checking sanctions…',\n SANCTION_PASSED: 'Sanctions passed — setting up your account…',\n SANCTION_BLOCK: 'Order blocked',\n STRIPE_STARTED: 'Setting up your subscription…',\n STRIPE_CONFIRMATION_REQUIRED: 'Card verification required',\n STRIPE_SUBSCRIBED: 'Card verified — finalizing…',\n STRIPE_FAIL: 'Payment failed',\n SUBSCRIPTION_CREATED: 'Subscription created',\n};\n\nexport const isTerminalStatus = (status: Status | null | undefined): boolean =>\n TERMINAL_STATES.includes(status as Status);\n\n/** UI phase derived from the raw bpStatus code + cart readiness. */\nexport function phaseFor(status: Status | null, ready: boolean): Phase {\n if (status === STATUS.SUBSCRIPTION_CREATED) return 'success';\n if (status === STATUS.SANCTION_BLOCK) return 'blocked';\n if (status === STATUS.STRIPE_FAIL) return 'failed';\n if (status && status !== STATUS.IN_CART) return 'processing';\n return ready ? 'ready' : 'init';\n}\n\n// --- Dev defaults (match the local test harness) -----------------------------\nexport const DEFAULTS = {\n apiUrl: '/api/graphql',\n confirmIntentUrl: '/api/stripe/confirm-pi',\n customerUid: '019d2bde-f769-743d-88f9-8bf0d1a7a002',\n salableUid: '019d2ce7-05bc-7dd6-b141-e32df9ac86c1',\n billingPlanUid: '019d2ce7-05c0-7188-81b0-8eb747b41b0f',\n};\n\nexport const LS_KEYS = { biId: 'twou.cartBiId', uid: 'twou.cartUid' };\n\n// ─── Checkout gate feature flags (dev controls) ───────────────────────────────\n// Set to false during development to bypass the country gate check.\n// Should be true in production. Subscriber access is enforced outside this app.\n\n/** When false, the country check is skipped — all countries can access checkout. */\nexport const GATE_CHECK_COUNTRY = true;\n\n/**\n * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.\n * Add or remove codes here to open or restrict access by country.\n * e.g. ['US', 'CA', 'GB'] to allow US, Canada, and UK.\n */\nexport const ALLOWED_CHECKOUT_COUNTRIES: readonly string[] = ['US', 'CA'];\n\n/**\n * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.\n * Add or remove codes here to control which residents see the second checkbox.\n */\nexport const COUNTRIES_REQUIRING_EXTRA_CONFIRM: readonly string[] = ['GB', 'CA'];\n\nexport const COUNTRIES: readonly (readonly [string, string])[] = [\n ['AF', 'Afghanistan'],\n ['AL', 'Albania'],\n ['DZ', 'Algeria'],\n ['AD', 'Andorra'],\n ['AO', 'Angola'],\n ['AG', 'Antigua and Barbuda'],\n ['AR', 'Argentina'],\n ['AM', 'Armenia'],\n ['AU', 'Australia'],\n ['AT', 'Austria'],\n ['AZ', 'Azerbaijan'],\n ['BS', 'Bahamas'],\n ['BH', 'Bahrain'],\n ['BD', 'Bangladesh'],\n ['BB', 'Barbados'],\n ['BY', 'Belarus'],\n ['BE', 'Belgium'],\n ['BZ', 'Belize'],\n ['BJ', 'Benin'],\n ['BT', 'Bhutan'],\n ['BO', 'Bolivia'],\n ['BA', 'Bosnia and Herzegovina'],\n ['BW', 'Botswana'],\n ['BR', 'Brazil'],\n ['BN', 'Brunei'],\n ['BG', 'Bulgaria'],\n ['BF', 'Burkina Faso'],\n ['BI', 'Burundi'],\n ['CV', 'Cabo Verde'],\n ['KH', 'Cambodia'],\n ['CM', 'Cameroon'],\n ['CA', 'Canada'],\n ['CF', 'Central African Republic'],\n ['TD', 'Chad'],\n ['CL', 'Chile'],\n ['CN', 'China'],\n ['CO', 'Colombia'],\n ['KM', 'Comoros'],\n ['CG', 'Congo (Congo-Brazzaville)'],\n ['CR', 'Costa Rica'],\n ['HR', 'Croatia'],\n ['CU', 'Cuba'],\n ['CY', 'Cyprus'],\n ['CZ', 'Czechia (Czech Republic)'],\n ['CD', 'Democratic Republic of the Congo'],\n ['DK', 'Denmark'],\n ['DJ', 'Djibouti'],\n ['DM', 'Dominica'],\n ['DO', 'Dominican Republic'],\n ['EC', 'Ecuador'],\n ['EG', 'Egypt'],\n ['SV', 'El Salvador'],\n ['GQ', 'Equatorial Guinea'],\n ['ER', 'Eritrea'],\n ['EE', 'Estonia'],\n ['SZ', 'Eswatini'],\n ['ET', 'Ethiopia'],\n ['FJ', 'Fiji'],\n ['FI', 'Finland'],\n ['FR', 'France'],\n ['GA', 'Gabon'],\n ['GM', 'Gambia'],\n ['GE', 'Georgia'],\n ['DE', 'Germany'],\n ['GH', 'Ghana'],\n ['GR', 'Greece'],\n ['GD', 'Grenada'],\n ['GT', 'Guatemala'],\n ['GN', 'Guinea'],\n ['GW', 'Guinea-Bissau'],\n ['GY', 'Guyana'],\n ['HT', 'Haiti'],\n ['VA', 'Holy See (Vatican City)'],\n ['HN', 'Honduras'],\n ['HU', 'Hungary'],\n ['IS', 'Iceland'],\n ['IN', 'India'],\n ['ID', 'Indonesia'],\n ['IR', 'Iran'],\n ['IQ', 'Iraq'],\n ['IE', 'Ireland'],\n ['IL', 'Israel'],\n ['IT', 'Italy'],\n ['CI', \"Ivory Coast (Côte d'Ivoire)\"],\n ['JM', 'Jamaica'],\n ['JP', 'Japan'],\n ['JO', 'Jordan'],\n ['KZ', 'Kazakhstan'],\n ['KE', 'Kenya'],\n ['KI', 'Kiribati'],\n ['KW', 'Kuwait'],\n ['KG', 'Kyrgyzstan'],\n ['LA', 'Laos'],\n ['LV', 'Latvia'],\n ['LB', 'Lebanon'],\n ['LS', 'Lesotho'],\n ['LR', 'Liberia'],\n ['LY', 'Libya'],\n ['LI', 'Liechtenstein'],\n ['LT', 'Lithuania'],\n ['LU', 'Luxembourg'],\n ['MG', 'Madagascar'],\n ['MW', 'Malawi'],\n ['MY', 'Malaysia'],\n ['MV', 'Maldives'],\n ['ML', 'Mali'],\n ['MT', 'Malta'],\n ['MH', 'Marshall Islands'],\n ['MR', 'Mauritania'],\n ['MU', 'Mauritius'],\n ['MX', 'Mexico'],\n ['FM', 'Micronesia'],\n ['MD', 'Moldova'],\n ['MC', 'Monaco'],\n ['MN', 'Mongolia'],\n ['ME', 'Montenegro'],\n ['MA', 'Morocco'],\n ['MZ', 'Mozambique'],\n ['MM', 'Myanmar (Burma)'],\n ['NA', 'Namibia'],\n ['NR', 'Nauru'],\n ['NP', 'Nepal'],\n ['NL', 'Netherlands'],\n ['NZ', 'New Zealand'],\n ['NI', 'Nicaragua'],\n ['NE', 'Niger'],\n ['NG', 'Nigeria'],\n ['KP', 'North Korea'],\n ['MK', 'North Macedonia'],\n ['NO', 'Norway'],\n ['OM', 'Oman'],\n ['PK', 'Pakistan'],\n ['PW', 'Palau'],\n ['PS', 'Palestine State'],\n ['PA', 'Panama'],\n ['PG', 'Papua New Guinea'],\n ['PY', 'Paraguay'],\n ['PE', 'Peru'],\n ['PH', 'Philippines'],\n ['PL', 'Poland'],\n ['PT', 'Portugal'],\n ['QA', 'Qatar'],\n ['RO', 'Romania'],\n ['RU', 'Russia'],\n ['RW', 'Rwanda'],\n ['KN', 'Saint Kitts and Nevis'],\n ['LC', 'Saint Lucia'],\n ['VC', 'Saint Vincent and the Grenadines'],\n ['WS', 'Samoa'],\n ['SM', 'San Marino'],\n ['ST', 'Sao Tome and Principe'],\n ['SA', 'Saudi Arabia'],\n ['SN', 'Senegal'],\n ['RS', 'Serbia'],\n ['SC', 'Seychelles'],\n ['SL', 'Sierra Leone'],\n ['SG', 'Singapore'],\n ['SK', 'Slovakia'],\n ['SI', 'Slovenia'],\n ['SB', 'Solomon Islands'],\n ['SO', 'Somalia'],\n ['ZA', 'South Africa'],\n ['KR', 'South Korea'],\n ['SS', 'South Sudan'],\n ['ES', 'Spain'],\n ['LK', 'Sri Lanka'],\n ['SD', 'Sudan'],\n ['SR', 'Suriname'],\n ['SE', 'Sweden'],\n ['CH', 'Switzerland'],\n ['SY', 'Syria'],\n ['TJ', 'Tajikistan'],\n ['TZ', 'Tanzania'],\n ['TH', 'Thailand'],\n ['TL', 'Timor-Leste'],\n ['TG', 'Togo'],\n ['TO', 'Tonga'],\n ['TT', 'Trinidad and Tobago'],\n ['TN', 'Tunisia'],\n ['TR', 'Turkey'],\n ['TM', 'Turkmenistan'],\n ['TV', 'Tuvalu'],\n ['UG', 'Uganda'],\n ['UA', 'Ukraine'],\n ['AE', 'United Arab Emirates'],\n ['GB', 'United Kingdom'],\n ['US', 'United States'],\n ['UY', 'Uruguay'],\n ['UZ', 'Uzbekistan'],\n ['VU', 'Vanuatu'],\n ['VE', 'Venezuela'],\n ['VN', 'Vietnam'],\n ['YE', 'Yemen'],\n ['ZM', 'Zambia'],\n ['ZW', 'Zimbabwe'],\n];\n\n// --- Stripe Element presentation ---------------------------------------------\n// A div that hosts a Stripe Element but reads like a Paragon input.\nexport const STRIPE_FIELD_STYLE: CSSProperties = {\n height: 'auto', minHeight: '2.875rem', display: 'flex', alignItems: 'center',\n};\nexport const STRIPE_ELEMENT_OPTS = {\n style: { base: { fontSize: '16px', color: '#1a1a1a', '::placeholder': { color: '#8f8f8f' } } },\n};\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * query/keys.ts — typed query-key factory for the checkout module.
3
+ */
4
+ export declare const checkoutKeys: {
5
+ all: readonly ["checkout"];
6
+ status: (cartBiId: string) => readonly ["checkout", "status", string];
7
+ clientSecret: (subscriptionId: string) => readonly ["checkout", "clientSecret", string];
8
+ subscriptionId: (cartBiId: string) => readonly ["checkout", "subscriptionId", string];
9
+ customer: (userEmail: string) => readonly ["checkout", "customer", string];
10
+ salable: (maId: string) => readonly ["checkout", "salable", string];
11
+ billingPlans: () => readonly ["checkout", "billingPlans"];
12
+ viaxSession: () => readonly ["checkout", "viaxSession"];
13
+ courseDetail: (courseKey: string) => readonly ["checkout", "courseDetail", string];
14
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * query/keys.ts — typed query-key factory for the checkout module.
3
+ */
4
+ export const checkoutKeys = {
5
+ all: ['checkout'],
6
+ status: (cartBiId) => ['checkout', 'status', cartBiId],
7
+ clientSecret: (subscriptionId) => ['checkout', 'clientSecret', subscriptionId],
8
+ subscriptionId: (cartBiId) => ['checkout', 'subscriptionId', cartBiId],
9
+ customer: (userEmail) => ['checkout', 'customer', userEmail],
10
+ salable: (maId) => ['checkout', 'salable', maId],
11
+ billingPlans: () => ['checkout', 'billingPlans'],
12
+ viaxSession: () => ['checkout', 'viaxSession'],
13
+ courseDetail: (courseKey) => ['checkout', 'courseDetail', courseKey],
14
+ };
15
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/data/hooks/keys.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,GAAG,EAAE,CAAC,UAAU,CAAU;IAC1B,MAAM,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAU;IACvE,YAAY,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,CAAU;IAC/F,cAAc,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,gBAAgB,EAAE,QAAQ,CAAU;IACvF,QAAQ,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAU;IAC7E,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,IAAI,CAAU;IACjE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE,cAAc,CAAU;IACzD,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE,aAAa,CAAU;IACvD,YAAY,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,CAAU;CACtF,CAAC","sourcesContent":["/**\n * query/keys.ts — typed query-key factory for the checkout module.\n */\nexport const checkoutKeys = {\n all: ['checkout'] as const,\n status: (cartBiId: string) => ['checkout', 'status', cartBiId] as const,\n clientSecret: (subscriptionId: string) => ['checkout', 'clientSecret', subscriptionId] as const,\n subscriptionId: (cartBiId: string) => ['checkout', 'subscriptionId', cartBiId] as const,\n customer: (userEmail: string) => ['checkout', 'customer', userEmail] as const,\n salable: (maId: string) => ['checkout', 'salable', maId] as const,\n billingPlans: () => ['checkout', 'billingPlans'] as const,\n viaxSession: () => ['checkout', 'viaxSession'] as const,\n courseDetail: (courseKey: string) => ['checkout', 'courseDetail', courseKey] as const,\n};\n"]}
@@ -0,0 +1,57 @@
1
+ import type { Ref } from 'react';
2
+ import type { BillingCycle } from '../../types';
3
+ import type { Status, Phase, BillingInfo, BillingPlan, CheckoutConsent } from '../../types';
4
+ export interface UseCheckoutOptions {
5
+ apiUrl?: string;
6
+ edxSessionUrl?: string;
7
+ stripePublishableKey?: string;
8
+ onComplete?: (subscriptionBiId: string | null) => void;
9
+ /** Country code resolved by CheckoutGate — used to show/hide the UK/CA extra checkbox. */
10
+ userCountry?: string | null;
11
+ /**
12
+ * Course run key from the URL (e.g. course-v1:HarvardX+CS50+X).
13
+ * When omitted, read from ?course_run_key=.
14
+ */
15
+ courseRunKey?: string | null;
16
+ }
17
+ export interface UseCheckoutResult {
18
+ phase: Phase;
19
+ status: Status | null;
20
+ statusLabel: string;
21
+ stripeReady: boolean;
22
+ /** True once the Stripe card Element iframe is fully initialised and interactive. */
23
+ cardReady: boolean;
24
+ notConfigured: boolean;
25
+ showBanner: boolean;
26
+ dismissBanner: () => void;
27
+ error: string;
28
+ clearError: () => void;
29
+ cardError: string;
30
+ lastComment: string;
31
+ /** Full subscription details including card last 4 — available after SUBSCRIPTION_CREATED. */
32
+ subscriptionDetails: import('../../types').SubscriptionDetails | null;
33
+ billing: BillingInfo;
34
+ setField: (field: keyof BillingInfo, value: string) => void;
35
+ numberMountRef: Ref<HTMLDivElement>;
36
+ expiryMountRef: Ref<HTMLDivElement>;
37
+ cvcMountRef: Ref<HTMLDivElement>;
38
+ submitting: boolean;
39
+ /** True from Place order click until a terminal status is reached. */
40
+ processingSubscription: boolean;
41
+ placeOrder: (consent: CheckoutConsent) => void;
42
+ /** Billing plans fetched on mount — includes prices for display in CartSummary. */
43
+ billingPlans: BillingPlan[];
44
+ /** Live active subscriber count for display in CartSummary. */
45
+ activeSubscriberCount: number | null;
46
+ /** Currently selected billing cycle. */
47
+ selectedCycle: BillingCycle;
48
+ /** Switch between monthly and annual billing. */
49
+ setCycle: (cycle: BillingCycle) => void;
50
+ /** True once GET /edx-session has returned and the viax token is set. */
51
+ sessionReady: boolean;
52
+ /** ISO 3166-1 alpha-2 country code — passed in from CheckoutGate for the UK/CA checkbox. */
53
+ userCountry: string | null;
54
+ /** Course details when arrived via ?course_run_key=; null for standard checkout. */
55
+ course: import('../../types').CourseDetail | null;
56
+ }
57
+ export default function useCheckout(options?: UseCheckoutOptions): UseCheckoutResult;
@@ -0,0 +1,249 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
11
+ import { createCheckoutClient } from '../../utils/checkout';
12
+ import { loadStripe } from '../../utils/stripe';
13
+ import { STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS, } from '../../constants';
14
+ import { useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery, useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery, } from './useCheckoutQueries';
15
+ import { useCheckoutMutations } from './useCheckoutMutations';
16
+ /**
17
+ * Read ?course_run_key= from the current URL.
18
+ * Avoid URLSearchParams — it treats bare `+` as a space, which would turn
19
+ * HarvardX+CS50+X into "HarvardX CS50 X". decodeURIComponent keeps `+` intact.
20
+ */
21
+ function getCourseRunKeyFromUrl() {
22
+ if (typeof window === 'undefined')
23
+ return null;
24
+ const match = /[?&]course_run_key=([^&]*)/.exec(window.location.search);
25
+ if (!match)
26
+ return null;
27
+ try {
28
+ // Preserve literal `+` (treat as %2B) then decode %XX sequences.
29
+ return decodeURIComponent(match[1].replace(/\+/g, '%2B')).trim() || null;
30
+ }
31
+ catch (_a) {
32
+ return match[1].trim() || null;
33
+ }
34
+ }
35
+ export default function useCheckout(options = {}) {
36
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
37
+ const { apiUrl = DEFAULTS.apiUrl, edxSessionUrl, stripePublishableKey, onComplete, userCountry = null, courseRunKey: courseRunKeyProp, } = options;
38
+ const courseRunKey = useMemo(() => courseRunKeyProp !== null && courseRunKeyProp !== void 0 ? courseRunKeyProp : getCourseRunKeyFromUrl(), [courseRunKeyProp]);
39
+ const client = useMemo(() => {
40
+ if (!apiUrl)
41
+ return null;
42
+ return createCheckoutClient({ apiUrl });
43
+ }, [apiUrl]);
44
+ const notConfigured = !client || !stripePublishableKey || !edxSessionUrl;
45
+ // Exchange edX session for viax token on page load.
46
+ const sessionQuery = useViaxSessionQuery(notConfigured ? null : edxSessionUrl);
47
+ const sessionReady = !!sessionQuery.data;
48
+ useEffect(() => {
49
+ if (sessionQuery.data && client) {
50
+ client.setToken(sessionQuery.data.viaxToken);
51
+ }
52
+ }, [sessionQuery.data, client]);
53
+ // Fetch billing plans, subscriber count, and optional course once the viax session is ready.
54
+ const billingPlansQuery = useBillingPlansQuery(client, sessionReady);
55
+ const activeSubscriptionsQuery = useActiveSubscriptionsQuery(client, sessionReady);
56
+ const courseDetailQuery = useCourseDetailQuery(client, sessionReady, courseRunKey);
57
+ // --- state ---
58
+ const [showBanner, setShowBanner] = useState(true);
59
+ const [cart, setCart] = useState(null);
60
+ const [stripe, setStripe] = useState(null);
61
+ const [stripeReady, setStripeReady] = useState(false);
62
+ const [cardReady, setCardReady] = useState(false);
63
+ const [error, setError] = useState('');
64
+ const [cardError, setCardError] = useState('');
65
+ const [billing, setBilling] = useState({
66
+ firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',
67
+ });
68
+ const [selectedCycle, setSelectedCycle] = useState('monthly');
69
+ const [processingSubscription, setProcessingSubscription] = useState(false);
70
+ useEffect(() => {
71
+ if (sessionQuery.error) {
72
+ setError(sessionQuery.error.message);
73
+ }
74
+ }, [sessionQuery.error]);
75
+ const setField = useCallback((field, value) => setBilling((p) => (Object.assign(Object.assign({}, p), { [field]: value }))), []);
76
+ // --- refs ---
77
+ // Stripe instances — written inside useEffect and mutations.
78
+ const stripeInstanceRef = useRef(null);
79
+ const cardNumberElementRef = useRef(null);
80
+ const elementsRef = useRef(null);
81
+ const elementsMountedRef = useRef(false);
82
+ // DOM mount targets — passed as ref={} to the Stripe Element host divs.
83
+ const numberMountRef = useRef(null);
84
+ const expiryMountRef = useRef(null);
85
+ const cvcMountRef = useRef(null);
86
+ const mountedRef = useRef(true);
87
+ const completedRef = useRef(false);
88
+ const sessionRef = useRef(null);
89
+ useEffect(() => {
90
+ var _a;
91
+ sessionRef.current = (_a = sessionQuery.data) !== null && _a !== void 0 ? _a : null;
92
+ }, [sessionQuery.data]);
93
+ // Mirror state into refs so mutations can read current values without stale closures.
94
+ const cartRef = useRef(null);
95
+ const billingRef = useRef(billing);
96
+ useEffect(() => {
97
+ cartRef.current = cart;
98
+ }, [cart]);
99
+ useEffect(() => {
100
+ billingRef.current = billing;
101
+ }, [billing]);
102
+ useEffect(() => {
103
+ stripeInstanceRef.current = stripe;
104
+ }, [stripe]);
105
+ // --- server state ---
106
+ const statusQuery = useCartStatusQuery(client, (_a = cart === null || cart === void 0 ? void 0 : cart.biId) !== null && _a !== void 0 ? _a : null);
107
+ const status = (_c = (_b = statusQuery.data) === null || _b === void 0 ? void 0 : _b.status) !== null && _c !== void 0 ? _c : null;
108
+ const lastComment = (_e = (_d = statusQuery.data) === null || _d === void 0 ? void 0 : _d.lastComment) !== null && _e !== void 0 ? _e : '';
109
+ // Phase is 'ready' until a cart exists, then driven by bpStatus.
110
+ const phase = cart ? phaseFor(status, status === STATUS.IN_CART) : 'ready';
111
+ const subscriptionIdQuery = useSubscriptionIdQuery(client, (_f = cart === null || cart === void 0 ? void 0 : cart.biId) !== null && _f !== void 0 ? _f : null, status === STATUS.SUBSCRIPTION_CREATED);
112
+ // --- mutations ---
113
+ const { placeOrder: placeMutation } = useCheckoutMutations({
114
+ client,
115
+ sessionRef,
116
+ stripeRef: stripeInstanceRef,
117
+ cardNumberElRef: cardNumberElementRef,
118
+ billingRef,
119
+ setError: (msg) => {
120
+ setProcessingSubscription(false);
121
+ setError(msg);
122
+ },
123
+ setCardError: (msg) => {
124
+ setProcessingSubscription(false);
125
+ setCardError(msg);
126
+ },
127
+ onCartCreated: (created) => {
128
+ // Sync the ref immediately so any same-tick readers see the cart
129
+ // before the setCart → useEffect mirror runs.
130
+ cartRef.current = created;
131
+ if (mountedRef.current)
132
+ setCart(created);
133
+ },
134
+ });
135
+ // --- load Stripe.js on mount ---
136
+ useEffect(() => {
137
+ mountedRef.current = true;
138
+ if (!stripePublishableKey)
139
+ return undefined;
140
+ (() => __awaiter(this, void 0, void 0, function* () {
141
+ try {
142
+ const instance = yield loadStripe(stripePublishableKey);
143
+ if (mountedRef.current) {
144
+ setStripe(instance);
145
+ setStripeReady(true);
146
+ }
147
+ }
148
+ catch (e) {
149
+ if (mountedRef.current)
150
+ setError(e.message);
151
+ }
152
+ }))();
153
+ return () => {
154
+ mountedRef.current = false;
155
+ };
156
+ }, [stripePublishableKey]);
157
+ // --- mount Stripe Elements once Stripe is loaded ---
158
+ useEffect(() => {
159
+ if (!stripe)
160
+ return;
161
+ if (!numberMountRef.current || !expiryMountRef.current || !cvcMountRef.current)
162
+ return;
163
+ // Hard guard — never recreate elements once mounted, even if stripe reference changes.
164
+ if (elementsMountedRef.current)
165
+ return;
166
+ elementsMountedRef.current = true;
167
+ setCardReady(false);
168
+ const elements = stripe.elements();
169
+ elementsRef.current = elements;
170
+ const number = elements.create('cardNumber', Object.assign(Object.assign({}, STRIPE_ELEMENT_OPTS), { showIcon: true }));
171
+ const expiry = elements.create('cardExpiry', STRIPE_ELEMENT_OPTS);
172
+ const cvc = elements.create('cardCvc', STRIPE_ELEMENT_OPTS);
173
+ number.mount(numberMountRef.current);
174
+ expiry.mount(expiryMountRef.current);
175
+ cvc.mount(cvcMountRef.current);
176
+ number.on('ready', () => {
177
+ if (mountedRef.current)
178
+ setCardReady(true);
179
+ });
180
+ number.on('change', (e) => {
181
+ var _a;
182
+ if (mountedRef.current)
183
+ setCardError(((_a = e.error) === null || _a === void 0 ? void 0 : _a.message) || '');
184
+ });
185
+ cardNumberElementRef.current = number;
186
+ }, [stripe]);
187
+ // --- on success ---
188
+ useEffect(() => {
189
+ var _a, _b;
190
+ if (status !== STATUS.SUBSCRIPTION_CREATED || completedRef.current)
191
+ return;
192
+ completedRef.current = true;
193
+ if (onComplete)
194
+ onComplete((_b = (_a = subscriptionIdQuery.data) === null || _a === void 0 ? void 0 : _a.biId) !== null && _b !== void 0 ? _b : null);
195
+ }, [status, subscriptionIdQuery.data, onComplete]);
196
+ // --- actions ---
197
+ const placeOrder = useCallback((consent) => {
198
+ setError('');
199
+ setCardError('');
200
+ if (phase === 'failed')
201
+ setCart(null);
202
+ setProcessingSubscription(true);
203
+ placeMutation.mutate(consent);
204
+ }, [placeMutation, phase]);
205
+ // Turn off processingSubscription once we reach a terminal status.
206
+ useEffect(() => {
207
+ if (!status)
208
+ return;
209
+ const terminalStatuses = [
210
+ STATUS.SUBSCRIPTION_CREATED,
211
+ STATUS.STRIPE_FAIL,
212
+ STATUS.SANCTION_BLOCK,
213
+ ];
214
+ if (terminalStatuses.includes(status)) {
215
+ setProcessingSubscription(false);
216
+ }
217
+ }, [status]);
218
+ return {
219
+ phase,
220
+ status,
221
+ statusLabel: (status && STATUS_LABELS[status]) || 'Processing your order…',
222
+ stripeReady,
223
+ cardReady,
224
+ notConfigured,
225
+ showBanner,
226
+ dismissBanner: () => setShowBanner(false),
227
+ error,
228
+ clearError: () => setError(''),
229
+ cardError,
230
+ lastComment,
231
+ subscriptionDetails: (_g = subscriptionIdQuery.data) !== null && _g !== void 0 ? _g : null,
232
+ billing,
233
+ setField,
234
+ numberMountRef,
235
+ expiryMountRef,
236
+ cvcMountRef,
237
+ submitting: placeMutation.isPending,
238
+ processingSubscription,
239
+ placeOrder,
240
+ billingPlans: (_j = (_h = billingPlansQuery.data) === null || _h === void 0 ? void 0 : _h.plans) !== null && _j !== void 0 ? _j : [],
241
+ activeSubscriberCount: (_l = (_k = activeSubscriptionsQuery.data) === null || _k === void 0 ? void 0 : _k.active) !== null && _l !== void 0 ? _l : null,
242
+ selectedCycle,
243
+ setCycle: setSelectedCycle,
244
+ sessionReady,
245
+ userCountry,
246
+ course: (_m = courseDetailQuery.data) !== null && _m !== void 0 ? _m : null,
247
+ };
248
+ }
249
+ //# sourceMappingURL=useCheckout.js.map