@edx/frontend-app-subscription-manage 1.3.2 → 1.4.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.
- package/dist/app.js +2 -2
- package/dist/app.js.map +1 -1
- package/dist/components/ActiveSubscription/ActiveSubscription.d.ts +7 -0
- package/dist/components/ActiveSubscription/ActiveSubscription.js +24 -0
- package/dist/components/ActiveSubscription/ActiveSubscription.js.map +1 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.d.ts +7 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.js +19 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.js.map +1 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.d.ts +12 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.js +21 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.js.map +1 -0
- package/dist/components/CancelSuccess/CancelSuccess.d.ts +7 -0
- package/dist/components/CancelSuccess/CancelSuccess.js +17 -0
- package/dist/components/CancelSuccess/CancelSuccess.js.map +1 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.d.ts +13 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.js +27 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.js.map +1 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.d.ts +8 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.js +20 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.js.map +1 -0
- package/dist/components/HelpFooter/HelpFooter.d.ts +3 -0
- package/dist/components/HelpFooter/HelpFooter.js +12 -0
- package/dist/components/HelpFooter/HelpFooter.js.map +1 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.d.ts +3 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.js +9 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.js.map +1 -0
- package/dist/components/PaymentHistory/PaymentHistory.d.ts +10 -0
- package/dist/components/PaymentHistory/PaymentHistory.js +23 -0
- package/dist/components/PaymentHistory/PaymentHistory.js.map +1 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.d.ts +17 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.js +63 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.js.map +1 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.d.ts +9 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.js +25 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.js.map +1 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.d.ts +8 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.js +9 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.js.map +1 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.d.ts +9 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.js +135 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.js.map +1 -0
- package/dist/components/messages.d.ts +473 -0
- package/dist/components/messages.js +482 -0
- package/dist/components/messages.js.map +1 -0
- package/dist/constants.d.ts +14 -56
- package/dist/constants.js +23 -272
- package/dist/constants.js.map +1 -1
- package/dist/data/hooks/keys.d.ts +8 -13
- package/dist/data/hooks/keys.js +8 -13
- package/dist/data/hooks/keys.js.map +1 -1
- package/dist/data/hooks/useManageQueries.d.ts +37 -0
- package/dist/data/hooks/useManageQueries.js +206 -0
- package/dist/data/hooks/useManageQueries.js.map +1 -0
- package/dist/data/services/subs/urls.d.ts +2 -2
- package/dist/data/services/subs/urls.js.map +1 -1
- package/dist/data/services/subscription/cancelSubscription.d.ts +6 -0
- package/dist/data/services/subscription/cancelSubscription.js +31 -0
- package/dist/data/services/subscription/cancelSubscription.js.map +1 -0
- package/dist/data/services/subscription/getBillingPlans.d.ts +3 -0
- package/dist/{utils/fetchBillingPlans.js → data/services/subscription/getBillingPlans.js} +10 -21
- package/dist/data/services/subscription/getBillingPlans.js.map +1 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.d.ts +3 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.js +35 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.js.map +1 -0
- package/dist/data/services/subscription/getPaymentHistory.d.ts +6 -0
- package/dist/data/services/subscription/getPaymentHistory.js +65 -0
- package/dist/data/services/subscription/getPaymentHistory.js.map +1 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.d.ts +7 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.js +98 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.js.map +1 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.d.ts +8 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.js +42 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.js.map +1 -0
- package/dist/data/services/subscription/reactivateSubscription.d.ts +6 -0
- package/dist/data/services/subscription/reactivateSubscription.js +30 -0
- package/dist/data/services/subscription/reactivateSubscription.js.map +1 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.d.ts +10 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.js +31 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.js.map +1 -0
- package/dist/icons/ExternalLinkIcon.d.ts +6 -0
- package/dist/icons/ExternalLinkIcon.js +18 -0
- package/dist/icons/ExternalLinkIcon.js.map +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +2 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.js +53 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.js.map +1 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.js +24 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.js.map +1 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.js +87 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.js.map +1 -0
- package/dist/messages.js +2 -2
- package/dist/messages.js.map +1 -1
- package/dist/routes.d.ts +9 -2
- package/dist/routes.js +26 -6
- package/dist/routes.js.map +1 -1
- package/dist/style.scss +1 -14
- package/dist/styles/components/manageSubscription.scss +454 -0
- package/dist/types.d.ts +57 -201
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/billingDetails.d.ts +3 -20
- package/dist/utils/billingDetails.js +4 -25
- package/dist/utils/billingDetails.js.map +1 -1
- package/dist/utils/edxSession.d.ts +18 -0
- package/dist/utils/edxSession.js +72 -0
- package/dist/utils/edxSession.js.map +1 -0
- package/dist/utils/formatDate.d.ts +16 -0
- package/dist/utils/formatDate.js +69 -0
- package/dist/utils/formatDate.js.map +1 -0
- package/dist/utils/graphqlClient.d.ts +9 -10
- package/dist/utils/graphqlClient.js +22 -11
- package/dist/utils/graphqlClient.js.map +1 -1
- package/dist/utils/invoiceAmount.d.ts +22 -0
- package/dist/utils/invoiceAmount.js +59 -0
- package/dist/utils/invoiceAmount.js.map +1 -0
- package/dist/utils/queries.d.ts +38 -33
- package/dist/utils/queries.js +83 -123
- package/dist/utils/queries.js.map +1 -1
- package/dist/utils/subscriptionView.d.ts +15 -0
- package/dist/utils/subscriptionView.js +50 -0
- package/dist/utils/subscriptionView.js.map +1 -0
- package/dist/utils/urls.d.ts +13 -0
- package/dist/utils/urls.js +52 -0
- package/dist/utils/urls.js.map +1 -0
- package/package.json +7 -2
- package/dist/checkoutPage/CheckoutPage.d.ts +0 -3
- package/dist/checkoutPage/CheckoutPage.js +0 -30
- package/dist/checkoutPage/CheckoutPage.js.map +0 -1
- package/dist/components/BrandMarks/BrandMarks.d.ts +0 -3
- package/dist/components/BrandMarks/BrandMarks.js +0 -9
- package/dist/components/BrandMarks/BrandMarks.js.map +0 -1
- package/dist/components/CartSummary/CartSummary.d.ts +0 -21
- package/dist/components/CartSummary/CartSummary.js +0 -30
- package/dist/components/CartSummary/CartSummary.js.map +0 -1
- package/dist/components/CartSummary/Messages.d.ts +0 -73
- package/dist/components/CartSummary/Messages.js +0 -76
- package/dist/components/CartSummary/Messages.js.map +0 -1
- package/dist/components/Checkout/Checkout.d.ts +0 -4
- package/dist/components/Checkout/Checkout.js +0 -40
- package/dist/components/Checkout/Checkout.js.map +0 -1
- package/dist/components/CheckoutGate/CheckoutGate.d.ts +0 -7
- package/dist/components/CheckoutGate/CheckoutGate.js +0 -35
- package/dist/components/CheckoutGate/CheckoutGate.js.map +0 -1
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +0 -9
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +0 -31
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +0 -1
- package/dist/components/CourseEnrollmentCard/Messages.d.ts +0 -33
- package/dist/components/CourseEnrollmentCard/Messages.js +0 -35
- package/dist/components/CourseEnrollmentCard/Messages.js.map +0 -1
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.d.ts +0 -13
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js +0 -11
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js.map +0 -1
- package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +0 -15
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js +0 -21
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +0 -1
- package/dist/components/EnrollmentSummary/Messages.d.ts +0 -33
- package/dist/components/EnrollmentSummary/Messages.js +0 -35
- package/dist/components/EnrollmentSummary/Messages.js.map +0 -1
- package/dist/components/PaymentFields/PaymentFields.d.ts +0 -9
- package/dist/components/PaymentFields/PaymentFields.js +0 -7
- package/dist/components/PaymentFields/PaymentFields.js.map +0 -1
- package/dist/components/PaymentForm/Messages.d.ts +0 -88
- package/dist/components/PaymentForm/Messages.js +0 -95
- package/dist/components/PaymentForm/Messages.js.map +0 -1
- package/dist/components/PaymentForm/PaymentForm.d.ts +0 -21
- package/dist/components/PaymentForm/PaymentForm.js +0 -69
- package/dist/components/PaymentForm/PaymentForm.js.map +0 -1
- package/dist/components/StatusScreens/Messages.d.ts +0 -103
- package/dist/components/StatusScreens/Messages.js +0 -108
- package/dist/components/StatusScreens/Messages.js.map +0 -1
- package/dist/components/StatusScreens/StatusScreens.d.ts +0 -23
- package/dist/components/StatusScreens/StatusScreens.js +0 -25
- package/dist/components/StatusScreens/StatusScreens.js.map +0 -1
- package/dist/data/hooks/useCheckout.d.ts +0 -57
- package/dist/data/hooks/useCheckout.js +0 -249
- package/dist/data/hooks/useCheckout.js.map +0 -1
- package/dist/data/hooks/useCheckoutGate.d.ts +0 -15
- package/dist/data/hooks/useCheckoutGate.js +0 -39
- package/dist/data/hooks/useCheckoutGate.js.map +0 -1
- package/dist/data/hooks/useCheckoutMutations.d.ts +0 -16
- package/dist/data/hooks/useCheckoutMutations.js +0 -131
- package/dist/data/hooks/useCheckoutMutations.js.map +0 -1
- package/dist/data/hooks/useCheckoutQueries.d.ts +0 -30
- package/dist/data/hooks/useCheckoutQueries.js +0 -97
- package/dist/data/hooks/useCheckoutQueries.js.map +0 -1
- package/dist/styles/components/brandMarks.scss +0 -54
- package/dist/styles/components/cartSummary.scss +0 -18
- package/dist/styles/components/checkout.scss +0 -29
- package/dist/styles/components/checkoutStepper.scss +0 -9
- package/dist/styles/components/courseEnrollmentCard.scss +0 -38
- package/dist/styles/components/edxUnlimitedBanner.scss +0 -138
- package/dist/styles/components/enrollmentSummary.scss +0 -13
- package/dist/styles/components/paymentFields.scss +0 -15
- package/dist/styles/components/paymentForm.scss +0 -105
- package/dist/styles/components/statusScreens.scss +0 -29
- package/dist/styles/components/successScreen.scss +0 -0
- package/dist/utils/auth.d.ts +0 -7
- package/dist/utils/auth.js +0 -28
- package/dist/utils/auth.js.map +0 -1
- package/dist/utils/bootstrapApi.d.ts +0 -20
- package/dist/utils/bootstrapApi.js +0 -142
- package/dist/utils/bootstrapApi.js.map +0 -1
- package/dist/utils/cartApi.d.ts +0 -16
- package/dist/utils/cartApi.js +0 -118
- package/dist/utils/cartApi.js.map +0 -1
- package/dist/utils/checkout.d.ts +0 -6
- package/dist/utils/checkout.js +0 -28
- package/dist/utils/checkout.js.map +0 -1
- package/dist/utils/fetchActiveSubscriptions.d.ts +0 -4
- package/dist/utils/fetchActiveSubscriptions.js +0 -36
- package/dist/utils/fetchActiveSubscriptions.js.map +0 -1
- package/dist/utils/fetchBillingPlans.d.ts +0 -2
- package/dist/utils/fetchBillingPlans.js.map +0 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.js +0 -17
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/provision.d.ts +0 -25
- package/dist/utils/provision.js +0 -95
- package/dist/utils/provision.js.map +0 -1
- package/dist/utils/stripe.d.ts +0 -7
- package/dist/utils/stripe.js +0 -43
- package/dist/utils/stripe.js.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,39 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Manage Subscription — domain types for Viax subscriber + enrollment data.
|
|
3
|
+
*/
|
|
4
|
+
/** GraphQL runner used by VIAX fetchers. */
|
|
5
|
+
export type GqlRunner = (query: string, variables?: Record<string, unknown>) => Promise<any>;
|
|
6
|
+
/** Result of `tIsCurrentUserSubscriber` (JSON scalar). */
|
|
7
|
+
export interface CurrentUserSubscriberResult {
|
|
8
|
+
/** Has/expects access — drive manage vs upsell messaging. */
|
|
9
|
+
isSubscriber: boolean;
|
|
10
|
+
/** Enrollable right now (ACTIVE / TRIAL_ACTIVE). */
|
|
11
|
+
canEnroll: boolean;
|
|
12
|
+
subscriptionBiId: string | null;
|
|
13
|
+
status: string | null;
|
|
14
|
+
currentPeriodEnd: string | null;
|
|
15
|
+
subscriptionStartDate: string | null;
|
|
16
|
+
subscriptionEndDate: string | null;
|
|
17
|
+
/** Optional plan label from API when present. */
|
|
18
|
+
renewalType?: string | null;
|
|
19
|
+
/** Optional cancel timestamp when present. */
|
|
20
|
+
canceledAt?: string | null;
|
|
21
|
+
/** Optional price display amount when present. */
|
|
22
|
+
amount?: string | null;
|
|
23
|
+
currency?: string | null;
|
|
24
|
+
}
|
|
25
|
+
/** Normalized enrollment for the cancel confirmation course list. */
|
|
26
|
+
export interface SubscriptionEnrollment {
|
|
23
27
|
biId: string;
|
|
24
|
-
|
|
28
|
+
courseMaId: string | null;
|
|
29
|
+
courseName: string | null;
|
|
30
|
+
courseSlug: string | null;
|
|
31
|
+
/** Course card / thumbnail image. */
|
|
32
|
+
imageUrl: string | null;
|
|
33
|
+
orgName: string | null;
|
|
34
|
+
orgLogoUrl: string | null;
|
|
35
|
+
courseRunKey: string | null;
|
|
36
|
+
/** TwouEnrollment bpStatus.code (ACTIVE, COMPLETED, …). */
|
|
37
|
+
status: string | null;
|
|
38
|
+
/** True when bpStatus.code is COMPLETED. */
|
|
39
|
+
hasCertificate: boolean;
|
|
40
|
+
certificateUrl: string | null;
|
|
25
41
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
/** Normalized invoice row for the Payment history tab. */
|
|
43
|
+
export interface PaymentHistoryItem {
|
|
44
|
+
biId: string;
|
|
45
|
+
/** Display order number, e.g. EDX-BI3X25N5SY30OSIK */
|
|
46
|
+
orderNumber: string;
|
|
47
|
+
stripeInvoiceId: string | null;
|
|
48
|
+
status: string | null;
|
|
49
|
+
billDate: string | null;
|
|
50
|
+
periodStart: string | null;
|
|
51
|
+
periodEnd: string | null;
|
|
52
|
+
/** Charged amount in major currency units (e.g. 59.00). */
|
|
53
|
+
amount: number;
|
|
54
|
+
currency: string;
|
|
55
|
+
isTrial: boolean;
|
|
30
56
|
}
|
|
57
|
+
/** UI view derived from subscriber status. */
|
|
58
|
+
export type SubscriptionView = 'none' | 'active' | 'canceled_access' | 'canceled_expired';
|
|
59
|
+
export type ManageTab = 'subscription' | 'payment-history';
|
|
31
60
|
export type BillingCycle = 'monthly' | 'annual';
|
|
32
|
-
export type BillingPeriod = 'MONTHLY' | 'ANNUAL' | 'QUARTERLY' | string;
|
|
33
61
|
export interface BillingPlanOwnershipModel {
|
|
34
62
|
uid: string;
|
|
35
63
|
omName: string;
|
|
36
64
|
}
|
|
65
|
+
/** Normalized row from `filterCustomerBillingPlan`. */
|
|
37
66
|
export interface BillingPlan {
|
|
38
67
|
uid: string;
|
|
39
68
|
stripePriceId: string;
|
|
@@ -44,179 +73,6 @@ export interface BillingPlan {
|
|
|
44
73
|
isTemplate: boolean;
|
|
45
74
|
ownershipModel: BillingPlanOwnershipModel;
|
|
46
75
|
}
|
|
47
|
-
export interface SubscriptionDetails {
|
|
48
|
-
biId: string;
|
|
49
|
-
trialStart: string | null;
|
|
50
|
-
trialEnd: string | null;
|
|
51
|
-
renewalType: string | null;
|
|
52
|
-
cardLast4: string | null;
|
|
53
|
-
cardBrand: string | null;
|
|
54
|
-
stripePaymentMethodId: string | null;
|
|
55
|
-
planName: string | null;
|
|
56
|
-
}
|
|
57
|
-
export interface CurrentUserSubscriberResult {
|
|
58
|
-
isSubscriber: boolean;
|
|
59
|
-
subscriptionBiId: string | null;
|
|
60
|
-
status: string | null;
|
|
61
|
-
subscriptionStartDate: string | null;
|
|
62
|
-
currentPeriodEnd: string | null;
|
|
63
|
-
}
|
|
64
|
-
/** Course shown on checkout / post-checkout when arriving via ?course_run_key=. */
|
|
65
|
-
export interface CourseDetail {
|
|
66
|
-
maId: string;
|
|
67
|
-
maName: string;
|
|
68
|
-
maDescription: string | null;
|
|
69
|
-
tShortDescription: string | null;
|
|
70
|
-
imageUrl: string | null;
|
|
71
|
-
tCourseKey: string | null;
|
|
72
|
-
tBrandText: string | null;
|
|
73
|
-
tPrimarySubjectArea: string | null;
|
|
74
|
-
tLevelType: string | null;
|
|
75
|
-
tLanguage: string | null;
|
|
76
|
-
tPacingType: string | null;
|
|
77
|
-
tDurationLow: number | null;
|
|
78
|
-
tDurationHigh: number | null;
|
|
79
|
-
tDurationUnit: string | null;
|
|
80
|
-
tEffortLow: number | null;
|
|
81
|
-
tEffortHigh: number | null;
|
|
82
|
-
tEffortUnit: string | null;
|
|
83
|
-
tUrlCourse: string | null;
|
|
84
|
-
tB2cSubscriptionInclusion: boolean | null;
|
|
85
|
-
tHasOfacRestrictions: boolean | null;
|
|
86
|
-
tCatalogActive: boolean | null;
|
|
87
|
-
}
|
|
88
|
-
/** Returned by getBillingPlans — all available plans for the product. */
|
|
89
76
|
export interface BillingPlansResult {
|
|
90
77
|
plans: BillingPlan[];
|
|
91
78
|
}
|
|
92
|
-
/** Returned by getSalableUid — the product uid and its ownership models. */
|
|
93
|
-
export interface ProductInfo {
|
|
94
|
-
uid: string;
|
|
95
|
-
maName: string;
|
|
96
|
-
ownershipModels: {
|
|
97
|
-
uid: string;
|
|
98
|
-
omName: string;
|
|
99
|
-
}[];
|
|
100
|
-
}
|
|
101
|
-
export interface CartStatusResult {
|
|
102
|
-
status: Status | null;
|
|
103
|
-
stripeSubscriptionId: string | null;
|
|
104
|
-
lastComment: string;
|
|
105
|
-
}
|
|
106
|
-
export interface CartBillingAddress {
|
|
107
|
-
tFirstName: string;
|
|
108
|
-
tLastName: string;
|
|
109
|
-
upaLine1: string;
|
|
110
|
-
upaCity: string;
|
|
111
|
-
upaPostcode: string;
|
|
112
|
-
gadStateOrProvince: string;
|
|
113
|
-
gadCountry: {
|
|
114
|
-
iso2Code: string;
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
export interface UpdateCartItemArgs {
|
|
118
|
-
cartItemUid: string;
|
|
119
|
-
billingAddress?: CartBillingAddress;
|
|
120
|
-
paymentMethodId?: string;
|
|
121
|
-
}
|
|
122
|
-
/** Auto-renewal consent captured on TwouCart at checkout confirmation (SUBS-228). */
|
|
123
|
-
export interface CheckoutConsent {
|
|
124
|
-
/** Main auto-renewal checkbox — always required at submit. */
|
|
125
|
-
tConsentRecurring: boolean;
|
|
126
|
-
/** UK/CA resident checkbox; null when that checkbox is not shown. */
|
|
127
|
-
tConsentUkCa: boolean | null;
|
|
128
|
-
/** ISO-8601 timestamp when consent was captured. */
|
|
129
|
-
tConsentAt: string;
|
|
130
|
-
/** Exact disclosure text shown to the learner (audit trail). */
|
|
131
|
-
tConsentText: string;
|
|
132
|
-
}
|
|
133
|
-
export interface UpdateCartConsentArgs {
|
|
134
|
-
cartUid: string;
|
|
135
|
-
consent: CheckoutConsent;
|
|
136
|
-
}
|
|
137
|
-
export interface BillingInfo {
|
|
138
|
-
firstName: string;
|
|
139
|
-
lastName: string;
|
|
140
|
-
city: string;
|
|
141
|
-
zip: string;
|
|
142
|
-
country: string;
|
|
143
|
-
line1: string;
|
|
144
|
-
state: string;
|
|
145
|
-
}
|
|
146
|
-
export interface CheckoutClient {
|
|
147
|
-
gql: GqlRunner;
|
|
148
|
-
setToken: (token: string) => void;
|
|
149
|
-
createCart: (vars: CartIds) => Promise<Cart>;
|
|
150
|
-
getCartItem: (biId: string) => Promise<{
|
|
151
|
-
cartUid: string;
|
|
152
|
-
cartItemUid: string;
|
|
153
|
-
}>;
|
|
154
|
-
updateCartItem: (args: UpdateCartItemArgs) => Promise<void>;
|
|
155
|
-
updateCartConsent: (args: UpdateCartConsentArgs) => Promise<void>;
|
|
156
|
-
placeOrder: (cartUid: string) => Promise<unknown>;
|
|
157
|
-
getCartStatus: (biId: string) => Promise<CartStatusResult>;
|
|
158
|
-
findSubscriptionBiId: (biId: string) => Promise<SubscriptionDetails | null>;
|
|
159
|
-
getSalableUid: (maId: string) => Promise<ProductInfo>;
|
|
160
|
-
getBillingPlans: () => Promise<BillingPlansResult>;
|
|
161
|
-
getActiveSubscriptions: () => Promise<{
|
|
162
|
-
active: number;
|
|
163
|
-
}>;
|
|
164
|
-
isCurrentUserSubscriber: () => Promise<CurrentUserSubscriberResult | null>;
|
|
165
|
-
getCourseDetail: (courseKey: string) => Promise<CourseDetail | null>;
|
|
166
|
-
}
|
|
167
|
-
export interface DevAuth {
|
|
168
|
-
iamUrl: string;
|
|
169
|
-
clientId: string;
|
|
170
|
-
clientSecret: string;
|
|
171
|
-
}
|
|
172
|
-
export interface StripeElementChangeEvent {
|
|
173
|
-
error?: {
|
|
174
|
-
message?: string;
|
|
175
|
-
};
|
|
176
|
-
[key: string]: unknown;
|
|
177
|
-
}
|
|
178
|
-
export interface StripeElementLike {
|
|
179
|
-
mount: (node: HTMLElement) => void;
|
|
180
|
-
on: (event: string, handler: (e: StripeElementChangeEvent) => void) => void;
|
|
181
|
-
unmount?: () => void;
|
|
182
|
-
}
|
|
183
|
-
export interface StripeElementsLike {
|
|
184
|
-
create: (type: string, options?: Record<string, unknown>) => StripeElementLike;
|
|
185
|
-
}
|
|
186
|
-
export interface StripeError {
|
|
187
|
-
message?: string;
|
|
188
|
-
code?: string;
|
|
189
|
-
}
|
|
190
|
-
export interface PaymentMethodResult {
|
|
191
|
-
paymentMethod?: {
|
|
192
|
-
id: string;
|
|
193
|
-
};
|
|
194
|
-
error?: StripeError;
|
|
195
|
-
}
|
|
196
|
-
export interface ConfirmResult {
|
|
197
|
-
error?: StripeError;
|
|
198
|
-
setupIntent?: unknown;
|
|
199
|
-
paymentIntent?: unknown;
|
|
200
|
-
}
|
|
201
|
-
export interface CreatePaymentMethodParams {
|
|
202
|
-
type: 'card';
|
|
203
|
-
card: StripeElementLike;
|
|
204
|
-
billing_details?: Record<string, unknown>;
|
|
205
|
-
}
|
|
206
|
-
export interface StripeLike {
|
|
207
|
-
elements: () => StripeElementsLike;
|
|
208
|
-
createPaymentMethod: (params: CreatePaymentMethodParams) => Promise<PaymentMethodResult>;
|
|
209
|
-
confirmCardSetup: (clientSecret: string) => Promise<ConfirmResult>;
|
|
210
|
-
confirmCardPayment: (clientSecret: string) => Promise<ConfirmResult>;
|
|
211
|
-
}
|
|
212
|
-
declare global {
|
|
213
|
-
interface Window {
|
|
214
|
-
Stripe?: (publishableKey: string) => StripeLike;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
export interface TrialDateRange {
|
|
218
|
-
/** e.g. "June 22, 2026" */
|
|
219
|
-
displayStart: string;
|
|
220
|
-
/** e.g. "June 29, 2026" */
|
|
221
|
-
displayEnd: string;
|
|
222
|
-
}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * Manage Subscription — domain types for Viax subscriber + enrollment data.\n */\n\n/** GraphQL runner used by VIAX fetchers. */\nexport type GqlRunner = (\n query: string,\n variables?: Record<string, unknown>,\n) => Promise<any>;\n\n/** Result of `tIsCurrentUserSubscriber` (JSON scalar). */\nexport interface CurrentUserSubscriberResult {\n /** Has/expects access — drive manage vs upsell messaging. */\n isSubscriber: boolean,\n /** Enrollable right now (ACTIVE / TRIAL_ACTIVE). */\n canEnroll: boolean,\n subscriptionBiId: string | null,\n status: string | null,\n currentPeriodEnd: string | null,\n subscriptionStartDate: string | null,\n subscriptionEndDate: string | null,\n /** Optional plan label from API when present. */\n renewalType?: string | null,\n /** Optional cancel timestamp when present. */\n canceledAt?: string | null,\n /** Optional price display amount when present. */\n amount?: string | null,\n currency?: string | null,\n}\n\n/** Normalized enrollment for the cancel confirmation course list. */\nexport interface SubscriptionEnrollment {\n biId: string,\n courseMaId: string | null,\n courseName: string | null,\n courseSlug: string | null,\n /** Course card / thumbnail image. */\n imageUrl: string | null,\n orgName: string | null,\n orgLogoUrl: string | null,\n courseRunKey: string | null,\n /** TwouEnrollment bpStatus.code (ACTIVE, COMPLETED, …). */\n status: string | null,\n /** True when bpStatus.code is COMPLETED. */\n hasCertificate: boolean,\n certificateUrl: string | null,\n}\n\n/** Normalized invoice row for the Payment history tab. */\nexport interface PaymentHistoryItem {\n biId: string,\n /** Display order number, e.g. EDX-BI3X25N5SY30OSIK */\n orderNumber: string,\n stripeInvoiceId: string | null,\n status: string | null,\n billDate: string | null,\n periodStart: string | null,\n periodEnd: string | null,\n /** Charged amount in major currency units (e.g. 59.00). */\n amount: number,\n currency: string,\n isTrial: boolean,\n}\n\n/** UI view derived from subscriber status. */\nexport type SubscriptionView =\n | 'none'\n | 'active'\n | 'canceled_access'\n | 'canceled_expired';\n\nexport type ManageTab = 'subscription' | 'payment-history';\n\nexport type BillingCycle = 'monthly' | 'annual';\n\nexport interface BillingPlanOwnershipModel {\n uid: string,\n omName: string,\n}\n\n/** Normalized row from `filterCustomerBillingPlan`. */\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 BillingPlansResult {\n plans: BillingPlan[],\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BillingCycle, BillingPlan } from '../types';
|
|
2
2
|
export interface PlanPrice {
|
|
3
3
|
uid: string;
|
|
4
4
|
stripePriceId: string;
|
|
@@ -7,24 +7,7 @@ export interface PlanPrice {
|
|
|
7
7
|
label: string;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Matches plans by looking for "annual"/"year" or "month" in omName.
|
|
13
|
-
* Falls back to the first plan if no match is found.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* getPlanPrice(billingPlans, 'monthly')
|
|
17
|
-
* // → { uid: '...', amount: '11', currency: 'USD', label: '$11 USD/month' }
|
|
18
|
-
*
|
|
19
|
-
* getPlanPrice(billingPlans, 'annual')
|
|
20
|
-
* // → { uid: '...', amount: '111', currency: 'USD', label: '$111 USD/year' }
|
|
10
|
+
* Returns the price for the selected billing cycle.
|
|
11
|
+
* Matches plans by "annual"/"year" or "month" in omName; falls back to first plan.
|
|
21
12
|
*/
|
|
22
13
|
export declare function getPlanPrice(plans: BillingPlan[], cycle: BillingCycle): PlanPrice | null;
|
|
23
|
-
/**
|
|
24
|
-
* getRenewalLabel — returns a "Then $X/month" style label for CartSummary.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* getRenewalLabel(billingPlans, 'monthly') // → "Then $11 USD/month"
|
|
28
|
-
* getRenewalLabel(billingPlans, 'annual') // → "Then $111 USD/year"
|
|
29
|
-
*/
|
|
30
|
-
export declare function getRenewalLabel(plans: BillingPlan[], cycle: BillingCycle): string;
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Matches plans by looking for "annual"/"year" or "month" in omName.
|
|
5
|
-
* Falls back to the first plan if no match is found.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* getPlanPrice(billingPlans, 'monthly')
|
|
9
|
-
* // → { uid: '...', amount: '11', currency: 'USD', label: '$11 USD/month' }
|
|
10
|
-
*
|
|
11
|
-
* getPlanPrice(billingPlans, 'annual')
|
|
12
|
-
* // → { uid: '...', amount: '111', currency: 'USD', label: '$111 USD/year' }
|
|
2
|
+
* Returns the price for the selected billing cycle.
|
|
3
|
+
* Matches plans by "annual"/"year" or "month" in omName; falls back to first plan.
|
|
13
4
|
*/
|
|
14
5
|
export function getPlanPrice(plans, cycle) {
|
|
15
6
|
var _a;
|
|
16
|
-
if (!plans.length)
|
|
7
|
+
if (!plans.length) {
|
|
17
8
|
return null;
|
|
9
|
+
}
|
|
18
10
|
const isAnnual = cycle === 'annual';
|
|
19
11
|
const match = (_a = plans.find((p) => {
|
|
20
12
|
var _a, _b;
|
|
@@ -31,17 +23,4 @@ export function getPlanPrice(plans, cycle) {
|
|
|
31
23
|
label: `$${match.amount} ${match.currency}/${isAnnual ? 'year' : 'month'}`,
|
|
32
24
|
};
|
|
33
25
|
}
|
|
34
|
-
/**
|
|
35
|
-
* getRenewalLabel — returns a "Then $X/month" style label for CartSummary.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* getRenewalLabel(billingPlans, 'monthly') // → "Then $11 USD/month"
|
|
39
|
-
* getRenewalLabel(billingPlans, 'annual') // → "Then $111 USD/year"
|
|
40
|
-
*/
|
|
41
|
-
export function getRenewalLabel(plans, cycle) {
|
|
42
|
-
const price = getPlanPrice(plans, cycle);
|
|
43
|
-
if (!price)
|
|
44
|
-
return '';
|
|
45
|
-
return `Then $${price.amount} ${price.currency}/${cycle === 'annual' ? 'year' : 'month'}`;
|
|
46
|
-
}
|
|
47
26
|
//# sourceMappingURL=billingDetails.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billingDetails.js","sourceRoot":"","sources":["../../src/utils/billingDetails.ts"],"names":[],"mappings":"AAUA
|
|
1
|
+
{"version":3,"file":"billingDetails.js","sourceRoot":"","sources":["../../src/utils/billingDetails.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAoB,EACpB,KAAmB;;IAEnB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,KAAK,QAAQ,CAAC;IAEpC,MAAM,KAAK,GAAG,MAAA,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;;QAC7B,MAAM,IAAI,GAAG,MAAA,MAAA,CAAC,CAAC,cAAc,CAAC,MAAM,0CAAE,WAAW,EAAE,mCAAI,EAAE,CAAC;QAC1D,OAAO,QAAQ;YACb,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAClD,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC,CAAC,mCAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAEf,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;KAC3E,CAAC;AACJ,CAAC","sourcesContent":["import type { BillingCycle, BillingPlan } from '../types';\n\nexport interface PlanPrice {\n uid: string,\n stripePriceId: string,\n amount: string,\n currency: string,\n label: string,\n}\n\n/**\n * Returns the price for the selected billing cycle.\n * Matches plans by \"annual\"/\"year\" or \"month\" in omName; falls back to first plan.\n */\nexport function getPlanPrice(\n plans: BillingPlan[],\n cycle: BillingCycle,\n): PlanPrice | null {\n if (!plans.length) {\n return null;\n }\n\n const isAnnual = cycle === 'annual';\n\n const match = plans.find((p) => {\n const name = p.ownershipModel.omName?.toLowerCase() ?? '';\n return isAnnual\n ? name.includes('annual') || name.includes('year')\n : name.includes('month');\n }) ?? plans[0];\n\n return {\n uid: match.uid,\n stripePriceId: match.stripePriceId,\n amount: match.amount,\n currency: match.currency,\n label: `$${match.amount} ${match.currency}/${isAnnual ? 'year' : 'month'}`,\n };\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exchange the learner's edX session for a Viax JWT.
|
|
3
|
+
*
|
|
4
|
+
* Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is
|
|
5
|
+
* unavailable). Stage/prod use POST with browser session cookies.
|
|
6
|
+
*/
|
|
7
|
+
export interface EdxSessionResult {
|
|
8
|
+
viaxToken: string;
|
|
9
|
+
customerUid: string;
|
|
10
|
+
partyUid?: string;
|
|
11
|
+
edxUserId?: string;
|
|
12
|
+
username?: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
}
|
|
15
|
+
/** LMS edx-session endpoint for the current site. */
|
|
16
|
+
export declare function getEdxSessionUrl(): string;
|
|
17
|
+
/** Exchange the learner's edX session for a Viax token. */
|
|
18
|
+
export declare function fetchEdxSession(sessionUrl: string): Promise<EdxSessionResult>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exchange the learner's edX session for a Viax JWT.
|
|
3
|
+
*
|
|
4
|
+
* Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is
|
|
5
|
+
* unavailable). Stage/prod use POST with browser session cookies.
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
import { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';
|
|
17
|
+
/** Hardcoded edX JWT used only for local/dev against Viax (same pattern as enroll/checkout MFEs). */
|
|
18
|
+
const DEV_SESSION_BODY = {
|
|
19
|
+
payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc4NjEzNTQ1NywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzg2MTMxODU3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZGV2Z2FuIiwic2NvcGVzIjpbInVzZXJfaWQiLCJlbWFpbCIsInByb2ZpbGUiXSwidmVyc2lvbiI6IjEuMi4wIiwic3ViIjoiYmRlNjcwYTRiNmYxYjc0OTExYWZhZGY4NDM4YmFmZTkiLCJmaWx0ZXJzIjpbInVzZXI6bWUiXSwiaXNfcmVzdHJpY3RlZCI6ZmFsc2UsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJ1c2VyX2lkIjo1MjgzMTE5LCJlbWFpbCI6ImFkZXZnYW5AMnUuY29tIiwibmFtZSI6IkFrYXNoIERldmdhbiIsImZhbWlseV9uYW1lIjoiRGV2Z2FuIiwiZ2l2ZW5fbmFtZSI6IkFrYXNoIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',
|
|
20
|
+
signature: 'RY64FgDMT-gRKJ6aObjUcocYqHjU3E2R_A2nxZL1BwJZgSDT1mMZMY_9HYZh8F0bAM9IFSQ1B3yP6PtcQnYsA2iYXK6_LyhG07l5qu6GRU7W99-Dq8CxLX9viJrKVj3CgGfc9bIUultlM-fjy-iZBTqDqe-DO2NHLvE-rd3b_d7cRTrhEtZ6HYkFWJXy5YOo8vxV46X4kM56jHGSq1Leixvc0ksa-NKn4AMHNSfGv_mQA16DN-Ou_uEl9CdHURGD4vOPDYE7xZt5JiwKZ3i1jzJfgMdpPgCYvYeC-5dr95_s-LaJnN6va9k3u9RFRnYKTfhHPgtSR4q7qTCzNABQqQ'
|
|
21
|
+
};
|
|
22
|
+
function parseSessionResponse(data) {
|
|
23
|
+
var _a, _b, _c, _d;
|
|
24
|
+
const viaxToken = ((_c = (_b = (_a = data.viaxToken) !== null && _a !== void 0 ? _a : data.token) !== null && _b !== void 0 ? _b : data.access_token) !== null && _c !== void 0 ? _c : data.accessToken);
|
|
25
|
+
const customerUid = ((_d = data.customerUid) !== null && _d !== void 0 ? _d : data.customer_uid);
|
|
26
|
+
if (!viaxToken) {
|
|
27
|
+
throw new Error('Session response missing viax token.');
|
|
28
|
+
}
|
|
29
|
+
if (!customerUid) {
|
|
30
|
+
throw new Error('Session response missing customerUid.');
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
viaxToken,
|
|
34
|
+
customerUid,
|
|
35
|
+
partyUid: data.partyUid,
|
|
36
|
+
edxUserId: data.edxUserId,
|
|
37
|
+
username: data.username,
|
|
38
|
+
email: data.email,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function isDevelopment() {
|
|
42
|
+
return getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT;
|
|
43
|
+
}
|
|
44
|
+
/** LMS edx-session endpoint for the current site. */
|
|
45
|
+
export function getEdxSessionUrl() {
|
|
46
|
+
return isDevelopment()
|
|
47
|
+
? 'https://courses.stage.edx.org/api/edx-session'
|
|
48
|
+
: `${getSiteConfig().lmsBaseUrl}/api/edx-session`;
|
|
49
|
+
}
|
|
50
|
+
/** Exchange the learner's edX session for a Viax token. */
|
|
51
|
+
export function fetchEdxSession(sessionUrl) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
const res = yield fetch(sessionUrl, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
credentials: 'include',
|
|
56
|
+
headers: {
|
|
57
|
+
Accept: 'application/json',
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
},
|
|
60
|
+
body: isDevelopment() ? JSON.stringify(DEV_SESSION_BODY) : undefined,
|
|
61
|
+
});
|
|
62
|
+
if (!res.ok) {
|
|
63
|
+
throw new Error(`Failed to establish session (${res.status}). Please log into edX and try again.`);
|
|
64
|
+
}
|
|
65
|
+
const data = yield res.json();
|
|
66
|
+
if (data.error) {
|
|
67
|
+
throw new Error(String(data.error));
|
|
68
|
+
}
|
|
69
|
+
return parseSessionResponse(data);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=edxSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edxSession.js","sourceRoot":"","sources":["../../src/utils/edxSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAWzE,qGAAqG;AACrG,MAAM,gBAAgB,GAAG;IACvB,OAAO,EAAE,suBAAsuB;IAC/uB,SAAS,EAAE,wVAAwV;CACpW,CAAC;AAEF,SAAS,oBAAoB,CAAC,IAA6B;;IACzD,MAAM,SAAS,GAAG,CAChB,MAAA,MAAA,MAAA,IAAI,CAAC,SAAS,mCAAI,IAAI,CAAC,KAAK,mCAAI,IAAI,CAAC,YAAY,mCAAI,IAAI,CAAC,WAAW,CAChD,CAAC;IACxB,MAAM,WAAW,GAAG,CAAC,MAAA,IAAI,CAAC,WAAW,mCAAI,IAAI,CAAC,YAAY,CAAuB,CAAC;IAElF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,SAAS;QACT,WAAW;QACX,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,SAAS,EAAE,IAAI,CAAC,SAA+B;QAC/C,QAAQ,EAAE,IAAI,CAAC,QAA8B;QAC7C,KAAK,EAAE,IAAI,CAAC,KAA2B;KACxC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,aAAa,EAAE,CAAC,WAAW,KAAK,gBAAgB,CAAC,WAAW,CAAC;AACtE,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,EAAE;QACpB,CAAC,CAAC,+CAA+C;QACjD,CAAC,CAAC,GAAG,aAAa,EAAE,CAAC,UAAU,kBAAkB,CAAC;AACtD,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAgB,eAAe,CAAC,UAAkB;;QACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS;SACrE,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,CAAC,MAAM,uCAAuC,CAClF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAkD,CAAC;QAC9E,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CAAA","sourcesContent":["/**\n * Exchange the learner's edX session for a Viax JWT.\n *\n * Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is\n * unavailable). Stage/prod use POST with browser session cookies.\n */\n\nimport { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';\n\nexport interface EdxSessionResult {\n viaxToken: string,\n customerUid: string,\n partyUid?: string,\n edxUserId?: string,\n username?: string,\n email?: string,\n}\n\n/** Hardcoded edX JWT used only for local/dev against Viax (same pattern as enroll/checkout MFEs). */\nconst DEV_SESSION_BODY = {\n payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc4NjEzNTQ1NywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzg2MTMxODU3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZGV2Z2FuIiwic2NvcGVzIjpbInVzZXJfaWQiLCJlbWFpbCIsInByb2ZpbGUiXSwidmVyc2lvbiI6IjEuMi4wIiwic3ViIjoiYmRlNjcwYTRiNmYxYjc0OTExYWZhZGY4NDM4YmFmZTkiLCJmaWx0ZXJzIjpbInVzZXI6bWUiXSwiaXNfcmVzdHJpY3RlZCI6ZmFsc2UsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJ1c2VyX2lkIjo1MjgzMTE5LCJlbWFpbCI6ImFkZXZnYW5AMnUuY29tIiwibmFtZSI6IkFrYXNoIERldmdhbiIsImZhbWlseV9uYW1lIjoiRGV2Z2FuIiwiZ2l2ZW5fbmFtZSI6IkFrYXNoIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',\n signature: 'RY64FgDMT-gRKJ6aObjUcocYqHjU3E2R_A2nxZL1BwJZgSDT1mMZMY_9HYZh8F0bAM9IFSQ1B3yP6PtcQnYsA2iYXK6_LyhG07l5qu6GRU7W99-Dq8CxLX9viJrKVj3CgGfc9bIUultlM-fjy-iZBTqDqe-DO2NHLvE-rd3b_d7cRTrhEtZ6HYkFWJXy5YOo8vxV46X4kM56jHGSq1Leixvc0ksa-NKn4AMHNSfGv_mQA16DN-Ou_uEl9CdHURGD4vOPDYE7xZt5JiwKZ3i1jzJfgMdpPgCYvYeC-5dr95_s-LaJnN6va9k3u9RFRnYKTfhHPgtSR4q7qTCzNABQqQ'\n};\n\nfunction parseSessionResponse(data: Record<string, unknown>): EdxSessionResult {\n const viaxToken = (\n data.viaxToken ?? data.token ?? data.access_token ?? data.accessToken\n ) as string | undefined;\n const customerUid = (data.customerUid ?? data.customer_uid) as string | undefined;\n\n if (!viaxToken) {\n throw new Error('Session response missing viax token.');\n }\n if (!customerUid) {\n throw new Error('Session response missing customerUid.');\n }\n\n return {\n viaxToken,\n customerUid,\n partyUid: data.partyUid as string | undefined,\n edxUserId: data.edxUserId as string | undefined,\n username: data.username as string | undefined,\n email: data.email as string | undefined,\n };\n}\n\nfunction isDevelopment(): boolean {\n return getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT;\n}\n\n/** LMS edx-session endpoint for the current site. */\nexport function getEdxSessionUrl(): string {\n return isDevelopment()\n ? 'https://courses.stage.edx.org/api/edx-session'\n : `${getSiteConfig().lmsBaseUrl}/api/edx-session`;\n}\n\n/** Exchange the learner's edX session for a Viax token. */\nexport async function fetchEdxSession(sessionUrl: string): Promise<EdxSessionResult> {\n const res = await fetch(sessionUrl, {\n method: 'POST',\n credentials: 'include',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: isDevelopment() ? JSON.stringify(DEV_SESSION_BODY) : undefined,\n });\n\n if (!res.ok) {\n throw new Error(\n `Failed to establish session (${res.status}). Please log into edX and try again.`,\n );\n }\n\n const data = await res.json() as Record<string, unknown> & { error?: string };\n if (data.error) {\n throw new Error(String(data.error));\n }\n\n return parseSessionResponse(data);\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format ISO date strings for manage-subscription copy.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Formats a date for display, e.g. "April 13, 2027".
|
|
6
|
+
* Uses the calendar date from YYYY-MM-DD to avoid timezone day-shift.
|
|
7
|
+
* Returns null when the value cannot be parsed.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatDisplayDate(value: string | null | undefined, locale?: string): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Formats a date as MM/DD/YYYY (en-US), e.g. "10/13/2026".
|
|
12
|
+
* Returns null when the value cannot be parsed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatNumericDate(value: string | null | undefined, locale?: string): string | null;
|
|
15
|
+
/** True when the ISO date is strictly in the future. */
|
|
16
|
+
export declare function isFutureDate(value: string | null | undefined): boolean;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format ISO date strings for manage-subscription copy.
|
|
3
|
+
*/
|
|
4
|
+
function parseDate(value) {
|
|
5
|
+
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})/.exec(value);
|
|
6
|
+
let date;
|
|
7
|
+
if (dateOnly) {
|
|
8
|
+
const year = Number(dateOnly[1]);
|
|
9
|
+
const month = Number(dateOnly[2]) - 1;
|
|
10
|
+
const day = Number(dateOnly[3]);
|
|
11
|
+
date = new Date(year, month, day);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
date = new Date(value);
|
|
15
|
+
}
|
|
16
|
+
if (Number.isNaN(date.getTime())) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return date;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Formats a date for display, e.g. "April 13, 2027".
|
|
23
|
+
* Uses the calendar date from YYYY-MM-DD to avoid timezone day-shift.
|
|
24
|
+
* Returns null when the value cannot be parsed.
|
|
25
|
+
*/
|
|
26
|
+
export function formatDisplayDate(value, locale = 'en-US') {
|
|
27
|
+
if (!value) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const date = parseDate(value);
|
|
31
|
+
if (!date) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return new Intl.DateTimeFormat(locale, {
|
|
35
|
+
month: 'long',
|
|
36
|
+
day: 'numeric',
|
|
37
|
+
year: 'numeric',
|
|
38
|
+
}).format(date);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Formats a date as MM/DD/YYYY (en-US), e.g. "10/13/2026".
|
|
42
|
+
* Returns null when the value cannot be parsed.
|
|
43
|
+
*/
|
|
44
|
+
export function formatNumericDate(value, locale = 'en-US') {
|
|
45
|
+
if (!value) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const date = parseDate(value);
|
|
49
|
+
if (!date) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return new Intl.DateTimeFormat(locale, {
|
|
53
|
+
month: '2-digit',
|
|
54
|
+
day: '2-digit',
|
|
55
|
+
year: 'numeric',
|
|
56
|
+
}).format(date);
|
|
57
|
+
}
|
|
58
|
+
/** True when the ISO date is strictly in the future. */
|
|
59
|
+
export function isFutureDate(value) {
|
|
60
|
+
if (!value) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const date = new Date(value);
|
|
64
|
+
if (Number.isNaN(date.getTime())) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return date.getTime() > Date.now();
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=formatDate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDate.js","sourceRoot":"","sources":["../../src/utils/formatDate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,QAAQ,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,IAAU,CAAC;IACf,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAgC,EAChC,MAAM,GAAG,OAAO;IAEhB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;QACrC,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAgC,EAChC,MAAM,GAAG,OAAO;IAEhB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;QACrC,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,KAAgC;IAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AACrC,CAAC","sourcesContent":["/**\n * Format ISO date strings for manage-subscription copy.\n */\n\nfunction parseDate(value: string): Date | null {\n const dateOnly = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value);\n let date: Date;\n if (dateOnly) {\n const year = Number(dateOnly[1]);\n const month = Number(dateOnly[2]) - 1;\n const day = Number(dateOnly[3]);\n date = new Date(year, month, day);\n } else {\n date = new Date(value);\n }\n\n if (Number.isNaN(date.getTime())) {\n return null;\n }\n return date;\n}\n\n/**\n * Formats a date for display, e.g. \"April 13, 2027\".\n * Uses the calendar date from YYYY-MM-DD to avoid timezone day-shift.\n * Returns null when the value cannot be parsed.\n */\nexport function formatDisplayDate(\n value: string | null | undefined,\n locale = 'en-US',\n): string | null {\n if (!value) {\n return null;\n }\n\n const date = parseDate(value);\n if (!date) {\n return null;\n }\n\n return new Intl.DateTimeFormat(locale, {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n }).format(date);\n}\n\n/**\n * Formats a date as MM/DD/YYYY (en-US), e.g. \"10/13/2026\".\n * Returns null when the value cannot be parsed.\n */\nexport function formatNumericDate(\n value: string | null | undefined,\n locale = 'en-US',\n): string | null {\n if (!value) {\n return null;\n }\n\n const date = parseDate(value);\n if (!date) {\n return null;\n }\n\n return new Intl.DateTimeFormat(locale, {\n month: '2-digit',\n day: '2-digit',\n year: 'numeric',\n }).format(date);\n}\n\n/** True when the ISO date is strictly in the future. */\nexport function isFutureDate(value: string | null | undefined): boolean {\n if (!value) {\n return false;\n }\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return false;\n }\n return date.getTime() > Date.now();\n}\n"]}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Minimal GraphQL client for VIAX.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* On 401 the token is cleared and the request fails — the mutation will
|
|
8
|
-
* surface the error and the user can retry.
|
|
4
|
+
* Authenticated calls (subscriber check, enrollments, cancel) require setToken()
|
|
5
|
+
* after exchanging the edX session for a Viax JWT.
|
|
9
6
|
*/
|
|
10
7
|
import type { GqlRunner } from '../types';
|
|
8
|
+
export interface ViaxGqlClient {
|
|
9
|
+
gql: GqlRunner;
|
|
10
|
+
setToken: (token: string | null) => void;
|
|
11
|
+
hasToken: () => boolean;
|
|
12
|
+
}
|
|
11
13
|
export declare function createGqlClient({ apiUrl }: {
|
|
12
14
|
apiUrl: string;
|
|
13
|
-
}):
|
|
14
|
-
gql: GqlRunner;
|
|
15
|
-
setToken: (token: string) => void;
|
|
16
|
-
};
|
|
15
|
+
}): ViaxGqlClient;
|