@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,40 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Alert, Col, Row } from '@openedx/paragon';
3
+ import { Error as ErrorIcon } from '@openedx/paragon/icons';
4
+ import useCheckout from '../../data/hooks/useCheckout';
5
+ import CartSummary from '../CartSummary/CartSummary';
6
+ import EnrollmentSummary from '../EnrollmentSummary/EnrollmentSummary';
7
+ import PaymentForm from '../PaymentForm/PaymentForm';
8
+ import { getPlanPrice, getRenewalLabel } from '../../utils/billingDetails';
9
+ import { getTrialDateRange } from '../../utils';
10
+ import { SuccessScreen, BlockedScreen } from '../StatusScreens/StatusScreens';
11
+ const Checkout = (props) => {
12
+ var _a, _b;
13
+ const c = useCheckout(props);
14
+ const showForm = c.phase === 'init'
15
+ || c.phase === 'ready'
16
+ || c.phase === 'failed'
17
+ || c.phase === 'processing';
18
+ const monthlyPrice = getPlanPrice(c.billingPlans, 'monthly');
19
+ const annualPrice = getPlanPrice(c.billingPlans, 'annual');
20
+ const isSubmitting = c.processingSubscription;
21
+ const { displayStart, displayEnd } = getTrialDateRange();
22
+ const handleStartCourse = () => {
23
+ var _a;
24
+ if ((_a = c.course) === null || _a === void 0 ? void 0 : _a.tUrlCourse) {
25
+ window.location.href = c.course.tUrlCourse;
26
+ }
27
+ else {
28
+ window.location.href = '/subscription-search';
29
+ }
30
+ };
31
+ const courseLabel = c.course
32
+ ? [c.course.tBrandText, c.course.maName].filter(Boolean).join(': ')
33
+ : null;
34
+ return (_jsxs(Row, { className: "checkout__container bg-light-200", children: [_jsx(Col, { xs: 12, className: "d-lg-none", children: _jsx("h1", { className: "font-weight-bold text-primary-900", children: "Checkout" }) }), _jsx(Col, { xs: 12, children: _jsxs(Row, { className: "flex-column-reverse gap-5 flex-lg-row", children: [_jsx(Col, { xs: 12, lg: 7, xxl: 9, className: "payment__options", children: _jsxs("div", { children: [_jsx("h1", { className: "font-weight-bold text-primary-900 d-none d-lg-block", children: "Checkout" }), c.error && (_jsx(Alert, { variant: "danger", icon: ErrorIcon, dismissible: true, onClose: c.clearError, children: c.error })), showForm && (_jsxs(_Fragment, { children: [c.phase === 'failed' && (_jsx(Alert, { variant: "danger", icon: ErrorIcon, className: "mb-3", children: c.lastComment
35
+ || 'Your payment could not be processed. Please check your card details and try again.' })), _jsx(PaymentForm, { billing: c.billing, setField: c.setField, numberMountRef: c.numberMountRef, expiryMountRef: c.expiryMountRef, cvcMountRef: c.cvcMountRef, cardError: c.cardError, stripeReady: c.stripeReady, sessionReady: c.sessionReady, submitting: isSubmitting, onPlaceOrder: c.placeOrder, trialEnd: displayEnd, priceToShow: c.selectedCycle === 'monthly' ? monthlyPrice : annualPrice, cycleToShow: c.selectedCycle === 'monthly' ? 'monthly' : 'annual', userCountry: c.userCountry })] })), c.phase === 'success' && (_jsx(SuccessScreen, { subscriptionBiId: ((_a = c.subscriptionDetails) === null || _a === void 0 ? void 0 : _a.biId) || '', cardLast4: ((_b = c.subscriptionDetails) === null || _b === void 0 ? void 0 : _b.cardLast4) || '', trialStart: displayStart, trialEnd: displayEnd, priceToShow: c.selectedCycle === 'monthly'
36
+ ? monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.label
37
+ : annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.label, cycleToShow: c.selectedCycle === 'monthly' ? 'monthly' : 'annual', courseLabel: courseLabel, onFindCourse: handleStartCourse })), c.phase === 'blocked' && (_jsx(BlockedScreen, { detail: c.lastComment }))] }) }), _jsx(Col, { xs: 12, lg: 5, xxl: 3, className: "payment__summary", children: c.phase === 'success' ? (_jsx(EnrollmentSummary, { course: c.course, onStartCourse: handleStartCourse })) : (_jsx(CartSummary, { monthlyRenewalLabel: getRenewalLabel(c.billingPlans, 'monthly'), annualRenewalLabel: getRenewalLabel(c.billingPlans, 'annual'), activeSubscriberCount: c.activeSubscriberCount, defaultCycle: c.selectedCycle, onCycleChange: c.setCycle, course: c.course })) })] }) })] }));
38
+ };
39
+ export default Checkout;
40
+ //# sourceMappingURL=Checkout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Checkout.js","sourceRoot":"","sources":["../../../src/components/Checkout/Checkout.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Alert, Col, Row } from '@openedx/paragon';\nimport { Error as ErrorIcon } from '@openedx/paragon/icons';\nimport useCheckout from '../../data/hooks/useCheckout';\nimport type { UseCheckoutOptions } from '../../data/hooks/useCheckout';\nimport CartSummary from '../CartSummary/CartSummary';\nimport EnrollmentSummary from '../EnrollmentSummary/EnrollmentSummary';\nimport PaymentForm from '../PaymentForm/PaymentForm';\nimport { getPlanPrice, getRenewalLabel } from '../../utils/billingDetails';\nimport { getTrialDateRange } from '@src/utils';\nimport { SuccessScreen, BlockedScreen } from '../StatusScreens/StatusScreens';\n\nexport type CheckoutProps = UseCheckoutOptions;\n\nconst Checkout = (props: CheckoutProps) => {\n const c = useCheckout(props);\n\n const showForm\n = c.phase === 'init'\n || c.phase === 'ready'\n || c.phase === 'failed'\n || c.phase === 'processing';\n const monthlyPrice = getPlanPrice(c.billingPlans, 'monthly');\n const annualPrice = getPlanPrice(c.billingPlans, 'annual');\n const isSubmitting = c.processingSubscription;\n\n const { displayStart, displayEnd } = getTrialDateRange();\n\n const handleStartCourse = () => {\n if (c.course?.tUrlCourse) {\n window.location.href = c.course.tUrlCourse;\n } else {\n window.location.href = '/subscription-search';\n }\n };\n\n const courseLabel = c.course\n ? [c.course.tBrandText, c.course.maName].filter(Boolean).join(': ')\n : null;\n\n return (\n <Row className=\"checkout__container bg-light-200\">\n <Col xs={12} className=\"d-lg-none\">\n <h1 className=\"font-weight-bold text-primary-900\">Checkout</h1>\n </Col>\n <Col xs={12}>\n <Row className=\"flex-column-reverse gap-5 flex-lg-row\">\n {/* ── LEFT ── */}\n <Col xs={12} lg={7} xxl={9} className=\"payment__options\">\n <div>\n <h1 className=\"font-weight-bold text-primary-900 d-none d-lg-block\">\n Checkout\n </h1>\n {c.error && (\n <Alert\n variant=\"danger\"\n icon={ErrorIcon}\n dismissible\n onClose={c.clearError}\n >\n {c.error}\n </Alert>\n )}\n\n {showForm && (\n <>\n {c.phase === 'failed' && (\n <Alert variant=\"danger\" icon={ErrorIcon} className=\"mb-3\">\n {c.lastComment\n || 'Your payment could not be processed. Please check your card details and try again.'}\n </Alert>\n )}\n <PaymentForm\n billing={c.billing}\n setField={c.setField}\n numberMountRef={c.numberMountRef}\n expiryMountRef={c.expiryMountRef}\n cvcMountRef={c.cvcMountRef}\n cardError={c.cardError}\n stripeReady={c.stripeReady}\n sessionReady={c.sessionReady}\n submitting={isSubmitting}\n onPlaceOrder={c.placeOrder}\n trialEnd={displayEnd}\n priceToShow={\n c.selectedCycle === 'monthly' ? monthlyPrice : annualPrice\n }\n cycleToShow={\n c.selectedCycle === 'monthly' ? 'monthly' : 'annual'\n }\n userCountry={c.userCountry}\n />\n </>\n )}\n\n {c.phase === 'success' && (\n <SuccessScreen\n subscriptionBiId={c.subscriptionDetails?.biId || ''}\n cardLast4={c.subscriptionDetails?.cardLast4 || ''}\n trialStart={displayStart}\n trialEnd={displayEnd}\n priceToShow={\n c.selectedCycle === 'monthly'\n ? monthlyPrice?.label\n : annualPrice?.label\n }\n cycleToShow={\n c.selectedCycle === 'monthly' ? 'monthly' : 'annual'\n }\n courseLabel={courseLabel}\n onFindCourse={handleStartCourse}\n />\n )}\n\n {c.phase === 'blocked' && (\n <BlockedScreen detail={c.lastComment} />\n )}\n </div>\n </Col>\n\n {/* ── RIGHT — swaps to EnrollmentSummary on success ── */}\n <Col xs={12} lg={5} xxl={3} className=\"payment__summary\">\n {c.phase === 'success' ? (\n <EnrollmentSummary\n course={c.course}\n onStartCourse={handleStartCourse}\n />\n ) : (\n <CartSummary\n monthlyRenewalLabel={getRenewalLabel(c.billingPlans, 'monthly')}\n annualRenewalLabel={getRenewalLabel(c.billingPlans, 'annual')}\n activeSubscriberCount={c.activeSubscriberCount}\n defaultCycle={c.selectedCycle}\n onCycleChange={c.setCycle}\n course={c.course}\n />\n )}\n </Col>\n </Row>\n </Col>\n </Row>\n );\n};\n\nexport default Checkout;\n"]}
@@ -0,0 +1,7 @@
1
+ import type { CheckoutProps } from '../Checkout/Checkout';
2
+ export interface CheckoutGateProps extends CheckoutProps {
3
+ /** URL linked in the "not available in your country" message. */
4
+ learnerDashboardUrl?: string;
5
+ }
6
+ declare const CheckoutGate: ({ learnerDashboardUrl, ...checkoutProps }: CheckoutGateProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default CheckoutGate;
@@ -0,0 +1,35 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { Alert, Spinner } from '@openedx/paragon';
14
+ import { Error as ErrorIcon } from '@openedx/paragon/icons';
15
+ import { useCheckoutGate } from '../../data/hooks/useCheckoutGate';
16
+ import Checkout from '../Checkout/Checkout';
17
+ const CheckoutGate = (_a) => {
18
+ var { learnerDashboardUrl } = _a, checkoutProps = __rest(_a, ["learnerDashboardUrl"]);
19
+ const { gateStatus, userCountry, errorMessage } = useCheckoutGate({
20
+ edxSessionUrl: checkoutProps.edxSessionUrl,
21
+ learnerDashboardUrl,
22
+ });
23
+ if (gateStatus === 'loading') {
24
+ return (_jsx("div", { className: "d-flex justify-content-center align-items-center", style: { minHeight: '100vh' }, children: _jsx(Spinner, { animation: "border", screenReaderText: "Checking your account\u2026" }) }));
25
+ }
26
+ if (gateStatus === 'error') {
27
+ return (_jsxs(Alert, { variant: "danger", icon: ErrorIcon, children: [errorMessage !== null && errorMessage !== void 0 ? errorMessage : 'We\u2019re having trouble loading checkout. Please refresh and try again.', ' ', learnerDashboardUrl && (_jsx("a", { href: learnerDashboardUrl, className: "alert-link", children: "Go to your learner dashboard" }))] }));
28
+ }
29
+ if (gateStatus === 'blocked') {
30
+ return (_jsxs(Alert, { variant: "danger", icon: ErrorIcon, children: ["Subscription is not available in your country.", ' ', learnerDashboardUrl && (_jsx("a", { href: learnerDashboardUrl, className: "alert-link", children: "Go to your learner dashboard" }))] }));
31
+ }
32
+ return _jsx(Checkout, Object.assign({}, checkoutProps, { userCountry: userCountry }));
33
+ };
34
+ export default CheckoutGate;
35
+ //# sourceMappingURL=CheckoutGate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckoutGate.js","sourceRoot":"","sources":["../../../src/components/CheckoutGate/CheckoutGate.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAQ5C,MAAM,YAAY,GAAG,CAAC,EAGF,EAAE,EAAE;QAHF,EACpB,mBAAmB,OAED,EADf,aAAa,cAFI,uBAGrB,CADiB;IAEhB,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC;QAChE,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,mBAAmB;KACpB,CAAC,CAAC;IAEH,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,cACE,SAAS,EAAC,kDAAkD,EAC5D,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,YAE7B,KAAC,OAAO,IAAC,SAAS,EAAC,QAAQ,EAAC,gBAAgB,EAAC,6BAAwB,GAAG,GACpE,CACP,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,EAAC,IAAI,EAAE,SAAS,aACpC,YAAY,aAAZ,YAAY,cAAZ,YAAY,GACV,2EAA2E,EAAE,GAAG,EAClF,mBAAmB,IAAI,CACtB,YAAG,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAC,YAAY,6CAEhD,CACL,IACK,CACT,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,EAAC,IAAI,EAAE,SAAS,+DACU,GAAG,EACjD,mBAAmB,IAAI,CACtB,YAAG,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAC,YAAY,6CAEhD,CACL,IACK,CACT,CAAC;IACJ,CAAC;IAED,OAAO,KAAC,QAAQ,oBAAK,aAAa,IAAE,WAAW,EAAE,WAAW,IAAI,CAAC;AACnE,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import { Alert, Spinner } from '@openedx/paragon';\nimport { Error as ErrorIcon } from '@openedx/paragon/icons';\nimport { useCheckoutGate } from '../../data/hooks/useCheckoutGate';\nimport Checkout from '../Checkout/Checkout';\nimport type { CheckoutProps } from '../Checkout/Checkout';\n\nexport interface CheckoutGateProps extends CheckoutProps {\n /** URL linked in the \"not available in your country\" message. */\n learnerDashboardUrl?: string,\n}\n\nconst CheckoutGate = ({\n learnerDashboardUrl,\n ...checkoutProps\n}: CheckoutGateProps) => {\n const { gateStatus, userCountry, errorMessage } = useCheckoutGate({\n edxSessionUrl: checkoutProps.edxSessionUrl,\n learnerDashboardUrl,\n });\n\n if (gateStatus === 'loading') {\n return (\n <div\n className=\"d-flex justify-content-center align-items-center\"\n style={{ minHeight: '100vh' }}\n >\n <Spinner animation=\"border\" screenReaderText=\"Checking your account…\" />\n </div>\n );\n }\n\n if (gateStatus === 'error') {\n return (\n <Alert variant=\"danger\" icon={ErrorIcon}>\n {errorMessage\n ?? 'We\\u2019re having trouble loading checkout. Please refresh and try again.'}{' '}\n {learnerDashboardUrl && (\n <a href={learnerDashboardUrl} className=\"alert-link\">\n Go to your learner dashboard\n </a>\n )}\n </Alert>\n );\n }\n\n if (gateStatus === 'blocked') {\n return (\n <Alert variant=\"danger\" icon={ErrorIcon}>\n Subscription is not available in your country.{' '}\n {learnerDashboardUrl && (\n <a href={learnerDashboardUrl} className=\"alert-link\">\n Go to your learner dashboard\n </a>\n )}\n </Alert>\n );\n }\n\n return <Checkout {...checkoutProps} userCountry={userCountry} />;\n};\n\nexport default CheckoutGate;\n"]}
@@ -0,0 +1,9 @@
1
+ import type { CourseDetail } from '../../types';
2
+ export type CourseEnrollmentCardVariant = 'checkout' | 'success';
3
+ export interface CourseEnrollmentCardProps {
4
+ course: CourseDetail;
5
+ variant?: CourseEnrollmentCardVariant;
6
+ onStartCourse?: () => void;
7
+ }
8
+ declare const CourseEnrollmentCard: ({ course, variant, onStartCourse, }: CourseEnrollmentCardProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default CourseEnrollmentCard;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from '@openedx/paragon';
3
+ import { useIntl } from '@openedx/frontend-base';
4
+ import messages from './Messages';
5
+ const CourseEnrollmentCard = ({ course, variant = 'checkout', onStartCourse, }) => {
6
+ var _a, _b;
7
+ const { formatMessage } = useIntl();
8
+ const brand = (_b = (_a = course.tBrandText) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
9
+ const courseName = course.maName;
10
+ const handleStartCourse = () => {
11
+ if (onStartCourse) {
12
+ onStartCourse();
13
+ return;
14
+ }
15
+ if (course.tUrlCourse) {
16
+ window.location.href = course.tUrlCourse;
17
+ }
18
+ else {
19
+ window.location.href = '/subscription-search';
20
+ }
21
+ };
22
+ const checkoutCopy = brand
23
+ ? formatMessage(messages.checkoutEnrollCopy, { brand, courseName })
24
+ : formatMessage(messages.checkoutEnrollCopyNoBrand, { courseName });
25
+ const successLabel = brand
26
+ ? formatMessage(messages.successCourseLabel, { brand, courseName })
27
+ : formatMessage(messages.successCourseLabelNoBrand, { courseName });
28
+ return (_jsx("div", { className: `course-enrollment-card course-enrollment-card--${variant}`, children: _jsxs("div", { className: "course-enrollment-card__body d-flex align-items-start", children: [_jsx("div", { className: "course-enrollment-card__image-wrap flex-shrink-0 mr-3", children: course.imageUrl ? (_jsx("img", { src: course.imageUrl, alt: formatMessage(messages.courseImageAlt, { courseName }), className: "course-enrollment-card__image" })) : (_jsx("div", { className: "course-enrollment-card__image course-enrollment-card__image--placeholder", "aria-hidden": "true" })) }), _jsx("div", { className: "course-enrollment-card__content flex-grow-1", children: variant === 'checkout' ? (_jsx("p", { className: "course-enrollment-card__copy mb-0 small", children: checkoutCopy })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "course-enrollment-card__copy font-weight-bold mb-2 small", children: successLabel }), _jsx(Button, { variant: "brand", size: "sm", className: "course-enrollment-card__cta", onClick: handleStartCourse, disabled: !course.tUrlCourse && !onStartCourse, children: formatMessage(messages.startCourse) })] })) })] }) }));
29
+ };
30
+ export default CourseEnrollmentCard;
31
+ //# sourceMappingURL=CourseEnrollmentCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CourseEnrollmentCard.js","sourceRoot":"","sources":["../../../src/components/CourseEnrollmentCard/CourseEnrollmentCard.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAUlC,MAAM,oBAAoB,GAAG,CAAC,EAC5B,MAAM,EACN,OAAO,GAAG,UAAU,EACpB,aAAa,GACa,EAAE,EAAE;;IAC9B,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,MAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,IAAI,EAAE,mCAAI,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IAEjC,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,sBAAsB,CAAC;QAChD,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK;QACxB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACnE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,yBAAyB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IAEtE,MAAM,YAAY,GAAG,KAAK;QACxB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACnE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,yBAAyB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IAEtE,OAAO,CACL,cACE,SAAS,EAAE,kDAAkD,OAAO,EAAE,YAEtE,eAAK,SAAS,EAAC,uDAAuD,aACpE,cAAK,SAAS,EAAC,uDAAuD,YACnE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CACjB,cACE,GAAG,EAAE,MAAM,CAAC,QAAQ,EACpB,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC,EAC3D,SAAS,EAAC,+BAA+B,GACzC,CACH,CAAC,CAAC,CAAC,CACF,cACE,SAAS,EAAC,0EAA0E,iBACxE,MAAM,GAClB,CACH,GACG,EAEN,cAAK,SAAS,EAAC,6CAA6C,YACzD,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,CACxB,YAAG,SAAS,EAAC,yCAAyC,YACnD,YAAY,GACX,CACL,CAAC,CAAC,CAAC,CACF,8BACE,YAAG,SAAS,EAAC,0DAA0D,YACpE,YAAY,GACX,EACJ,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,IAAI,EACT,SAAS,EAAC,6BAA6B,EACvC,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,aAAa,YAE7C,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAC7B,IACR,CACJ,GACG,IACF,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,oBAAoB,CAAC","sourcesContent":["import React from 'react';\nimport { Button } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport type { CourseDetail } from '../../types';\nimport messages from './Messages';\n\nexport type CourseEnrollmentCardVariant = 'checkout' | 'success';\n\nexport interface CourseEnrollmentCardProps {\n course: CourseDetail,\n variant?: CourseEnrollmentCardVariant,\n onStartCourse?: () => void,\n}\n\nconst CourseEnrollmentCard = ({\n course,\n variant = 'checkout',\n onStartCourse,\n}: CourseEnrollmentCardProps) => {\n const { formatMessage } = useIntl();\n const brand = course.tBrandText?.trim() ?? '';\n const courseName = course.maName;\n\n const handleStartCourse = () => {\n if (onStartCourse) {\n onStartCourse();\n return;\n }\n if (course.tUrlCourse) {\n window.location.href = course.tUrlCourse;\n } else {\n window.location.href = '/subscription-search';\n }\n };\n\n const checkoutCopy = brand\n ? formatMessage(messages.checkoutEnrollCopy, { brand, courseName })\n : formatMessage(messages.checkoutEnrollCopyNoBrand, { courseName });\n\n const successLabel = brand\n ? formatMessage(messages.successCourseLabel, { brand, courseName })\n : formatMessage(messages.successCourseLabelNoBrand, { courseName });\n\n return (\n <div\n className={`course-enrollment-card course-enrollment-card--${variant}`}\n >\n <div className=\"course-enrollment-card__body d-flex align-items-start\">\n <div className=\"course-enrollment-card__image-wrap flex-shrink-0 mr-3\">\n {course.imageUrl ? (\n <img\n src={course.imageUrl}\n alt={formatMessage(messages.courseImageAlt, { courseName })}\n className=\"course-enrollment-card__image\"\n />\n ) : (\n <div\n className=\"course-enrollment-card__image course-enrollment-card__image--placeholder\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n\n <div className=\"course-enrollment-card__content flex-grow-1\">\n {variant === 'checkout' ? (\n <p className=\"course-enrollment-card__copy mb-0 small\">\n {checkoutCopy}\n </p>\n ) : (\n <>\n <p className=\"course-enrollment-card__copy font-weight-bold mb-2 small\">\n {successLabel}\n </p>\n <Button\n variant=\"brand\"\n size=\"sm\"\n className=\"course-enrollment-card__cta\"\n onClick={handleStartCourse}\n disabled={!course.tUrlCourse && !onStartCourse}\n >\n {formatMessage(messages.startCourse)}\n </Button>\n </>\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default CourseEnrollmentCard;\n"]}
@@ -0,0 +1,33 @@
1
+ declare const messages: {
2
+ checkoutEnrollCopy: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ checkoutEnrollCopyNoBrand: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ successCourseLabel: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ successCourseLabelNoBrand: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ startCourse: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ courseImageAlt: {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ };
33
+ export default messages;
@@ -0,0 +1,35 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ checkoutEnrollCopy: {
4
+ id: 'checkout.courseEnrollmentCard.checkoutEnrollCopy',
5
+ defaultMessage: "After checkout you'll be enrolled in {brand}: {courseName}.",
6
+ description: 'Enrollment preview copy on the checkout summary sidebar',
7
+ },
8
+ checkoutEnrollCopyNoBrand: {
9
+ id: 'checkout.courseEnrollmentCard.checkoutEnrollCopyNoBrand',
10
+ defaultMessage: "After checkout you'll be enrolled in {courseName}.",
11
+ description: 'Enrollment preview copy when partner brand is unavailable',
12
+ },
13
+ successCourseLabel: {
14
+ id: 'checkout.courseEnrollmentCard.successCourseLabel',
15
+ defaultMessage: '{brand}: {courseName}.',
16
+ description: 'Course label on the post-checkout enrollment card',
17
+ },
18
+ successCourseLabelNoBrand: {
19
+ id: 'checkout.courseEnrollmentCard.successCourseLabelNoBrand',
20
+ defaultMessage: '{courseName}.',
21
+ description: 'Course label on the post-checkout card when partner brand is unavailable',
22
+ },
23
+ startCourse: {
24
+ id: 'checkout.courseEnrollmentCard.startCourse',
25
+ defaultMessage: 'Start course',
26
+ description: 'CTA to open the enrolled course after checkout',
27
+ },
28
+ courseImageAlt: {
29
+ id: 'checkout.courseEnrollmentCard.courseImageAlt',
30
+ defaultMessage: 'Course image for {courseName}',
31
+ description: 'Alt text for the course card thumbnail',
32
+ },
33
+ });
34
+ export default messages;
35
+ //# sourceMappingURL=Messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/CourseEnrollmentCard/Messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,kBAAkB,EAAE;QAClB,EAAE,EAAE,kDAAkD;QACtD,cAAc,EAAE,6DAA6D;QAC7E,WAAW,EAAE,yDAAyD;KACvE;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,yDAAyD;QAC7D,cAAc,EAAE,oDAAoD;QACpE,WAAW,EAAE,2DAA2D;KACzE;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,kDAAkD;QACtD,cAAc,EAAE,wBAAwB;QACxC,WAAW,EAAE,mDAAmD;KACjE;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,yDAAyD;QAC7D,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,0EAA0E;KACxF;IACD,WAAW,EAAE;QACX,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,gDAAgD;KAC9D;IACD,cAAc,EAAE;QACd,EAAE,EAAE,8CAA8C;QAClD,cAAc,EAAE,+BAA+B;QAC/C,WAAW,EAAE,wCAAwC;KACtD;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n checkoutEnrollCopy: {\n id: 'checkout.courseEnrollmentCard.checkoutEnrollCopy',\n defaultMessage: \"After checkout you'll be enrolled in {brand}: {courseName}.\",\n description: 'Enrollment preview copy on the checkout summary sidebar',\n },\n checkoutEnrollCopyNoBrand: {\n id: 'checkout.courseEnrollmentCard.checkoutEnrollCopyNoBrand',\n defaultMessage: \"After checkout you'll be enrolled in {courseName}.\",\n description: 'Enrollment preview copy when partner brand is unavailable',\n },\n successCourseLabel: {\n id: 'checkout.courseEnrollmentCard.successCourseLabel',\n defaultMessage: '{brand}: {courseName}.',\n description: 'Course label on the post-checkout enrollment card',\n },\n successCourseLabelNoBrand: {\n id: 'checkout.courseEnrollmentCard.successCourseLabelNoBrand',\n defaultMessage: '{courseName}.',\n description: 'Course label on the post-checkout card when partner brand is unavailable',\n },\n startCourse: {\n id: 'checkout.courseEnrollmentCard.startCourse',\n defaultMessage: 'Start course',\n description: 'CTA to open the enrolled course after checkout',\n },\n courseImageAlt: {\n id: 'checkout.courseEnrollmentCard.courseImageAlt',\n defaultMessage: 'Course image for {courseName}',\n description: 'Alt text for the course card thumbnail',\n },\n});\n\nexport default messages;\n"]}
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface EdxUnlimitedBannerProps {
3
+ headlinePre?: string;
4
+ headlinePost?: string;
5
+ body?: string;
6
+ ctaLabel?: string;
7
+ ctaHref?: string;
8
+ imageUrl?: string;
9
+ imageAlt?: string;
10
+ setShowLandingPage?: (show: boolean) => void;
11
+ }
12
+ declare const EdxUnlimitedBanner: React.FC<EdxUnlimitedBannerProps>;
13
+ export default EdxUnlimitedBanner;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const EdxUnlimitedBadge = () => (_jsxs("span", { className: "edx-banner__badge", "aria-label": "edX unlimited", children: [_jsx("span", { className: "edx-banner__badge-edx", children: "edX" }), _jsx("span", { className: "edx-banner__badge-unlimited", children: "unlimited" })] }));
3
+ const BulletIcon = () => (_jsx("span", { className: "edx-banner__bullet", "aria-hidden": "true", children: _jsxs("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: [_jsx("circle", { cx: "6", cy: "6", r: "3", fill: "#fff" }), _jsx("circle", { cx: "6", cy: "1.5", r: "1.5", fill: "#fff" }), _jsx("circle", { cx: "6", cy: "10.5", r: "1.5", fill: "#fff" }), _jsx("circle", { cx: "1.5", cy: "6", r: "1.5", fill: "#fff" }), _jsx("circle", { cx: "10.5", cy: "6", r: "1.5", fill: "#fff" })] }) }));
4
+ const EdxUnlimitedBanner = ({ headlinePre = 'Never stop learning with', headlinePost = '', body = 'Access 850 courses and programs from world-class institutions — all included for $39 a month. Expand your skills, grow your career, and keep learning for life.', ctaLabel = 'Start 7-day free trial', ctaHref = '#', imageUrl, imageAlt = 'Student learning online', setShowLandingPage, }) => (_jsxs("div", { className: "edx-banner", children: [_jsxs("div", { className: "edx-banner__content", children: [_jsxs("div", { className: "edx-banner__eyebrow", children: [_jsx(BulletIcon, {}), _jsxs("h2", { className: "edx-banner__headline", children: [headlinePre, " ", _jsx(EdxUnlimitedBadge, {}), headlinePost && ` ${headlinePost}`] })] }), _jsx("p", { className: "edx-banner__body", children: body }), _jsx("div", { className: "edx-banner__cta-wrapper", children: _jsx("a", { href: ctaHref, className: "edx-banner__cta", onClick: setShowLandingPage
5
+ ? (e) => {
6
+ e.preventDefault();
7
+ setShowLandingPage(false);
8
+ }
9
+ : undefined, children: ctaLabel }) })] }), imageUrl && (_jsx("div", { className: "edx-banner__photo", "aria-hidden": "true", children: _jsx("img", { src: imageUrl, alt: imageAlt }) })), !imageUrl && (_jsx("div", { className: "edx-banner__placeholder", "aria-hidden": "true", children: _jsxs("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", opacity: "0.3", children: [_jsx("rect", { x: "8", y: "8", width: "32", height: "32", rx: "16", stroke: "#fff", strokeWidth: "2" }), _jsx("path", { d: "M24 20a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM12 36c0-6.627 5.373-12 12-12s12 5.373 12 12", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round" })] }) }))] }));
10
+ export default EdxUnlimitedBanner;
11
+ //# sourceMappingURL=EdxUnlimitedBanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EdxUnlimitedBanner.js","sourceRoot":"","sources":["../../../src/components/EdxUnlimitedBanner/EdxUnlimitedBanner.tsx"],"names":[],"mappings":";AAaA,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,CAC9B,gBAAM,SAAS,EAAC,mBAAmB,gBAAY,eAAe,aAC5D,eAAM,SAAS,EAAC,uBAAuB,oBAAW,EAClD,eAAM,SAAS,EAAC,6BAA6B,0BAAiB,IACzD,CACR,CAAC;AAEF,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,CACvB,eAAM,SAAS,EAAC,oBAAoB,iBAAa,MAAM,YACrD,eAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,aACzD,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,MAAM,GAAG,EAC1C,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,KAAK,EAAC,CAAC,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAG,EAC9C,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAG,EAC/C,iBAAQ,EAAE,EAAC,KAAK,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAG,EAC9C,iBAAQ,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAG,IAC3C,GACD,CACR,CAAC;AAEF,MAAM,kBAAkB,GAAsC,CAAC,EAC7D,WAAW,GAAG,0BAA0B,EACxC,YAAY,GAAG,EAAE,EACjB,IAAI,GAAG,iKAAiK,EACxK,QAAQ,GAAG,wBAAwB,EACnC,OAAO,GAAG,GAAG,EACb,QAAQ,EACR,QAAQ,GAAG,yBAAyB,EACpC,kBAAkB,GACnB,EAAE,EAAE,CAAC,CACJ,eAAK,SAAS,EAAC,YAAY,aAEzB,eAAK,SAAS,EAAC,qBAAqB,aAClC,eAAK,SAAS,EAAC,qBAAqB,aAClC,KAAC,UAAU,KAAG,EACd,cAAI,SAAS,EAAC,sBAAsB,aACjC,WAAW,OAAE,KAAC,iBAAiB,KAAG,EAClC,YAAY,IAAI,IAAI,YAAY,EAAE,IAChC,IACD,EAEN,YAAG,SAAS,EAAC,kBAAkB,YAAE,IAAI,GAAK,EAE1C,cAAK,SAAS,EAAC,yBAAyB,YACtC,YACE,IAAI,EAAE,OAAO,EACb,SAAS,EAAC,iBAAiB,EAC3B,OAAO,EACL,kBAAkB;4BAChB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE;gCACJ,CAAC,CAAC,cAAc,EAAE,CAAC;gCACnB,kBAAkB,CAAC,KAAK,CAAC,CAAC;4BAC5B,CAAC;4BACH,CAAC,CAAC,SAAS,YAGd,QAAQ,GACP,GACA,IACF,EAGL,QAAQ,IAAI,CACX,cAAK,SAAS,EAAC,mBAAmB,iBAAa,MAAM,YACnD,cAAK,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,GAAI,GACjC,CACP,EAGA,CAAC,QAAQ,IAAI,CACZ,cAAK,SAAS,EAAC,yBAAyB,iBAAa,MAAM,YACzD,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,KAAK,aAEb,eACE,CAAC,EAAC,GAAG,EACL,CAAC,EAAC,GAAG,EACL,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,EAAE,EAAC,IAAI,EACP,MAAM,EAAC,MAAM,EACb,WAAW,EAAC,GAAG,GACf,EACF,eACE,CAAC,EAAC,iFAAiF,EACnF,MAAM,EAAC,MAAM,EACb,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,GACF,CACP,IACG,CACP,CAAC;AAEF,eAAe,kBAAkB,CAAC","sourcesContent":["import React from 'react';\n\ninterface EdxUnlimitedBannerProps {\n headlinePre?: string,\n headlinePost?: string,\n body?: string,\n ctaLabel?: string,\n ctaHref?: string,\n imageUrl?: string,\n imageAlt?: string,\n setShowLandingPage?: (show: boolean) => void,\n}\n\nconst EdxUnlimitedBadge = () => (\n <span className=\"edx-banner__badge\" aria-label=\"edX unlimited\">\n <span className=\"edx-banner__badge-edx\">edX</span>\n <span className=\"edx-banner__badge-unlimited\">unlimited</span>\n </span>\n);\n\nconst BulletIcon = () => (\n <span className=\"edx-banner__bullet\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <circle cx=\"6\" cy=\"6\" r=\"3\" fill=\"#fff\" />\n <circle cx=\"6\" cy=\"1.5\" r=\"1.5\" fill=\"#fff\" />\n <circle cx=\"6\" cy=\"10.5\" r=\"1.5\" fill=\"#fff\" />\n <circle cx=\"1.5\" cy=\"6\" r=\"1.5\" fill=\"#fff\" />\n <circle cx=\"10.5\" cy=\"6\" r=\"1.5\" fill=\"#fff\" />\n </svg>\n </span>\n);\n\nconst EdxUnlimitedBanner: React.FC<EdxUnlimitedBannerProps> = ({\n headlinePre = 'Never stop learning with',\n headlinePost = '',\n body = 'Access 850 courses and programs from world-class institutions — all included for $39 a month. Expand your skills, grow your career, and keep learning for life.',\n ctaLabel = 'Start 7-day free trial',\n ctaHref = '#',\n imageUrl,\n imageAlt = 'Student learning online',\n setShowLandingPage,\n}) => (\n <div className=\"edx-banner\">\n {/* ── Left: text content ── */}\n <div className=\"edx-banner__content\">\n <div className=\"edx-banner__eyebrow\">\n <BulletIcon />\n <h2 className=\"edx-banner__headline\">\n {headlinePre} <EdxUnlimitedBadge />\n {headlinePost && ` ${headlinePost}`}\n </h2>\n </div>\n\n <p className=\"edx-banner__body\">{body}</p>\n\n <div className=\"edx-banner__cta-wrapper\">\n <a\n href={ctaHref}\n className=\"edx-banner__cta\"\n onClick={\n setShowLandingPage\n ? (e) => {\n e.preventDefault();\n setShowLandingPage(false);\n }\n : undefined\n }\n >\n {ctaLabel}\n </a>\n </div>\n </div>\n\n {/* ── Right: photo ── */}\n {imageUrl && (\n <div className=\"edx-banner__photo\" aria-hidden=\"true\">\n <img src={imageUrl} alt={imageAlt} />\n </div>\n )}\n\n {/* Placeholder when no imageUrl */}\n {!imageUrl && (\n <div className=\"edx-banner__placeholder\" aria-hidden=\"true\">\n <svg\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n opacity=\"0.3\"\n >\n <rect\n x=\"8\"\n y=\"8\"\n width=\"32\"\n height=\"32\"\n rx=\"16\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n />\n <path\n d=\"M24 20a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM12 36c0-6.627 5.373-12 12-12s12 5.373 12 12\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n </div>\n )}\n </div>\n);\n\nexport default EdxUnlimitedBanner;\n"]}
@@ -0,0 +1,15 @@
1
+ import type { CourseDetail } from '../../types';
2
+ export interface EnrollmentSummaryProps {
3
+ productTitle?: string;
4
+ productBlurb?: string;
5
+ /** e.g. "39" */
6
+ amount?: string;
7
+ /** e.g. "USD" */
8
+ currency?: string;
9
+ cycleToShow?: string;
10
+ /** When set, shows the enrolled course card below the purchase summary. */
11
+ course?: CourseDetail | null;
12
+ onStartCourse?: () => void;
13
+ }
14
+ declare const EnrollmentSummary: ({ productTitle, productBlurb, amount, currency, cycleToShow, course, onStartCourse, }: EnrollmentSummaryProps) => import("react/jsx-runtime").JSX.Element;
15
+ export default EnrollmentSummary;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card } from '@openedx/paragon';
3
+ import { useIntl } from '@openedx/frontend-base';
4
+ import { EdxUnlimitedLogo } from '../BrandMarks/BrandMarks';
5
+ import CourseEnrollmentCard from '../CourseEnrollmentCard/CourseEnrollmentCard';
6
+ import messages from './Messages';
7
+ const EnrollmentSummary = ({ productTitle = 'edX Subscription', productBlurb = 'Subscribe and get access to hundreds of courses and programs.', amount, currency = 'USD', cycleToShow = 'monthly', course = null, onStartCourse, }) => {
8
+ const { formatMessage } = useIntl();
9
+ const isMonthly = cycleToShow === 'monthly';
10
+ const frequency = isMonthly ? 'month' : 'year';
11
+ const cycleLabel = isMonthly
12
+ ? formatMessage(messages.monthlySubscription)
13
+ : formatMessage(messages.annualSubscription);
14
+ return (_jsxs("div", { className: "enrollment-summary", children: [_jsxs(Card, { className: "enrollment-summary", children: [_jsxs(Card.Section, { children: [_jsx("p", { className: "font-weight-bold mb-3", children: formatMessage(messages.purchaseSummary) }), _jsxs("div", { className: "d-flex align-items-start mb-3", children: [_jsx(EdxUnlimitedLogo, {}), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-1", style: { fontSize: '0.9rem' }, children: productTitle }), _jsx("p", { className: "text-muted mb-0", style: { fontSize: '0.82rem' }, children: productBlurb })] })] }), _jsxs("div", { className: "d-flex justify-content-between align-items-center mb-1", children: [_jsx("span", { className: "small text-muted", children: cycleLabel }), amount && (_jsx("span", { className: "small font-weight-bold", children: formatMessage(messages.priceDisplay, {
15
+ amount,
16
+ frequency,
17
+ currency,
18
+ }) }))] })] }), _jsx(Card.Divider, {}), _jsxs(Card.Section, { className: "d-flex justify-content-between align-items-center", children: [_jsx("span", { className: "font-weight-bold", children: formatMessage(messages.todaysTotal) }), _jsx("span", { className: "font-weight-bold text-success", children: formatMessage(messages.todaysTotalValue) })] })] }), course && (_jsx(CourseEnrollmentCard, { course: course, variant: "success", onStartCourse: onStartCourse }))] }));
19
+ };
20
+ export default EnrollmentSummary;
21
+ //# sourceMappingURL=EnrollmentSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnrollmentSummary.js","sourceRoot":"","sources":["../../../src/components/EnrollmentSummary/EnrollmentSummary.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,oBAAoB,MAAM,8CAA8C,CAAC;AAEhF,OAAO,QAAQ,MAAM,YAAY,CAAC;AAelC,MAAM,iBAAiB,GAAG,CAAC,EACzB,YAAY,GAAG,kBAAkB,EACjC,YAAY,GAAG,+DAA+D,EAC9E,MAAM,EACN,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,SAAS,EACvB,MAAM,GAAG,IAAI,EACb,aAAa,GACU,EAAE,EAAE;IAC3B,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IAEpC,MAAM,SAAS,GAAG,WAAW,KAAK,SAAS,CAAC;IAC5C,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,UAAU,GAAG,SAAS;QAC1B,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAC7C,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAE/C,OAAO,CACL,eAAK,SAAS,EAAC,oBAAoB,aACjC,MAAC,IAAI,IAAC,SAAS,EAAC,oBAAoB,aAClC,MAAC,IAAI,CAAC,OAAO,eACX,YAAG,SAAS,EAAC,uBAAuB,YACjC,aAAa,CAAC,QAAQ,CAAC,eAAe,CAAC,GACtC,EAEJ,eAAK,SAAS,EAAC,+BAA+B,aAC5C,KAAC,gBAAgB,KAAG,EACpB,0BACE,YAAG,SAAS,EAAC,uBAAuB,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAC/D,YAAY,GACX,EACJ,YAAG,SAAS,EAAC,iBAAiB,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,YAC1D,YAAY,GACX,IACA,IACF,EAEN,eAAK,SAAS,EAAC,wDAAwD,aACrE,eAAM,SAAS,EAAC,kBAAkB,YAAE,UAAU,GAAQ,EACrD,MAAM,IAAI,CACT,eAAM,SAAS,EAAC,wBAAwB,YACrC,aAAa,CAAC,QAAQ,CAAC,YAAY,EAAE;4CACpC,MAAM;4CACN,SAAS;4CACT,QAAQ;yCACT,CAAC,GACG,CACR,IACG,IACO,EAEf,KAAC,IAAI,CAAC,OAAO,KAAG,EAEhB,MAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAC,mDAAmD,aACzE,eAAM,SAAS,EAAC,kBAAkB,YAC/B,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAC/B,EACP,eAAM,SAAS,EAAC,+BAA+B,YAC5C,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GACpC,IACM,IACV,EAEN,MAAM,IAAI,CACT,KAAC,oBAAoB,IACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAC,SAAS,EACjB,aAAa,EAAE,aAAa,GAC5B,CACH,IACG,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC","sourcesContent":["import React from 'react';\nimport { Card } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { EdxUnlimitedLogo } from '../BrandMarks/BrandMarks';\nimport CourseEnrollmentCard from '../CourseEnrollmentCard/CourseEnrollmentCard';\nimport type { CourseDetail } from '../../types';\nimport messages from './Messages';\n\nexport interface EnrollmentSummaryProps {\n productTitle?: string,\n productBlurb?: string,\n /** e.g. \"39\" */\n amount?: string,\n /** e.g. \"USD\" */\n currency?: string,\n cycleToShow?: string,\n /** When set, shows the enrolled course card below the purchase summary. */\n course?: CourseDetail | null,\n onStartCourse?: () => void,\n}\n\nconst EnrollmentSummary = ({\n productTitle = 'edX Subscription',\n productBlurb = 'Subscribe and get access to hundreds of courses and programs.',\n amount,\n currency = 'USD',\n cycleToShow = 'monthly',\n course = null,\n onStartCourse,\n}: EnrollmentSummaryProps) => {\n const { formatMessage } = useIntl();\n\n const isMonthly = cycleToShow === 'monthly';\n const frequency = isMonthly ? 'month' : 'year';\n const cycleLabel = isMonthly\n ? formatMessage(messages.monthlySubscription)\n : formatMessage(messages.annualSubscription);\n\n return (\n <div className=\"enrollment-summary\">\n <Card className=\"enrollment-summary\">\n <Card.Section>\n <p className=\"font-weight-bold mb-3\">\n {formatMessage(messages.purchaseSummary)}\n </p>\n\n <div className=\"d-flex align-items-start mb-3\">\n <EdxUnlimitedLogo />\n <div>\n <p className=\"font-weight-bold mb-1\" style={{ fontSize: '0.9rem' }}>\n {productTitle}\n </p>\n <p className=\"text-muted mb-0\" style={{ fontSize: '0.82rem' }}>\n {productBlurb}\n </p>\n </div>\n </div>\n\n <div className=\"d-flex justify-content-between align-items-center mb-1\">\n <span className=\"small text-muted\">{cycleLabel}</span>\n {amount && (\n <span className=\"small font-weight-bold\">\n {formatMessage(messages.priceDisplay, {\n amount,\n frequency,\n currency,\n })}\n </span>\n )}\n </div>\n </Card.Section>\n\n <Card.Divider />\n\n <Card.Section className=\"d-flex justify-content-between align-items-center\">\n <span className=\"font-weight-bold\">\n {formatMessage(messages.todaysTotal)}\n </span>\n <span className=\"font-weight-bold text-success\">\n {formatMessage(messages.todaysTotalValue)}\n </span>\n </Card.Section>\n </Card>\n\n {course && (\n <CourseEnrollmentCard\n course={course}\n variant=\"success\"\n onStartCourse={onStartCourse}\n />\n )}\n </div>\n );\n};\n\nexport default EnrollmentSummary;\n"]}
@@ -0,0 +1,33 @@
1
+ declare const messages: {
2
+ purchaseSummary: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ monthlySubscription: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ annualSubscription: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ priceDisplay: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ todaysTotal: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ todaysTotalValue: {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ };
33
+ export default messages;
@@ -0,0 +1,35 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ purchaseSummary: {
4
+ id: 'checkout.enrollmentSummary.purchaseSummary',
5
+ defaultMessage: 'Purchase summary',
6
+ description: 'Heading for the purchase summary card on the success screen',
7
+ },
8
+ monthlySubscription: {
9
+ id: 'checkout.enrollmentSummary.monthlySubscription',
10
+ defaultMessage: 'Monthly subscription',
11
+ description: 'Label for monthly billing cycle in purchase summary',
12
+ },
13
+ annualSubscription: {
14
+ id: 'checkout.enrollmentSummary.annualSubscription',
15
+ defaultMessage: 'Annual subscription',
16
+ description: 'Label for annual billing cycle in purchase summary',
17
+ },
18
+ priceDisplay: {
19
+ id: 'checkout.enrollmentSummary.priceDisplay',
20
+ defaultMessage: '${amount}/{frequency} USD',
21
+ description: 'Price display in the purchase summary',
22
+ },
23
+ todaysTotal: {
24
+ id: 'checkout.enrollmentSummary.todaysTotal',
25
+ defaultMessage: "Today's total",
26
+ description: "Label for today's total row",
27
+ },
28
+ todaysTotalValue: {
29
+ id: 'checkout.enrollmentSummary.todaysTotalValue',
30
+ defaultMessage: '$0',
31
+ description: "Today's total value during trial period",
32
+ },
33
+ });
34
+ export default messages;
35
+ //# sourceMappingURL=Messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/EnrollmentSummary/Messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,eAAe,EAAE;QACf,EAAE,EAAE,4CAA4C;QAChD,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,6DAA6D;KAC3E;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,gDAAgD;QACpD,cAAc,EAAE,sBAAsB;QACtC,WAAW,EAAE,qDAAqD;KACnE;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,+CAA+C;QACnD,cAAc,EAAE,qBAAqB;QACrC,WAAW,EAAE,oDAAoD;KAClE;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,2BAA2B;QAC3C,WAAW,EAAE,uCAAuC;KACrD;IACD,WAAW,EAAE;QACX,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,6BAA6B;KAC3C;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,6CAA6C;QACjD,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,yCAAyC;KACvD;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n purchaseSummary: {\n id: 'checkout.enrollmentSummary.purchaseSummary',\n defaultMessage: 'Purchase summary',\n description: 'Heading for the purchase summary card on the success screen',\n },\n monthlySubscription: {\n id: 'checkout.enrollmentSummary.monthlySubscription',\n defaultMessage: 'Monthly subscription',\n description: 'Label for monthly billing cycle in purchase summary',\n },\n annualSubscription: {\n id: 'checkout.enrollmentSummary.annualSubscription',\n defaultMessage: 'Annual subscription',\n description: 'Label for annual billing cycle in purchase summary',\n },\n priceDisplay: {\n id: 'checkout.enrollmentSummary.priceDisplay',\n defaultMessage: '${amount}/{frequency} USD',\n description: 'Price display in the purchase summary',\n },\n todaysTotal: {\n id: 'checkout.enrollmentSummary.todaysTotal',\n defaultMessage: \"Today's total\",\n description: \"Label for today's total row\",\n },\n todaysTotalValue: {\n id: 'checkout.enrollmentSummary.todaysTotalValue',\n defaultMessage: '$0',\n description: \"Today's total value during trial period\",\n },\n});\n\nexport default messages;\n"]}
@@ -0,0 +1,9 @@
1
+ import type { Ref } from 'react';
2
+ export interface PaymentFieldsProps {
3
+ numberMountRef: Ref<HTMLDivElement>;
4
+ expiryMountRef: Ref<HTMLDivElement>;
5
+ cvcMountRef: Ref<HTMLDivElement>;
6
+ cardError: string;
7
+ }
8
+ declare const PaymentFields: ({ numberMountRef, expiryMountRef, cvcMountRef, cardError, }: PaymentFieldsProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default PaymentFields;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Form } from '@openedx/paragon';
3
+ import { STRIPE_FIELD_STYLE } from '../../constants';
4
+ import { CardBrands } from '../BrandMarks/BrandMarks';
5
+ const PaymentFields = ({ numberMountRef, expiryMountRef, cvcMountRef, cardError, }) => (_jsxs("div", { className: "payment--field", children: [_jsxs("div", { className: "d-flex flex-column mb-3 gap-4", children: [_jsxs(Form.Group, { controlId: "cardNumber", className: "mb-0 flex-grow-1", children: [_jsx(Form.Label, { className: "text-gray-900 m-0 x-small", children: "Card number" }), _jsxs("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: [_jsx("div", { ref: numberMountRef, className: "flex-grow-1" }), _jsx(CardBrands, {})] })] }), _jsxs("div", { className: "d-flex gap-4", children: [_jsxs(Form.Group, { controlId: "cardExpiry", className: "card__expiry mb-0 w-50", children: [_jsx(Form.Label, { className: "text-gray-900 m-0 x-small", children: "Expiration" }), _jsx("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: _jsx("div", { ref: expiryMountRef, className: "flex-grow-1" }) })] }), _jsxs(Form.Group, { controlId: "cardCvc", className: "card__cvc mb-0 w-50", children: [_jsx(Form.Label, { className: "text-gray-900 m-0 x-small", children: "CVC" }), _jsx("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: _jsx("div", { ref: cvcMountRef, className: "flex-grow-1" }) })] })] })] }), cardError && _jsx("p", { className: "text-danger small mb-2", children: cardError })] }));
6
+ export default PaymentFields;
7
+ //# sourceMappingURL=PaymentFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaymentFields.js","sourceRoot":"","sources":["../../../src/components/PaymentFields/PaymentFields.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAStD,MAAM,aAAa,GAAG,CAAC,EACrB,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,GACU,EAAE,EAAE,CAAC,CACxB,eAAK,SAAS,EAAC,gBAAgB,aAE7B,eAAK,SAAS,EAAC,+BAA+B,aAE5C,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,SAAS,EAAC,kBAAkB,aAC7D,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,2BAA2B,4BAEpC,EACb,eAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,aACrD,cAAK,GAAG,EAAE,cAAc,EAAE,SAAS,EAAC,aAAa,GAAG,EACpD,KAAC,UAAU,KAAG,IACV,IACK,EAEb,eAAK,SAAS,EAAC,cAAc,aAE3B,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,SAAS,EAAC,wBAAwB,aACnE,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,2BAA2B,2BAEpC,EACb,cAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,YACrD,cAAK,GAAG,EAAE,cAAc,EAAE,SAAS,EAAC,aAAa,GAAG,GAChD,IACK,EAGb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,SAAS,EAAC,SAAS,EAAC,qBAAqB,aAC7D,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,2BAA2B,oBAAiB,EAClE,cAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,YACrD,cAAK,GAAG,EAAE,WAAW,EAAE,SAAS,EAAC,aAAa,GAAG,GAC7C,IACK,IACT,IACF,EAEL,SAAS,IAAI,YAAG,SAAS,EAAC,wBAAwB,YAAE,SAAS,GAAK,IAC/D,CACP,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import React from 'react';\nimport type { Ref } from 'react';\nimport { Form } from '@openedx/paragon';\nimport { STRIPE_FIELD_STYLE } from '../../constants';\nimport { CardBrands } from '../BrandMarks/BrandMarks';\n\nexport interface PaymentFieldsProps {\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n}\n\nconst PaymentFields = ({\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n}: PaymentFieldsProps) => (\n <div className=\"payment--field\">\n {/* Single-row wrapper on desktop, stacked on mobile */}\n <div className=\"d-flex flex-column mb-3 gap-4\">\n {/* Card number — grows to fill available space */}\n <Form.Group controlId=\"cardNumber\" className=\"mb-0 flex-grow-1\">\n <Form.Label className=\"text-gray-900 m-0 x-small\">\n Card number\n </Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={numberMountRef} className=\"flex-grow-1\" />\n <CardBrands />\n </div>\n </Form.Group>\n\n <div className=\"d-flex gap-4\">\n {/* Expiry — fixed width on desktop */}\n <Form.Group controlId=\"cardExpiry\" className=\"card__expiry mb-0 w-50\">\n <Form.Label className=\"text-gray-900 m-0 x-small\">\n Expiration\n </Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={expiryMountRef} className=\"flex-grow-1\" />\n </div>\n </Form.Group>\n\n {/* CVC — fixed width on desktop */}\n <Form.Group controlId=\"cardCvc\" className=\"card__cvc mb-0 w-50\">\n <Form.Label className=\"text-gray-900 m-0 x-small\">CVC</Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={cvcMountRef} className=\"flex-grow-1\" />\n </div>\n </Form.Group>\n </div>\n </div>\n\n {cardError && <p className=\"text-danger small mb-2\">{cardError}</p>}\n </div>\n);\n\nexport default PaymentFields;\n"]}
@@ -0,0 +1,88 @@
1
+ declare const messages: {
2
+ selectPaymentMethod: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ needAssistance: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ needAssistanceBody: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ learnerHelpCenter: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ card: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ googlePay: {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ paypal: {
33
+ id: string;
34
+ defaultMessage: string;
35
+ description: string;
36
+ };
37
+ termsNotice: {
38
+ id: string;
39
+ defaultMessage: string;
40
+ description: string;
41
+ };
42
+ termsOfUse: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ refundPolicy: {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
52
+ recurringConfirm: {
53
+ id: string;
54
+ defaultMessage: string;
55
+ description: string;
56
+ };
57
+ ukCaResidentConfirm: {
58
+ id: string;
59
+ defaultMessage: string;
60
+ description: string;
61
+ };
62
+ confirmSubscription: {
63
+ id: string;
64
+ defaultMessage: string;
65
+ description: string;
66
+ };
67
+ processing: {
68
+ id: string;
69
+ defaultMessage: string;
70
+ description: string;
71
+ };
72
+ loadingPayment: {
73
+ id: string;
74
+ defaultMessage: string;
75
+ description: string;
76
+ };
77
+ country: {
78
+ id: string;
79
+ defaultMessage: string;
80
+ description: string;
81
+ };
82
+ spinnerScreenReaderText: {
83
+ id: string;
84
+ defaultMessage: string;
85
+ description: string;
86
+ };
87
+ };
88
+ export default messages;