@edx/frontend-app-alacarte-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 (166) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +2 -0
  3. package/README.rst +235 -0
  4. package/dist/Main.d.ts +3 -0
  5. package/dist/Main.js +15 -0
  6. package/dist/Main.js.map +1 -0
  7. package/dist/app.d.ts +3 -0
  8. package/dist/app.js +12 -0
  9. package/dist/app.js.map +1 -0
  10. package/dist/checkoutPage/CheckoutPage.d.ts +3 -0
  11. package/dist/checkoutPage/CheckoutPage.js +26 -0
  12. package/dist/checkoutPage/CheckoutPage.js.map +1 -0
  13. package/dist/components/BrandMarks/BrandMarks.d.ts +7 -0
  14. package/dist/components/BrandMarks/BrandMarks.js +9 -0
  15. package/dist/components/BrandMarks/BrandMarks.js.map +1 -0
  16. package/dist/components/CartSummary/CartSummary.d.ts +26 -0
  17. package/dist/components/CartSummary/CartSummary.js +41 -0
  18. package/dist/components/CartSummary/CartSummary.js.map +1 -0
  19. package/dist/components/CartSummary/Messages.d.ts +103 -0
  20. package/dist/components/CartSummary/Messages.js +106 -0
  21. package/dist/components/CartSummary/Messages.js.map +1 -0
  22. package/dist/components/Checkout/Checkout.d.ts +9 -0
  23. package/dist/components/Checkout/Checkout.js +82 -0
  24. package/dist/components/Checkout/Checkout.js.map +1 -0
  25. package/dist/components/Checkout/Messages.d.ts +8 -0
  26. package/dist/components/Checkout/Messages.js +10 -0
  27. package/dist/components/Checkout/Messages.js.map +1 -0
  28. package/dist/components/CheckoutGate/CheckoutGate.d.ts +9 -0
  29. package/dist/components/CheckoutGate/CheckoutGate.js +40 -0
  30. package/dist/components/CheckoutGate/CheckoutGate.js.map +1 -0
  31. package/dist/components/CheckoutGate/Messages.d.ts +8 -0
  32. package/dist/components/CheckoutGate/Messages.js +10 -0
  33. package/dist/components/CheckoutGate/Messages.js.map +1 -0
  34. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.d.ts +9 -0
  35. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.js +10 -0
  36. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.js.map +1 -0
  37. package/dist/components/CountryUnavailableModal/Messages.d.ts +18 -0
  38. package/dist/components/CountryUnavailableModal/Messages.js +20 -0
  39. package/dist/components/CountryUnavailableModal/Messages.js.map +1 -0
  40. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +9 -0
  41. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +31 -0
  42. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +1 -0
  43. package/dist/components/CourseEnrollmentCard/Messages.d.ts +33 -0
  44. package/dist/components/CourseEnrollmentCard/Messages.js +35 -0
  45. package/dist/components/CourseEnrollmentCard/Messages.js.map +1 -0
  46. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.d.ts +13 -0
  47. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js +11 -0
  48. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js.map +1 -0
  49. package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +22 -0
  50. package/dist/components/EnrollmentSummary/EnrollmentSummary.js +33 -0
  51. package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -0
  52. package/dist/components/EnrollmentSummary/Messages.d.ts +48 -0
  53. package/dist/components/EnrollmentSummary/Messages.js +50 -0
  54. package/dist/components/EnrollmentSummary/Messages.js.map +1 -0
  55. package/dist/components/PaymentFields/PaymentFields.d.ts +9 -0
  56. package/dist/components/PaymentFields/PaymentFields.js +7 -0
  57. package/dist/components/PaymentFields/PaymentFields.js.map +1 -0
  58. package/dist/components/PaymentForm/Messages.d.ts +118 -0
  59. package/dist/components/PaymentForm/Messages.js +125 -0
  60. package/dist/components/PaymentForm/Messages.js.map +1 -0
  61. package/dist/components/PaymentForm/PaymentForm.d.ts +28 -0
  62. package/dist/components/PaymentForm/PaymentForm.js +121 -0
  63. package/dist/components/PaymentForm/PaymentForm.js.map +1 -0
  64. package/dist/components/StatusScreens/Messages.d.ts +108 -0
  65. package/dist/components/StatusScreens/Messages.js +114 -0
  66. package/dist/components/StatusScreens/Messages.js.map +1 -0
  67. package/dist/components/StatusScreens/StatusScreens.d.ts +24 -0
  68. package/dist/components/StatusScreens/StatusScreens.js +32 -0
  69. package/dist/components/StatusScreens/StatusScreens.js.map +1 -0
  70. package/dist/constants.d.ts +59 -0
  71. package/dist/constants.js +282 -0
  72. package/dist/constants.js.map +1 -0
  73. package/dist/data/hooks/keys.d.ts +14 -0
  74. package/dist/data/hooks/keys.js +15 -0
  75. package/dist/data/hooks/keys.js.map +1 -0
  76. package/dist/data/hooks/useCheckout.d.ts +61 -0
  77. package/dist/data/hooks/useCheckout.js +343 -0
  78. package/dist/data/hooks/useCheckout.js.map +1 -0
  79. package/dist/data/hooks/useCheckoutGate.d.ts +16 -0
  80. package/dist/data/hooks/useCheckoutGate.js +61 -0
  81. package/dist/data/hooks/useCheckoutGate.js.map +1 -0
  82. package/dist/data/hooks/useCheckoutMutations.d.ts +22 -0
  83. package/dist/data/hooks/useCheckoutMutations.js +166 -0
  84. package/dist/data/hooks/useCheckoutMutations.js.map +1 -0
  85. package/dist/data/hooks/useCheckoutQueries.d.ts +32 -0
  86. package/dist/data/hooks/useCheckoutQueries.js +107 -0
  87. package/dist/data/hooks/useCheckoutQueries.js.map +1 -0
  88. package/dist/data/services/subs/urls.d.ts +2 -0
  89. package/dist/data/services/subs/urls.js +4 -0
  90. package/dist/data/services/subs/urls.js.map +1 -0
  91. package/dist/i18n/index.d.ts +1 -0
  92. package/dist/i18n/index.js +2 -0
  93. package/dist/i18n/index.js.map +1 -0
  94. package/dist/index.d.ts +2 -0
  95. package/dist/index.js +3 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/messages.d.ts +8 -0
  98. package/dist/messages.js +10 -0
  99. package/dist/messages.js.map +1 -0
  100. package/dist/routes.d.ts +18 -0
  101. package/dist/routes.js +47 -0
  102. package/dist/routes.js.map +1 -0
  103. package/dist/slots/ExampleSlot/ExampleSlot.d.ts +3 -0
  104. package/dist/slots/ExampleSlot/ExampleSlot.js +6 -0
  105. package/dist/slots/ExampleSlot/ExampleSlot.js.map +1 -0
  106. package/dist/slots.d.ts +3 -0
  107. package/dist/slots.js +3 -0
  108. package/dist/slots.js.map +1 -0
  109. package/dist/style.scss +14 -0
  110. package/dist/styles/components/brandMarks.scss +41 -0
  111. package/dist/styles/components/cartSummary.scss +29 -0
  112. package/dist/styles/components/checkout.scss +29 -0
  113. package/dist/styles/components/checkoutStepper.scss +9 -0
  114. package/dist/styles/components/courseEnrollmentCard.scss +38 -0
  115. package/dist/styles/components/edxUnlimitedBanner.scss +138 -0
  116. package/dist/styles/components/enrollmentSummary.scss +19 -0
  117. package/dist/styles/components/paymentFields.scss +15 -0
  118. package/dist/styles/components/paymentForm.scss +139 -0
  119. package/dist/styles/components/statusScreens.scss +39 -0
  120. package/dist/styles/components/successScreen.scss +0 -0
  121. package/dist/types.d.ts +232 -0
  122. package/dist/types.js +2 -0
  123. package/dist/types.js.map +1 -0
  124. package/dist/utils/auth.d.ts +7 -0
  125. package/dist/utils/auth.js +28 -0
  126. package/dist/utils/auth.js.map +1 -0
  127. package/dist/utils/billingDetails.d.ts +30 -0
  128. package/dist/utils/billingDetails.js +48 -0
  129. package/dist/utils/billingDetails.js.map +1 -0
  130. package/dist/utils/bootstrapApi.d.ts +20 -0
  131. package/dist/utils/bootstrapApi.js +142 -0
  132. package/dist/utils/bootstrapApi.js.map +1 -0
  133. package/dist/utils/cartApi.d.ts +16 -0
  134. package/dist/utils/cartApi.js +133 -0
  135. package/dist/utils/cartApi.js.map +1 -0
  136. package/dist/utils/checkout.d.ts +6 -0
  137. package/dist/utils/checkout.js +28 -0
  138. package/dist/utils/checkout.js.map +1 -0
  139. package/dist/utils/checkoutErrors.d.ts +1 -0
  140. package/dist/utils/checkoutErrors.js +11 -0
  141. package/dist/utils/checkoutErrors.js.map +1 -0
  142. package/dist/utils/fetchActiveSubscriptions.d.ts +4 -0
  143. package/dist/utils/fetchActiveSubscriptions.js +36 -0
  144. package/dist/utils/fetchActiveSubscriptions.js.map +1 -0
  145. package/dist/utils/fetchBillingPlans.d.ts +2 -0
  146. package/dist/utils/fetchBillingPlans.js +48 -0
  147. package/dist/utils/fetchBillingPlans.js.map +1 -0
  148. package/dist/utils/graphqlClient.d.ts +16 -0
  149. package/dist/utils/graphqlClient.js +39 -0
  150. package/dist/utils/graphqlClient.js.map +1 -0
  151. package/dist/utils/index.d.ts +3 -0
  152. package/dist/utils/index.js +17 -0
  153. package/dist/utils/index.js.map +1 -0
  154. package/dist/utils/planQuery.d.ts +16 -0
  155. package/dist/utils/planQuery.js +57 -0
  156. package/dist/utils/planQuery.js.map +1 -0
  157. package/dist/utils/provision.d.ts +48 -0
  158. package/dist/utils/provision.js +161 -0
  159. package/dist/utils/provision.js.map +1 -0
  160. package/dist/utils/queries.d.ts +35 -0
  161. package/dist/utils/queries.js +168 -0
  162. package/dist/utils/queries.js.map +1 -0
  163. package/dist/utils/stripe.d.ts +23 -0
  164. package/dist/utils/stripe.js +86 -0
  165. package/dist/utils/stripe.js.map +1 -0
  166. package/package.json +85 -0
@@ -0,0 +1,9 @@
1
+ .checkout__stepper {
2
+ > div {
3
+ padding:0;
4
+
5
+ ul.pgn__stepper-header-step-list {
6
+ justify-content: flex-start;
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,38 @@
1
+ .course-enrollment-card {
2
+ margin-top: 1.25rem;
3
+ padding: 1rem;
4
+ background: var(--pgn-color-white, #fff);
5
+ border: 1px solid var(--pgn-color-light-400, #e5e5e5);
6
+ border-radius: var(--pgn-size-border-radius-base, 0.375rem);
7
+
8
+ &__image {
9
+ display: block;
10
+ width: 4.5rem;
11
+ height: 3.25rem;
12
+ object-fit: cover;
13
+ border-radius: 0.25rem;
14
+ background: var(--pgn-color-light-300, #f2f2f2);
15
+
16
+ &--placeholder {
17
+ background:
18
+ linear-gradient(
19
+ to top right,
20
+ transparent calc(50% - 1px),
21
+ var(--pgn-color-light-500, #c2c2c2) 50%,
22
+ transparent calc(50% + 1px)
23
+ ),
24
+ linear-gradient(
25
+ to top left,
26
+ transparent calc(50% - 1px),
27
+ var(--pgn-color-light-500, #c2c2c2) 50%,
28
+ transparent calc(50% + 1px)
29
+ ),
30
+ var(--pgn-color-light-300, #f2f2f2);
31
+ }
32
+ }
33
+
34
+ &__copy {
35
+ color: var(--pgn-color-gray-900, #212529);
36
+ line-height: 1.4;
37
+ }
38
+ }
@@ -0,0 +1,138 @@
1
+
2
+ .edx-banner {
3
+ background: #0a1628;
4
+ border-radius: 10px;
5
+ overflow: hidden;
6
+ display: flex;
7
+ align-items: stretch;
8
+ min-height: 120px;
9
+ position: relative;
10
+
11
+ &__content {
12
+ flex: 1 1 0;
13
+ padding: 28px 32px 28px 28px;
14
+ display: flex;
15
+ flex-direction: column;
16
+ justify-content: center;
17
+ gap: 10px;
18
+ z-index: 1;
19
+ }
20
+
21
+ &__eyebrow {
22
+ display: flex;
23
+ align-items: center;
24
+ }
25
+
26
+ &__headline {
27
+ margin: 0;
28
+ color: #fff;
29
+ font-size: clamp(1.1rem, 2.2vw, 1.55rem);
30
+ font-weight: 700;
31
+ line-height: 1.25;
32
+ letter-spacing: -0.01em;
33
+ }
34
+
35
+ &__body {
36
+ margin: 0;
37
+ color: rgba(255, 255, 255, 0.78);
38
+ font-size: clamp(0.78rem, 1.3vw, 0.88rem);
39
+ line-height: 1.55;
40
+ max-width: 540px;
41
+ }
42
+
43
+ &__cta-wrapper {
44
+ margin-top: 4px;
45
+ }
46
+
47
+ &__cta {
48
+ display: inline-block;
49
+ background: #e2522a;
50
+ color: #fff;
51
+ font-weight: 700;
52
+ font-size: 0.82rem;
53
+ padding: 9px 20px;
54
+ border-radius: 6px;
55
+ text-decoration: none;
56
+ letter-spacing: 0.01em;
57
+ transition: background 0.15s;
58
+ white-space: nowrap;
59
+
60
+ &:hover {
61
+ background: #c94420;
62
+ color: #fff;
63
+ text-decoration: none;
64
+ }
65
+ }
66
+
67
+ &__bullet {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ width: 28px;
72
+ height: 28px;
73
+ border-radius: 50%;
74
+ background: rgba(255, 255, 255, 0.15);
75
+ flex-shrink: 0;
76
+ margin-right: 10px;
77
+ }
78
+
79
+ &__badge {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ gap: 0;
83
+ vertical-align: middle;
84
+ position: relative;
85
+ top: -2px;
86
+ }
87
+
88
+ &__badge-edx {
89
+ background: #fff;
90
+ border-radius: 4px 0 0 4px;
91
+ padding: 2px 5px 2px 6px;
92
+ font-weight: 800;
93
+ font-size: 0.78em;
94
+ letter-spacing: -0.02em;
95
+ color: #000;
96
+ line-height: 1.15;
97
+ font-style: normal;
98
+ }
99
+
100
+ &__badge-unlimited {
101
+ background: #000;
102
+ border-radius: 0 4px 4px 0;
103
+ padding: 2px 6px 2px 4px;
104
+ font-weight: 600;
105
+ font-size: 0.64em;
106
+ letter-spacing: 0.02em;
107
+ color: #c5b8ff;
108
+ line-height: 1.15;
109
+ font-style: normal;
110
+ text-transform: lowercase;
111
+ }
112
+
113
+ &__photo {
114
+ flex-shrink: 0;
115
+ width: clamp(120px, 22%, 240px);
116
+ position: relative;
117
+ overflow: hidden;
118
+
119
+ img {
120
+ position: absolute;
121
+ inset: 0;
122
+ width: 100%;
123
+ height: 100%;
124
+ object-fit: cover;
125
+ object-position: center top;
126
+ }
127
+ }
128
+
129
+
130
+ &__placeholder {
131
+ flex-shrink: 0;
132
+ width: clamp(100px, 20%, 200px);
133
+ background: rgba(255, 255, 255, 0.06);
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ }
138
+ }
@@ -0,0 +1,19 @@
1
+ .enrollment-summary {
2
+ &__pricing {
3
+ line-height: 1.35;
4
+ }
5
+ }
6
+
7
+ .enrolled__banner {
8
+ div:first-child {
9
+ border-top-left-radius: var(--pgn-size-border-radius-base);
10
+ border-top-right-radius: var(--pgn-size-border-radius-base);
11
+ }
12
+
13
+ div:last-child {
14
+ border: 1px solid var(--pgn-color-light-400);
15
+ border-top: 0;
16
+ border-bottom-left-radius: var(--pgn-size-border-radius-base);
17
+ border-bottom-right-radius: var(--pgn-size-border-radius-base);
18
+ }
19
+ }
@@ -0,0 +1,15 @@
1
+ .payment--field {
2
+ .card__expiry,
3
+ .card__cvc {
4
+ width: 10.75rem;
5
+ }
6
+
7
+ .form-control {
8
+ border-radius: 5px;
9
+ border: 1px solid #E6E6E6;
10
+ background: #FFF;
11
+
12
+ /* default/box-shadow-default */
13
+ box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.02), 0 1px 1px 0 rgba(0, 0, 0, 0.03);
14
+ }
15
+ }
@@ -0,0 +1,139 @@
1
+ // styles/components/paymentForm.scss
2
+
3
+ .payment-form {
4
+ &__heading {
5
+ font-size: 1.1rem;
6
+ }
7
+
8
+ &__help {
9
+ a {
10
+ text-decoration: underline;
11
+ text-underline-offset: 0.2rem;
12
+ }
13
+ }
14
+
15
+ // ── Payment method accordion ─────────────────────────────────────────────
16
+
17
+ &__method {
18
+ border-radius: 8px;
19
+ border: 1px solid #E7E9EF;
20
+ background: #FFF;
21
+ overflow: hidden;
22
+ background: #F6F8FA;
23
+ &--selected {
24
+ background-color: white;
25
+ }
26
+
27
+ &--hidden {
28
+ display: none;
29
+ }
30
+ }
31
+
32
+ // Header row: radio + icon(s) + name — full-width clickable label
33
+ &__method-header {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.6rem;
37
+ padding: 0.9rem 1rem;
38
+ margin: 0;
39
+ cursor: pointer;
40
+ width: 100%;
41
+ font-weight: 600;
42
+ font-size: 0.95rem;
43
+ }
44
+
45
+ &__radio {
46
+ flex-shrink: 0;
47
+ width: 1.1rem;
48
+ height: 1.1rem;
49
+ accent-color: #000000;
50
+ cursor: pointer;
51
+ }
52
+
53
+ &__method-name {
54
+ flex: 1;
55
+ }
56
+
57
+ // Expanded card panel — no extra heading, just fields
58
+ &__card-panel {
59
+ padding: 0 1rem 1rem;
60
+ background: #fff;
61
+
62
+ // Hide without unmounting. Stripe Elements die if their host nodes leave the DOM.
63
+ // Avoid display:none so the iframes keep a layout box and stay interactive.
64
+ &--collapsed {
65
+ visibility: hidden;
66
+ max-height: 0;
67
+ padding: 0;
68
+ overflow: hidden;
69
+ pointer-events: none;
70
+ }
71
+ }
72
+
73
+ // Icon badges for Google Pay / PayPal
74
+ &__method-icon {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+ width: 1.5rem;
79
+ height: 1.5rem;
80
+ border-radius: 4px;
81
+ color: #fff;
82
+ font-weight: 800;
83
+ font-size: 0.7rem;
84
+ flex-shrink: 0;
85
+
86
+ &--gpay {
87
+ background: #4285f4;
88
+ }
89
+
90
+ &--paypal {
91
+ background: #003087;
92
+ }
93
+ }
94
+
95
+ .payment__field--country {
96
+ select {
97
+ border-radius: 5px;
98
+ border: 1px solid #E6E6E6;
99
+ box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.02), 0 1px 1px 0 rgba(0, 0, 0, 0.03);
100
+ }
101
+ }
102
+
103
+ // ── Submit button ────────────────────────────────────────────────────────
104
+ &__submit {
105
+ border-radius: 2rem;
106
+ font-weight: 700;
107
+ padding: 0.75rem 1.5rem;
108
+ }
109
+
110
+ &__terms {
111
+ line-height: 1.6;
112
+ }
113
+
114
+ &__confirm {
115
+ .pgn__form-checkbox {
116
+ align-items: flex-start;
117
+ }
118
+
119
+ // Paragon pins the label line-height to the checkbox size; let the
120
+ // copy wrap with its own leading instead.
121
+ .pgn__form-label {
122
+ display: block;
123
+ line-height: 1.6;
124
+ // Cancel half-leading above the first line and below the last so
125
+ // extra space only appears between wrapped lines.
126
+ margin-block: calc((1em - 1lh) / 2);
127
+ }
128
+ }
129
+
130
+ &__confirm-label {
131
+ line-height: inherit;
132
+ }
133
+ }
134
+
135
+ @media (--pgn-size-breakpoint-min-width-lg) {
136
+ .payment-form {
137
+ padding: 32px;
138
+ }
139
+ }
@@ -0,0 +1,39 @@
1
+ // styles/components/successScreen.scss
2
+
3
+ .processing-screen {
4
+ position: fixed;
5
+ inset: 0;
6
+ z-index: 1050;
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ background-color: var(--pgn-color-light-200, #f8f9fa);
11
+ }
12
+
13
+ .success-screen {
14
+ &__headline {
15
+ font-size: clamp(1.6rem, 3vw, 2.2rem);
16
+ color: #1a3a2a; // dark green as in design
17
+ }
18
+
19
+ &__ctas {
20
+ flex-wrap: wrap;
21
+ gap: 0.75rem;
22
+ }
23
+
24
+ &__cta-primary {
25
+ border-radius: 2rem;
26
+ font-weight: 700;
27
+ padding: 0.65rem 1.5rem;
28
+ }
29
+
30
+ &__benefits {
31
+ list-style: disc;
32
+ padding-left: 1.25rem;
33
+
34
+ li {
35
+ color: var(--gray-700, #495057);
36
+ line-height: 1.6;
37
+ }
38
+ }
39
+ }
File without changes
@@ -0,0 +1,232 @@
1
+ import type { Status, Phase } from './constants';
2
+ export type { Status, Phase };
3
+ export interface TwouCustomerContact {
4
+ email?: string;
5
+ }
6
+ export interface TwouCustomerParty {
7
+ paName: string;
8
+ indFirstName?: string;
9
+ indLastName?: string;
10
+ paContacts: {
11
+ edges: {
12
+ node: TwouCustomerContact;
13
+ }[];
14
+ };
15
+ }
16
+ export interface TwouCustomer {
17
+ uid: string;
18
+ parId: string;
19
+ parParty: TwouCustomerParty;
20
+ }
21
+ export type GqlRunner = (query: string, variables?: Record<string, unknown>, retry?: boolean) => Promise<any>;
22
+ export interface Cart {
23
+ biId: string;
24
+ uid: string;
25
+ }
26
+ export interface CartIds {
27
+ customerUid: string;
28
+ salableUid: string;
29
+ billingPlanUid: string;
30
+ }
31
+ export type BillingCycle = 'monthly' | 'annual';
32
+ export type PaymentMethod = 'card' | 'googlepay' | 'paypal';
33
+ export type SupportedPaymentMethod = Exclude<PaymentMethod, 'googlepay'>;
34
+ export type BillingPeriod = 'MONTHLY' | 'ANNUAL' | 'QUARTERLY' | string;
35
+ export interface BillingPlanOwnershipModel {
36
+ uid: string;
37
+ omName: string;
38
+ }
39
+ export interface BillingPlan {
40
+ uid: string;
41
+ stripePriceId: string;
42
+ /** Price amount e.g. "39.99" */
43
+ amount: string;
44
+ /** Currency code e.g. "USD" */
45
+ currency: string;
46
+ isTemplate: boolean;
47
+ ownershipModel: BillingPlanOwnershipModel;
48
+ }
49
+ export interface SubscriptionDetails {
50
+ biId: string;
51
+ trialStart: string | null;
52
+ trialEnd: string | null;
53
+ renewalType: string | null;
54
+ cardLast4: string | null;
55
+ cardBrand: string | null;
56
+ stripePaymentMethodId: string | null;
57
+ planName: string | null;
58
+ }
59
+ export interface CurrentUserSubscriberResult {
60
+ isSubscriber: boolean;
61
+ subscriptionBiId: string | null;
62
+ status: string | null;
63
+ subscriptionStartDate: string | null;
64
+ currentPeriodEnd: string | null;
65
+ }
66
+ /** Course shown on checkout / post-checkout when arriving via ?course_run_key=. */
67
+ export interface CourseDetail {
68
+ maId: string;
69
+ maName: string;
70
+ maDescription: string | null;
71
+ tShortDescription: string | null;
72
+ imageUrl: string | null;
73
+ tCourseKey: string | null;
74
+ tBrandText: string | null;
75
+ tPrimarySubjectArea: string | null;
76
+ tLevelType: string | null;
77
+ tLanguage: string | null;
78
+ tPacingType: string | null;
79
+ tDurationLow: number | null;
80
+ tDurationHigh: number | null;
81
+ tDurationUnit: string | null;
82
+ tEffortLow: number | null;
83
+ tEffortHigh: number | null;
84
+ tEffortUnit: string | null;
85
+ tUrlCourse: string | null;
86
+ tB2cSubscriptionInclusion: boolean | null;
87
+ tHasOfacRestrictions: boolean | null;
88
+ tCatalogActive: boolean | null;
89
+ }
90
+ /** Returned by getBillingPlans — all available plans for the product. */
91
+ export interface BillingPlansResult {
92
+ plans: BillingPlan[];
93
+ }
94
+ /** Returned by getSalableUid — the product uid and its ownership models. */
95
+ export interface ProductInfo {
96
+ uid: string;
97
+ maName: string;
98
+ ownershipModels: {
99
+ uid: string;
100
+ omName: string;
101
+ }[];
102
+ }
103
+ export interface CartStatusResult {
104
+ status: Status | null;
105
+ stripeSubscriptionId: string | null;
106
+ /** Stripe-hosted challenge URL for the checkout confirmation step. */
107
+ stripeConfirmationRedirectUrl: string | null;
108
+ /** PayPal-hosted approval URL for the same checkout confirmation step. */
109
+ paypalApprovalUrl: string | null;
110
+ lastComment: string;
111
+ }
112
+ export interface CartBillingAddress {
113
+ tFirstName: string;
114
+ tLastName: string;
115
+ upaLine1: string;
116
+ upaCity: string;
117
+ upaPostcode: string;
118
+ gadStateOrProvince: string;
119
+ gadCountry: {
120
+ iso2Code: string;
121
+ };
122
+ }
123
+ export interface UpdateCartItemArgs {
124
+ cartItemUid: string;
125
+ billingAddress?: CartBillingAddress;
126
+ paymentMethodId?: string;
127
+ /** Payer email attached when the payment type is TwouPaypalPayment. */
128
+ paypalEmail?: string | null;
129
+ }
130
+ /** Auto-renewal consent captured on TwouCart at checkout confirmation (SUBS-228). */
131
+ export interface CheckoutConsent {
132
+ /** Main auto-renewal checkbox — always required at submit. */
133
+ tConsentRecurring: boolean;
134
+ /** UK/CA resident checkbox; null when that checkbox is not shown. */
135
+ tConsentUkCa: boolean | null;
136
+ /** ISO-8601 timestamp when consent was captured. */
137
+ tConsentAt: string;
138
+ /** Exact disclosure text shown to the learner (audit trail). */
139
+ tConsentText: string;
140
+ }
141
+ export interface UpdateCartConsentArgs {
142
+ cartUid: string;
143
+ consent: CheckoutConsent;
144
+ /** Absolute checkout return URL stored in the backend's tStripeReturnUrl field. */
145
+ returnUrl?: string | null;
146
+ }
147
+ export interface BillingInfo {
148
+ firstName: string;
149
+ lastName: string;
150
+ city: string;
151
+ zip: string;
152
+ country: string;
153
+ line1: string;
154
+ state: string;
155
+ }
156
+ export interface CheckoutClient {
157
+ gql: GqlRunner;
158
+ setToken: (token: string) => void;
159
+ createCart: (vars: CartIds) => Promise<Cart>;
160
+ getCartItem: (biId: string) => Promise<{
161
+ cartUid: string;
162
+ cartItemUid: string;
163
+ }>;
164
+ updateCartItem: (args: UpdateCartItemArgs) => Promise<void>;
165
+ updateCartConsent: (args: UpdateCartConsentArgs) => Promise<void>;
166
+ placeOrder: (cartUid: string) => Promise<unknown>;
167
+ getCartStatus: (biId: string) => Promise<CartStatusResult>;
168
+ findSubscriptionBiId: (biId: string) => Promise<SubscriptionDetails | null>;
169
+ getSalableUid: (maId: string) => Promise<ProductInfo>;
170
+ getBillingPlans: () => Promise<BillingPlansResult>;
171
+ getActiveSubscriptions: () => Promise<{
172
+ active: number;
173
+ }>;
174
+ isCurrentUserSubscriber: () => Promise<CurrentUserSubscriberResult | null>;
175
+ getCourseDetail: (courseKey: string) => Promise<CourseDetail | null>;
176
+ }
177
+ export interface DevAuth {
178
+ iamUrl: string;
179
+ clientId: string;
180
+ clientSecret: string;
181
+ }
182
+ export interface StripeElementChangeEvent {
183
+ error?: {
184
+ message?: string;
185
+ };
186
+ [key: string]: unknown;
187
+ }
188
+ export interface StripeElementLike {
189
+ mount: (node: HTMLElement) => void;
190
+ on: (event: string, handler: (e: StripeElementChangeEvent) => void) => void;
191
+ unmount?: () => void;
192
+ }
193
+ export interface StripeElementsLike {
194
+ create: (type: string, options?: Record<string, unknown>) => StripeElementLike;
195
+ }
196
+ export interface StripeError {
197
+ message?: string;
198
+ code?: string;
199
+ }
200
+ export interface PaymentMethodResult {
201
+ paymentMethod?: {
202
+ id: string;
203
+ };
204
+ error?: StripeError;
205
+ }
206
+ export interface ConfirmResult {
207
+ error?: StripeError;
208
+ setupIntent?: unknown;
209
+ paymentIntent?: unknown;
210
+ }
211
+ export interface CreatePaymentMethodParams {
212
+ type: 'card';
213
+ card: StripeElementLike;
214
+ billing_details?: Record<string, unknown>;
215
+ }
216
+ export interface StripeLike {
217
+ elements: () => StripeElementsLike;
218
+ createPaymentMethod: (params: CreatePaymentMethodParams) => Promise<PaymentMethodResult>;
219
+ confirmCardSetup: (clientSecret: string) => Promise<ConfirmResult>;
220
+ confirmCardPayment: (clientSecret: string) => Promise<ConfirmResult>;
221
+ }
222
+ declare global {
223
+ interface Window {
224
+ Stripe?: (publishableKey: string) => StripeLike;
225
+ }
226
+ }
227
+ export interface TrialDateRange {
228
+ /** e.g. "June 22, 2026" */
229
+ displayStart: string;
230
+ /** e.g. "June 29, 2026" */
231
+ displayEnd: string;
232
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Status, Phase } from './constants';\n\nexport type { Status, Phase };\n\n// --- Bootstrap domain --------------------------------------------------------\nexport interface TwouCustomerContact {\n email?: string,\n}\n\nexport interface TwouCustomerParty {\n paName: string,\n indFirstName?: string,\n indLastName?: string,\n paContacts: { edges: { node: TwouCustomerContact }[] },\n}\n\nexport interface TwouCustomer {\n uid: string,\n parId: string,\n parParty: TwouCustomerParty,\n}\n\nexport type GqlRunner = (query: string, variables?: Record<string, unknown>, retry?: boolean) => Promise<any>;\n\n// --- Cart domain -------------------------------------------------------------\nexport interface Cart {\n biId: string,\n uid: string,\n}\n\nexport interface CartIds {\n customerUid: string,\n salableUid: string,\n billingPlanUid: string,\n}\n\nexport type BillingCycle = 'monthly' | 'annual';\n\nexport type PaymentMethod = 'card' | 'googlepay' | 'paypal';\n\nexport type SupportedPaymentMethod = Exclude<PaymentMethod, 'googlepay'>;\n\nexport type BillingPeriod = 'MONTHLY' | 'ANNUAL' | 'QUARTERLY' | string;\n\nexport interface BillingPlanOwnershipModel {\n uid: string,\n omName: string,\n}\n\nexport interface BillingPlan {\n uid: string,\n stripePriceId: string,\n /** Price amount e.g. \"39.99\" */\n amount: string,\n /** Currency code e.g. \"USD\" */\n currency: string,\n isTemplate: boolean,\n ownershipModel: BillingPlanOwnershipModel,\n}\n\nexport interface SubscriptionDetails {\n biId: string, // \"BI301ZDAD6CMICG2\"\n trialStart: string | null,\n trialEnd: string | null,\n renewalType: string | null, // \"Annual\" | \"Monthly\"\n cardLast4: string | null, // \"4242\"\n cardBrand: string | null, // \"visa\" | \"mastercard\" etc\n stripePaymentMethodId: string | null,\n planName: string | null, // \"Monthly Subscription\"\n}\n\nexport interface CurrentUserSubscriberResult {\n isSubscriber: boolean,\n subscriptionBiId: string | null,\n status: string | null,\n subscriptionStartDate: string | null,\n currentPeriodEnd: string | null,\n}\n\n/** Course shown on checkout / post-checkout when arriving via ?course_run_key=. */\nexport interface CourseDetail {\n maId: string,\n maName: string,\n maDescription: string | null,\n tShortDescription: string | null,\n imageUrl: string | null,\n tCourseKey: string | null,\n tBrandText: string | null,\n tPrimarySubjectArea: string | null,\n tLevelType: string | null,\n tLanguage: string | null,\n tPacingType: string | null,\n tDurationLow: number | null,\n tDurationHigh: number | null,\n tDurationUnit: string | null,\n tEffortLow: number | null,\n tEffortHigh: number | null,\n tEffortUnit: string | null,\n tUrlCourse: string | null,\n tB2cSubscriptionInclusion: boolean | null,\n tHasOfacRestrictions: boolean | null,\n tCatalogActive: boolean | null,\n}\n\n/** Returned by getBillingPlans — all available plans for the product. */\nexport interface BillingPlansResult {\n plans: BillingPlan[],\n}\n\n/** Returned by getSalableUid — the product uid and its ownership models. */\nexport interface ProductInfo {\n uid: string,\n maName: string,\n ownershipModels: { uid: string, omName: string }[],\n}\n\nexport interface CartStatusResult {\n status: Status | null,\n stripeSubscriptionId: string | null,\n /** Stripe-hosted challenge URL for the checkout confirmation step. */\n stripeConfirmationRedirectUrl: string | null,\n /** PayPal-hosted approval URL for the same checkout confirmation step. */\n paypalApprovalUrl: string | null,\n lastComment: string,\n}\n\nexport interface CartBillingAddress {\n tFirstName: string,\n tLastName: string,\n upaLine1: string,\n upaCity: string,\n upaPostcode: string,\n gadStateOrProvince: string,\n gadCountry: { iso2Code: string },\n}\n\nexport interface UpdateCartItemArgs {\n cartItemUid: string,\n billingAddress?: CartBillingAddress,\n paymentMethodId?: string,\n /** Payer email attached when the payment type is TwouPaypalPayment. */\n paypalEmail?: string | null,\n}\n\n/** Auto-renewal consent captured on TwouCart at checkout confirmation (SUBS-228). */\nexport interface CheckoutConsent {\n /** Main auto-renewal checkbox — always required at submit. */\n tConsentRecurring: boolean,\n /** UK/CA resident checkbox; null when that checkbox is not shown. */\n tConsentUkCa: boolean | null,\n /** ISO-8601 timestamp when consent was captured. */\n tConsentAt: string,\n /** Exact disclosure text shown to the learner (audit trail). */\n tConsentText: string,\n}\n\nexport interface UpdateCartConsentArgs {\n cartUid: string,\n consent: CheckoutConsent,\n /** Absolute checkout return URL stored in the backend's tStripeReturnUrl field. */\n returnUrl?: string | null,\n}\n\nexport interface BillingInfo {\n firstName: string,\n lastName: string,\n city: string,\n zip: string,\n country: string,\n line1: string,\n state: string,\n}\n\n// --- Checkout client surface -------------------------------------------------\nexport interface CheckoutClient {\n gql: GqlRunner,\n setToken: (token: string) => void,\n createCart: (vars: CartIds) => Promise<Cart>,\n getCartItem: (biId: string) => Promise<{ cartUid: string, cartItemUid: string }>,\n updateCartItem: (args: UpdateCartItemArgs) => Promise<void>,\n updateCartConsent: (args: UpdateCartConsentArgs) => Promise<void>,\n placeOrder: (cartUid: string) => Promise<unknown>,\n getCartStatus: (biId: string) => Promise<CartStatusResult>,\n findSubscriptionBiId: (biId: string) => Promise<SubscriptionDetails | null>,\n getSalableUid: (maId: string) => Promise<ProductInfo>,\n getBillingPlans: () => Promise<BillingPlansResult>,\n getActiveSubscriptions: () => Promise<{ active: number }>,\n isCurrentUserSubscriber: () => Promise<CurrentUserSubscriberResult | null>,\n getCourseDetail: (courseKey: string) => Promise<CourseDetail | null>,\n}\n\nexport interface DevAuth {\n iamUrl: string,\n clientId: string,\n clientSecret: string,\n}\n\n// --- Minimal Stripe.js types -------------------------------------------------\n// Just the surface this module uses. If you depend on `@stripe/stripe-js`,\n// you can replace these with its richer types.\nexport interface StripeElementChangeEvent {\n error?: { message?: string },\n [key: string]: unknown,\n}\n\nexport interface StripeElementLike {\n mount: (node: HTMLElement) => void,\n on: (event: string, handler: (e: StripeElementChangeEvent) => void) => void,\n unmount?: () => void,\n}\n\nexport interface StripeElementsLike {\n create: (type: string, options?: Record<string, unknown>) => StripeElementLike,\n}\n\nexport interface StripeError {\n message?: string,\n code?: string,\n}\n\nexport interface PaymentMethodResult {\n paymentMethod?: { id: string },\n error?: StripeError,\n}\n\nexport interface ConfirmResult {\n error?: StripeError,\n setupIntent?: unknown,\n paymentIntent?: unknown,\n}\n\nexport interface CreatePaymentMethodParams {\n type: 'card',\n card: StripeElementLike,\n billing_details?: Record<string, unknown>,\n}\n\nexport interface StripeLike {\n elements: () => StripeElementsLike,\n createPaymentMethod: (params: CreatePaymentMethodParams) => Promise<PaymentMethodResult>,\n confirmCardSetup: (clientSecret: string) => Promise<ConfirmResult>,\n confirmCardPayment: (clientSecret: string) => Promise<ConfirmResult>,\n}\n\ndeclare global {\n interface Window {\n Stripe?: (publishableKey: string) => StripeLike,\n }\n}\n\nexport interface TrialDateRange {\n /** e.g. \"June 22, 2026\" */\n displayStart: string,\n /** e.g. \"June 29, 2026\" */\n displayEnd: string,\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { CheckoutClient } from '../types';
2
+ interface CheckoutClientConfig {
3
+ apiUrl: string;
4
+ confirmIntentUrl?: string;
5
+ }
6
+ export declare function createCheckoutClient({ apiUrl }: CheckoutClientConfig): CheckoutClient;
7
+ export {};
@@ -0,0 +1,28 @@
1
+ /**
2
+ * api/index.ts — composes the pieces into a single checkout client and
3
+ * re-exports the API utilities.
4
+ */
5
+ import { createGqlClient } from './graphqlClient';
6
+ import * as cart from './cartApi';
7
+ import * as bootstrap from './bootstrapApi';
8
+ export function createCheckoutClient({ apiUrl }) {
9
+ const { gql, setToken } = createGqlClient({ apiUrl });
10
+ const fetchStatus = (biId) => cart.getCartStatus(gql, biId);
11
+ return {
12
+ gql,
13
+ setToken,
14
+ createCart: (vars) => cart.createCart(gql, vars),
15
+ getCartItem: (biId) => cart.getCartItem(gql, biId),
16
+ updateCartItem: (args) => cart.updateCartItem(gql, args),
17
+ updateCartConsent: (args) => cart.updateCartConsent(gql, args),
18
+ placeOrder: (cartUid) => cart.placeOrder(gql, cartUid),
19
+ getCartStatus: fetchStatus,
20
+ findSubscriptionBiId: (biId) => cart.findSubscriptionBiId(gql, biId),
21
+ getSalableUid: (maId) => bootstrap.getSalableUid(gql, maId),
22
+ getBillingPlans: () => bootstrap.getBillingPlans(gql),
23
+ getActiveSubscriptions: () => bootstrap.getActiveSubscriptions(gql),
24
+ isCurrentUserSubscriber: () => bootstrap.isCurrentUserSubscriber(gql),
25
+ getCourseDetail: (courseKey) => bootstrap.getCourseDetail(gql, courseKey),
26
+ };
27
+ }
28
+ //# sourceMappingURL=auth.js.map