@edx/frontend-app-alacarte-checkout 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +2 -0
  3. package/README.rst +235 -0
  4. package/dist/Main.d.ts +3 -0
  5. package/dist/Main.js +15 -0
  6. package/dist/Main.js.map +1 -0
  7. package/dist/app.d.ts +3 -0
  8. package/dist/app.js +12 -0
  9. package/dist/app.js.map +1 -0
  10. package/dist/checkoutPage/CheckoutPage.d.ts +3 -0
  11. package/dist/checkoutPage/CheckoutPage.js +26 -0
  12. package/dist/checkoutPage/CheckoutPage.js.map +1 -0
  13. package/dist/components/BrandMarks/BrandMarks.d.ts +7 -0
  14. package/dist/components/BrandMarks/BrandMarks.js +9 -0
  15. package/dist/components/BrandMarks/BrandMarks.js.map +1 -0
  16. package/dist/components/CartSummary/CartSummary.d.ts +26 -0
  17. package/dist/components/CartSummary/CartSummary.js +41 -0
  18. package/dist/components/CartSummary/CartSummary.js.map +1 -0
  19. package/dist/components/CartSummary/Messages.d.ts +103 -0
  20. package/dist/components/CartSummary/Messages.js +106 -0
  21. package/dist/components/CartSummary/Messages.js.map +1 -0
  22. package/dist/components/Checkout/Checkout.d.ts +9 -0
  23. package/dist/components/Checkout/Checkout.js +82 -0
  24. package/dist/components/Checkout/Checkout.js.map +1 -0
  25. package/dist/components/Checkout/Messages.d.ts +8 -0
  26. package/dist/components/Checkout/Messages.js +10 -0
  27. package/dist/components/Checkout/Messages.js.map +1 -0
  28. package/dist/components/CheckoutGate/CheckoutGate.d.ts +9 -0
  29. package/dist/components/CheckoutGate/CheckoutGate.js +40 -0
  30. package/dist/components/CheckoutGate/CheckoutGate.js.map +1 -0
  31. package/dist/components/CheckoutGate/Messages.d.ts +8 -0
  32. package/dist/components/CheckoutGate/Messages.js +10 -0
  33. package/dist/components/CheckoutGate/Messages.js.map +1 -0
  34. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.d.ts +9 -0
  35. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.js +10 -0
  36. package/dist/components/CountryUnavailableModal/CountryUnavailableModal.js.map +1 -0
  37. package/dist/components/CountryUnavailableModal/Messages.d.ts +18 -0
  38. package/dist/components/CountryUnavailableModal/Messages.js +20 -0
  39. package/dist/components/CountryUnavailableModal/Messages.js.map +1 -0
  40. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +9 -0
  41. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +31 -0
  42. package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +1 -0
  43. package/dist/components/CourseEnrollmentCard/Messages.d.ts +33 -0
  44. package/dist/components/CourseEnrollmentCard/Messages.js +35 -0
  45. package/dist/components/CourseEnrollmentCard/Messages.js.map +1 -0
  46. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.d.ts +13 -0
  47. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js +11 -0
  48. package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js.map +1 -0
  49. package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +22 -0
  50. package/dist/components/EnrollmentSummary/EnrollmentSummary.js +33 -0
  51. package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -0
  52. package/dist/components/EnrollmentSummary/Messages.d.ts +48 -0
  53. package/dist/components/EnrollmentSummary/Messages.js +50 -0
  54. package/dist/components/EnrollmentSummary/Messages.js.map +1 -0
  55. package/dist/components/PaymentFields/PaymentFields.d.ts +9 -0
  56. package/dist/components/PaymentFields/PaymentFields.js +7 -0
  57. package/dist/components/PaymentFields/PaymentFields.js.map +1 -0
  58. package/dist/components/PaymentForm/Messages.d.ts +118 -0
  59. package/dist/components/PaymentForm/Messages.js +125 -0
  60. package/dist/components/PaymentForm/Messages.js.map +1 -0
  61. package/dist/components/PaymentForm/PaymentForm.d.ts +28 -0
  62. package/dist/components/PaymentForm/PaymentForm.js +121 -0
  63. package/dist/components/PaymentForm/PaymentForm.js.map +1 -0
  64. package/dist/components/StatusScreens/Messages.d.ts +108 -0
  65. package/dist/components/StatusScreens/Messages.js +114 -0
  66. package/dist/components/StatusScreens/Messages.js.map +1 -0
  67. package/dist/components/StatusScreens/StatusScreens.d.ts +24 -0
  68. package/dist/components/StatusScreens/StatusScreens.js +32 -0
  69. package/dist/components/StatusScreens/StatusScreens.js.map +1 -0
  70. package/dist/constants.d.ts +59 -0
  71. package/dist/constants.js +282 -0
  72. package/dist/constants.js.map +1 -0
  73. package/dist/data/hooks/keys.d.ts +14 -0
  74. package/dist/data/hooks/keys.js +15 -0
  75. package/dist/data/hooks/keys.js.map +1 -0
  76. package/dist/data/hooks/useCheckout.d.ts +61 -0
  77. package/dist/data/hooks/useCheckout.js +343 -0
  78. package/dist/data/hooks/useCheckout.js.map +1 -0
  79. package/dist/data/hooks/useCheckoutGate.d.ts +16 -0
  80. package/dist/data/hooks/useCheckoutGate.js +61 -0
  81. package/dist/data/hooks/useCheckoutGate.js.map +1 -0
  82. package/dist/data/hooks/useCheckoutMutations.d.ts +22 -0
  83. package/dist/data/hooks/useCheckoutMutations.js +166 -0
  84. package/dist/data/hooks/useCheckoutMutations.js.map +1 -0
  85. package/dist/data/hooks/useCheckoutQueries.d.ts +32 -0
  86. package/dist/data/hooks/useCheckoutQueries.js +107 -0
  87. package/dist/data/hooks/useCheckoutQueries.js.map +1 -0
  88. package/dist/data/services/subs/urls.d.ts +2 -0
  89. package/dist/data/services/subs/urls.js +4 -0
  90. package/dist/data/services/subs/urls.js.map +1 -0
  91. package/dist/i18n/index.d.ts +1 -0
  92. package/dist/i18n/index.js +2 -0
  93. package/dist/i18n/index.js.map +1 -0
  94. package/dist/index.d.ts +2 -0
  95. package/dist/index.js +3 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/messages.d.ts +8 -0
  98. package/dist/messages.js +10 -0
  99. package/dist/messages.js.map +1 -0
  100. package/dist/routes.d.ts +18 -0
  101. package/dist/routes.js +47 -0
  102. package/dist/routes.js.map +1 -0
  103. package/dist/slots/ExampleSlot/ExampleSlot.d.ts +3 -0
  104. package/dist/slots/ExampleSlot/ExampleSlot.js +6 -0
  105. package/dist/slots/ExampleSlot/ExampleSlot.js.map +1 -0
  106. package/dist/slots.d.ts +3 -0
  107. package/dist/slots.js +3 -0
  108. package/dist/slots.js.map +1 -0
  109. package/dist/style.scss +14 -0
  110. package/dist/styles/components/brandMarks.scss +41 -0
  111. package/dist/styles/components/cartSummary.scss +29 -0
  112. package/dist/styles/components/checkout.scss +29 -0
  113. package/dist/styles/components/checkoutStepper.scss +9 -0
  114. package/dist/styles/components/courseEnrollmentCard.scss +38 -0
  115. package/dist/styles/components/edxUnlimitedBanner.scss +138 -0
  116. package/dist/styles/components/enrollmentSummary.scss +19 -0
  117. package/dist/styles/components/paymentFields.scss +15 -0
  118. package/dist/styles/components/paymentForm.scss +139 -0
  119. package/dist/styles/components/statusScreens.scss +39 -0
  120. package/dist/styles/components/successScreen.scss +0 -0
  121. package/dist/types.d.ts +232 -0
  122. package/dist/types.js +2 -0
  123. package/dist/types.js.map +1 -0
  124. package/dist/utils/auth.d.ts +7 -0
  125. package/dist/utils/auth.js +28 -0
  126. package/dist/utils/auth.js.map +1 -0
  127. package/dist/utils/billingDetails.d.ts +30 -0
  128. package/dist/utils/billingDetails.js +48 -0
  129. package/dist/utils/billingDetails.js.map +1 -0
  130. package/dist/utils/bootstrapApi.d.ts +20 -0
  131. package/dist/utils/bootstrapApi.js +142 -0
  132. package/dist/utils/bootstrapApi.js.map +1 -0
  133. package/dist/utils/cartApi.d.ts +16 -0
  134. package/dist/utils/cartApi.js +133 -0
  135. package/dist/utils/cartApi.js.map +1 -0
  136. package/dist/utils/checkout.d.ts +6 -0
  137. package/dist/utils/checkout.js +28 -0
  138. package/dist/utils/checkout.js.map +1 -0
  139. package/dist/utils/checkoutErrors.d.ts +1 -0
  140. package/dist/utils/checkoutErrors.js +11 -0
  141. package/dist/utils/checkoutErrors.js.map +1 -0
  142. package/dist/utils/fetchActiveSubscriptions.d.ts +4 -0
  143. package/dist/utils/fetchActiveSubscriptions.js +36 -0
  144. package/dist/utils/fetchActiveSubscriptions.js.map +1 -0
  145. package/dist/utils/fetchBillingPlans.d.ts +2 -0
  146. package/dist/utils/fetchBillingPlans.js +48 -0
  147. package/dist/utils/fetchBillingPlans.js.map +1 -0
  148. package/dist/utils/graphqlClient.d.ts +16 -0
  149. package/dist/utils/graphqlClient.js +39 -0
  150. package/dist/utils/graphqlClient.js.map +1 -0
  151. package/dist/utils/index.d.ts +3 -0
  152. package/dist/utils/index.js +17 -0
  153. package/dist/utils/index.js.map +1 -0
  154. package/dist/utils/planQuery.d.ts +16 -0
  155. package/dist/utils/planQuery.js +57 -0
  156. package/dist/utils/planQuery.js.map +1 -0
  157. package/dist/utils/provision.d.ts +48 -0
  158. package/dist/utils/provision.js +161 -0
  159. package/dist/utils/provision.js.map +1 -0
  160. package/dist/utils/queries.d.ts +35 -0
  161. package/dist/utils/queries.js +168 -0
  162. package/dist/utils/queries.js.map +1 -0
  163. package/dist/utils/stripe.d.ts +23 -0
  164. package/dist/utils/stripe.js +86 -0
  165. package/dist/utils/stripe.js.map +1 -0
  166. package/package.json +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EdxUnlimitedBanner.js","sourceRoot":"","sources":["../../../src/components/EdxUnlimitedBanner/EdxUnlimitedBanner.tsx"],"names":[],"mappings":"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","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,22 @@
1
+ import type { CourseDetail } from '../../types';
2
+ export interface EnrollmentSummaryProps {
3
+ productTitle?: string;
4
+ productBlurb?: string;
5
+ /** e.g. "59" or "396" from getBillingPlans */
6
+ amount?: string;
7
+ /** Promotional monthly price e.g. "39" — monthly plans only. */
8
+ promoAmount?: string;
9
+ /** Length of the promotional period in months. */
10
+ promoMonths?: number;
11
+ /** Regular monthly price after the promo period e.g. "59". */
12
+ monthlyRegularAmount?: string;
13
+ /** e.g. "USD" */
14
+ currency?: string;
15
+ /** Billing cycle for the purchased plan. */
16
+ cycleToShow?: 'monthly' | 'annual';
17
+ /** When set, shows the enrolled course card below the purchase summary. */
18
+ course?: CourseDetail | null;
19
+ onStartCourse?: () => void;
20
+ }
21
+ declare const EnrollmentSummary: ({ productTitle, productBlurb, amount, promoAmount, promoMonths, monthlyRegularAmount, currency, cycleToShow, course, onStartCourse, }: EnrollmentSummaryProps) => import("react/jsx-runtime").JSX.Element;
22
+ export default EnrollmentSummary;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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 Plus', productBlurb = 'Access to hundreds of courses and programs.', amount, promoAmount = '39', promoMonths = 3, monthlyRegularAmount, 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
+ const regularMonthlyAmount = monthlyRegularAmount !== null && monthlyRegularAmount !== void 0 ? monthlyRegularAmount : amount;
15
+ return (_jsxs("div", { className: "enrollment-summary", children: [_jsxs(Card, { className: "enrollment-summary__card p-3", children: [_jsx(Card.Section, { className: "p-0 pb-3", children: _jsx("p", { className: "font-weight-bold mb-0 text-gray-900", children: formatMessage(messages.purchaseSummary) }) }), _jsx(Card.Divider, {}), _jsx(Card.Section, { className: "p-0 py-3", children: _jsxs("div", { className: "d-flex align-items-start", children: [_jsx(EdxUnlimitedLogo, {}), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-0 text-primary-500", children: productTitle }), _jsx("p", { className: "small mb-0 text-gray-900", children: productBlurb })] })] }) }), _jsx(Card.Divider, {}), _jsx(Card.Section, { className: "p-0 pt-3 pb-2", children: _jsxs("div", { className: "d-flex justify-content-between align-items-start", children: [_jsx("span", { className: "small text-gray-900", children: cycleLabel }), _jsx("div", { className: "enrollment-summary__pricing text-right", children: isMonthly ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.promotionalPrice, {
16
+ amount: promoAmount,
17
+ months: promoMonths,
18
+ }) }), regularMonthlyAmount && (_jsx("div", { className: "small text-gray-900", children: formatMessage(messages.regularPrice, {
19
+ amount: regularMonthlyAmount,
20
+ currency,
21
+ }) }))] })) : (amount && (_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.priceDisplay, {
22
+ amount,
23
+ frequency,
24
+ currency,
25
+ }) }))) })] }) }), _jsxs(Card.Section, { className: "d-flex justify-content-between align-items-center px-0 pt-1", children: [_jsx("span", { className: "font-weight-bold text-gray-900", children: formatMessage(messages.todaysTotal) }), _jsx("span", { className: "font-weight-bold mb-0 text-success", children: isMonthly
26
+ ? formatMessage(messages.todaysTotalValue)
27
+ : formatMessage(messages.todaysTotalAnnualValue, {
28
+ amount: amount !== null && amount !== void 0 ? amount : '',
29
+ currency,
30
+ }) })] })] }), course && (_jsx(CourseEnrollmentCard, { course: course, variant: "success", onStartCourse: onStartCourse }))] }));
31
+ };
32
+ export default EnrollmentSummary;
33
+ //# sourceMappingURL=EnrollmentSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnrollmentSummary.js","sourceRoot":"","sources":["../../../src/components/EnrollmentSummary/EnrollmentSummary.tsx"],"names":[],"mappings":"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","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. \"59\" or \"396\" from getBillingPlans */\n amount?: string,\n /** Promotional monthly price e.g. \"39\" — monthly plans only. */\n promoAmount?: string,\n /** Length of the promotional period in months. */\n promoMonths?: number,\n /** Regular monthly price after the promo period e.g. \"59\". */\n monthlyRegularAmount?: string,\n /** e.g. \"USD\" */\n currency?: string,\n /** Billing cycle for the purchased plan. */\n cycleToShow?: 'monthly' | 'annual',\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 Plus',\n productBlurb = 'Access to hundreds of courses and programs.',\n amount,\n promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount,\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 const regularMonthlyAmount = monthlyRegularAmount ?? amount;\n\n return (\n <div className=\"enrollment-summary\">\n <Card className=\"enrollment-summary__card p-3\">\n <Card.Section className=\"p-0 pb-3\">\n <p className=\"font-weight-bold mb-0 text-gray-900\">\n {formatMessage(messages.purchaseSummary)}\n </p>\n </Card.Section>\n\n <Card.Divider />\n\n <Card.Section className=\"p-0 py-3\">\n <div className=\"d-flex align-items-start\">\n <EdxUnlimitedLogo />\n <div>\n <p className=\"font-weight-bold mb-0 text-primary-500\">\n {productTitle}\n </p>\n <p className=\"small mb-0 text-gray-900\">{productBlurb}</p>\n </div>\n </div>\n </Card.Section>\n\n <Card.Divider />\n\n <Card.Section className=\"p-0 pt-3 pb-2\">\n <div className=\"d-flex justify-content-between align-items-start\">\n <span className=\"small text-gray-900\">{cycleLabel}</span>\n <div className=\"enrollment-summary__pricing text-right\">\n {isMonthly ? (\n <>\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.promotionalPrice, {\n amount: promoAmount,\n months: promoMonths,\n })}\n </div>\n {regularMonthlyAmount && (\n <div className=\"small text-gray-900\">\n {formatMessage(messages.regularPrice, {\n amount: regularMonthlyAmount,\n currency,\n })}\n </div>\n )}\n </>\n ) : (\n amount && (\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.priceDisplay, {\n amount,\n frequency,\n currency,\n })}\n </div>\n )\n )}\n </div>\n </div>\n </Card.Section>\n\n <Card.Section className=\"d-flex justify-content-between align-items-center px-0 pt-1\">\n <span className=\"font-weight-bold text-gray-900\">\n {formatMessage(messages.todaysTotal)}\n </span>\n <span className=\"font-weight-bold mb-0 text-success\">\n {isMonthly\n ? formatMessage(messages.todaysTotalValue)\n : formatMessage(messages.todaysTotalAnnualValue, {\n amount: amount ?? '',\n currency,\n })}\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,48 @@
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
+ promotionalPrice: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ regularPrice: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ priceDisplay: {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ todaysTotal: {
33
+ id: string;
34
+ defaultMessage: string;
35
+ description: string;
36
+ };
37
+ todaysTotalValue: {
38
+ id: string;
39
+ defaultMessage: string;
40
+ description: string;
41
+ };
42
+ todaysTotalAnnualValue: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ };
48
+ export default messages;
@@ -0,0 +1,50 @@
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
+ promotionalPrice: {
19
+ id: 'checkout.enrollmentSummary.promotionalPrice',
20
+ defaultMessage: '${amount}/mo for {months} months',
21
+ description: 'Promotional monthly price e.g. $39/mo for 3 months',
22
+ },
23
+ regularPrice: {
24
+ id: 'checkout.enrollmentSummary.regularPrice',
25
+ defaultMessage: 'then ${amount}/mo {currency}',
26
+ description: 'Regular monthly price after the promo period e.g. then $59/mo {currency}',
27
+ },
28
+ priceDisplay: {
29
+ id: 'checkout.enrollmentSummary.priceDisplay',
30
+ defaultMessage: '${amount}/{frequency} {currency}',
31
+ description: 'Price display in the purchase summary e.g. $396/year USD',
32
+ },
33
+ todaysTotal: {
34
+ id: 'checkout.enrollmentSummary.todaysTotal',
35
+ defaultMessage: "Today's total",
36
+ description: "Label for today's total row",
37
+ },
38
+ todaysTotalValue: {
39
+ id: 'checkout.enrollmentSummary.todaysTotalValue',
40
+ defaultMessage: '$0',
41
+ description: "Today's total value during trial period (monthly only)",
42
+ },
43
+ todaysTotalAnnualValue: {
44
+ id: 'checkout.enrollmentSummary.todaysTotalAnnualValue',
45
+ defaultMessage: '${amount} {currency}',
46
+ description: "Today's total for annual plans with no trial e.g. $396 USD",
47
+ },
48
+ });
49
+ export default messages;
50
+ //# 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,gBAAgB,EAAE;QAChB,EAAE,EAAE,6CAA6C;QACjD,cAAc,EAAE,kCAAkC;QAClD,WAAW,EAAE,oDAAoD;KAClE;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,8BAA8B;QAC9C,WAAW,EAAE,0EAA0E;KACxF;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,kCAAkC;QAClD,WAAW,EAAE,0DAA0D;KACxE;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,wDAAwD;KACtE;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,mDAAmD;QACvD,cAAc,EAAE,sBAAsB;QACtC,WAAW,EAAE,4DAA4D;KAC1E;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 promotionalPrice: {\n id: 'checkout.enrollmentSummary.promotionalPrice',\n defaultMessage: '${amount}/mo for {months} months',\n description: 'Promotional monthly price e.g. $39/mo for 3 months',\n },\n regularPrice: {\n id: 'checkout.enrollmentSummary.regularPrice',\n defaultMessage: 'then ${amount}/mo {currency}',\n description: 'Regular monthly price after the promo period e.g. then $59/mo {currency}',\n },\n priceDisplay: {\n id: 'checkout.enrollmentSummary.priceDisplay',\n defaultMessage: '${amount}/{frequency} {currency}',\n description: 'Price display in the purchase summary e.g. $396/year USD',\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 (monthly only)\",\n },\n todaysTotalAnnualValue: {\n id: 'checkout.enrollmentSummary.todaysTotalAnnualValue',\n defaultMessage: '${amount} {currency}',\n description: \"Today's total for annual plans with no trial e.g. $396 USD\",\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,118 @@
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
+ termsNoticeAnnual: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ termsPricingMonthly: {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
52
+ termsPricingAnnual: {
53
+ id: string;
54
+ defaultMessage: string;
55
+ description: string;
56
+ };
57
+ termsOfUse: {
58
+ id: string;
59
+ defaultMessage: string;
60
+ description: string;
61
+ };
62
+ refundPolicy: {
63
+ id: string;
64
+ defaultMessage: string;
65
+ description: string;
66
+ };
67
+ recurringConfirmMonthly: {
68
+ id: string;
69
+ defaultMessage: string;
70
+ description: string;
71
+ };
72
+ recurringConfirmAnnual: {
73
+ id: string;
74
+ defaultMessage: string;
75
+ description: string;
76
+ };
77
+ ukWithdrawalConfirm: {
78
+ id: string;
79
+ defaultMessage: string;
80
+ description: string;
81
+ };
82
+ canadaQuebecConfirm: {
83
+ id: string;
84
+ defaultMessage: string;
85
+ description: string;
86
+ };
87
+ confirmSubscription: {
88
+ id: string;
89
+ defaultMessage: string;
90
+ description: string;
91
+ };
92
+ continueWithPaypal: {
93
+ id: string;
94
+ defaultMessage: string;
95
+ description: string;
96
+ };
97
+ processing: {
98
+ id: string;
99
+ defaultMessage: string;
100
+ description: string;
101
+ };
102
+ loadingPayment: {
103
+ id: string;
104
+ defaultMessage: string;
105
+ description: string;
106
+ };
107
+ country: {
108
+ id: string;
109
+ defaultMessage: string;
110
+ description: string;
111
+ };
112
+ spinnerScreenReaderText: {
113
+ id: string;
114
+ defaultMessage: string;
115
+ description: string;
116
+ };
117
+ };
118
+ export default messages;
@@ -0,0 +1,125 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ // Section headings
4
+ selectPaymentMethod: {
5
+ id: 'checkout.paymentForm.selectPaymentMethod',
6
+ defaultMessage: 'Select Payment Method',
7
+ description: 'Heading for the payment method selection section',
8
+ },
9
+ needAssistance: {
10
+ id: 'checkout.paymentForm.needAssistance',
11
+ defaultMessage: 'Need assistance?',
12
+ description: 'Help text heading',
13
+ },
14
+ needAssistanceBody: {
15
+ id: 'checkout.paymentForm.needAssistanceBody',
16
+ defaultMessage: 'Visit the {link} to review purchase and refund policies.',
17
+ description: 'Help text with learner help center link',
18
+ },
19
+ learnerHelpCenter: {
20
+ id: 'checkout.paymentForm.learnerHelpCenter',
21
+ defaultMessage: 'Learner Help Center',
22
+ description: 'Learner help center link text',
23
+ },
24
+ // Payment method options
25
+ card: {
26
+ id: 'checkout.paymentForm.card',
27
+ defaultMessage: 'Card',
28
+ description: 'Credit/debit card payment method label',
29
+ },
30
+ googlePay: {
31
+ id: 'checkout.paymentForm.googlePay',
32
+ defaultMessage: 'Google Pay',
33
+ description: 'Google Pay payment method label',
34
+ },
35
+ paypal: {
36
+ id: 'checkout.paymentForm.paypal',
37
+ defaultMessage: 'PayPal',
38
+ description: 'PayPal payment method label',
39
+ },
40
+ // Terms
41
+ termsNotice: {
42
+ id: 'checkout.paymentForm.termsNotice',
43
+ defaultMessage: 'Your edX Plus subscription will start today with a {trialDays}-day free trial. Your subscription automatically renews on {date} for {pricing} (inclusive of applicable taxes). Cancel your subscription anytime from your dashboard. By clicking “Confirm subscription” you agree to our {termsLink}, and {refundLink}.',
44
+ description: 'Monthly subscription terms notice with free trial, shown before the confirm button',
45
+ },
46
+ termsNoticeAnnual: {
47
+ id: 'checkout.paymentForm.termsNoticeAnnual',
48
+ defaultMessage: 'Your edX Plus subscription will start today. You will be charged {pricing} today (inclusive of applicable taxes). Your subscription automatically renews annually. Cancel your subscription anytime from your dashboard. By clicking “Confirm subscription” you agree to our {termsLink}, and {refundLink}.',
49
+ description: 'Annual subscription terms notice without free trial, shown before the confirm button',
50
+ },
51
+ termsPricingMonthly: {
52
+ id: 'checkout.paymentForm.termsPricingMonthly',
53
+ defaultMessage: '${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo',
54
+ description: 'Monthly promotional pricing in the terms notice e.g. $39/mo for 3 months then $59/mo',
55
+ },
56
+ termsPricingAnnual: {
57
+ id: 'checkout.paymentForm.termsPricingAnnual',
58
+ defaultMessage: '${amount}/{frequency}',
59
+ description: 'Annual plan pricing in the terms notice e.g. $299/year — no promotional pricing',
60
+ },
61
+ termsOfUse: {
62
+ id: 'checkout.paymentForm.termsOfUse',
63
+ defaultMessage: 'Terms of Use',
64
+ description: 'Terms of Use link text',
65
+ },
66
+ refundPolicy: {
67
+ id: 'checkout.paymentForm.refundPolicy',
68
+ defaultMessage: 'Refund Policy',
69
+ description: 'Refund Policy link text',
70
+ },
71
+ // Checkboxes
72
+ recurringConfirmMonthly: {
73
+ id: 'checkout.paymentForm.recurringConfirmMonthly',
74
+ defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo USD.',
75
+ description: 'Monthly checkbox confirming recurring charge with promo then regular price',
76
+ },
77
+ recurringConfirmAnnual: {
78
+ id: 'checkout.paymentForm.recurringConfirmAnnual',
79
+ defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${amount}/yr USD.',
80
+ description: 'Annual checkbox confirming recurring charge',
81
+ },
82
+ ukWithdrawalConfirm: {
83
+ id: 'checkout.paymentForm.ukWithdrawalConfirm',
84
+ defaultMessage: 'I hereby consent to immediate performance of the contract and acknowledge that I will lose my right of withdrawal from the contract once the download or streaming of the digital content has begun.',
85
+ description: 'UK consent to immediate performance of the contract and loss of withdrawal rights',
86
+ },
87
+ canadaQuebecConfirm: {
88
+ id: 'checkout.paymentForm.canadaQuebecConfirm',
89
+ defaultMessage: 'I hereby verify I am not a resident of Quebec province',
90
+ description: 'Canadian consent verifying that the customer is not a resident of Quebec province',
91
+ },
92
+ // Submit button
93
+ confirmSubscription: {
94
+ id: 'checkout.paymentForm.confirmSubscription',
95
+ defaultMessage: 'Confirm subscription',
96
+ description: 'Submit button label',
97
+ },
98
+ continueWithPaypal: {
99
+ id: 'checkout.paymentForm.continueWithPaypal',
100
+ defaultMessage: 'Continue with PayPal',
101
+ description: 'Submit button label when PayPal is the selected payment method',
102
+ },
103
+ processing: {
104
+ id: 'checkout.paymentForm.processing',
105
+ defaultMessage: 'Confirming Subscription',
106
+ description: 'Submit button label while the subscription is being confirmed',
107
+ },
108
+ loadingPayment: {
109
+ id: 'checkout.paymentForm.loadingPayment',
110
+ defaultMessage: 'Loading payment…',
111
+ description: 'Submit button label while Stripe loads',
112
+ },
113
+ country: {
114
+ id: 'checkout.paymentForm.country',
115
+ defaultMessage: 'Country',
116
+ description: 'Country selector label',
117
+ },
118
+ spinnerScreenReaderText: {
119
+ id: 'checkout.paymentForm.spinnerScreenReaderText',
120
+ defaultMessage: 'Working',
121
+ description: 'Screen reader text for the loading spinner',
122
+ },
123
+ });
124
+ export default messages;
125
+ //# sourceMappingURL=Messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/Messages.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n // Section headings\n selectPaymentMethod: {\n id: 'checkout.paymentForm.selectPaymentMethod',\n defaultMessage: 'Select Payment Method',\n description: 'Heading for the payment method selection section',\n },\n needAssistance: {\n id: 'checkout.paymentForm.needAssistance',\n defaultMessage: 'Need assistance?',\n description: 'Help text heading',\n },\n needAssistanceBody: {\n id: 'checkout.paymentForm.needAssistanceBody',\n defaultMessage: 'Visit the {link} to review purchase and refund policies.',\n description: 'Help text with learner help center link',\n },\n learnerHelpCenter: {\n id: 'checkout.paymentForm.learnerHelpCenter',\n defaultMessage: 'Learner Help Center',\n description: 'Learner help center link text',\n },\n\n // Payment method options\n card: {\n id: 'checkout.paymentForm.card',\n defaultMessage: 'Card',\n description: 'Credit/debit card payment method label',\n },\n googlePay: {\n id: 'checkout.paymentForm.googlePay',\n defaultMessage: 'Google Pay',\n description: 'Google Pay payment method label',\n },\n paypal: {\n id: 'checkout.paymentForm.paypal',\n defaultMessage: 'PayPal',\n description: 'PayPal payment method label',\n },\n\n // Terms\n termsNotice: {\n id: 'checkout.paymentForm.termsNotice',\n defaultMessage: 'Your edX Plus subscription will start today with a {trialDays}-day free trial. Your subscription automatically renews on {date} for {pricing} (inclusive of applicable taxes). Cancel your subscription anytime from your dashboard. By clicking “Confirm subscription” you agree to our {termsLink}, and {refundLink}.',\n description: 'Monthly subscription terms notice with free trial, shown before the confirm button',\n },\n termsNoticeAnnual: {\n id: 'checkout.paymentForm.termsNoticeAnnual',\n defaultMessage: 'Your edX Plus subscription will start today. You will be charged {pricing} today (inclusive of applicable taxes). Your subscription automatically renews annually. Cancel your subscription anytime from your dashboard. By clicking “Confirm subscription” you agree to our {termsLink}, and {refundLink}.',\n description: 'Annual subscription terms notice without free trial, shown before the confirm button',\n },\n termsPricingMonthly: {\n id: 'checkout.paymentForm.termsPricingMonthly',\n defaultMessage: '${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo',\n description: 'Monthly promotional pricing in the terms notice e.g. $39/mo for 3 months then $59/mo',\n },\n termsPricingAnnual: {\n id: 'checkout.paymentForm.termsPricingAnnual',\n defaultMessage: '${amount}/{frequency}',\n description: 'Annual plan pricing in the terms notice e.g. $299/year — no promotional pricing',\n },\n termsOfUse: {\n id: 'checkout.paymentForm.termsOfUse',\n defaultMessage: 'Terms of Use',\n description: 'Terms of Use link text',\n },\n refundPolicy: {\n id: 'checkout.paymentForm.refundPolicy',\n defaultMessage: 'Refund Policy',\n description: 'Refund Policy link text',\n },\n\n // Checkboxes\n recurringConfirmMonthly: {\n id: 'checkout.paymentForm.recurringConfirmMonthly',\n defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo USD.',\n description: 'Monthly checkbox confirming recurring charge with promo then regular price',\n },\n recurringConfirmAnnual: {\n id: 'checkout.paymentForm.recurringConfirmAnnual',\n defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${amount}/yr USD.',\n description: 'Annual checkbox confirming recurring charge',\n },\n ukWithdrawalConfirm: {\n id: 'checkout.paymentForm.ukWithdrawalConfirm',\n defaultMessage: 'I hereby consent to immediate performance of the contract and acknowledge that I will lose my right of withdrawal from the contract once the download or streaming of the digital content has begun.',\n description: 'UK consent to immediate performance of the contract and loss of withdrawal rights',\n },\n canadaQuebecConfirm: {\n id: 'checkout.paymentForm.canadaQuebecConfirm',\n defaultMessage: 'I hereby verify I am not a resident of Quebec province',\n description: 'Canadian consent verifying that the customer is not a resident of Quebec province',\n },\n\n // Submit button\n confirmSubscription: {\n id: 'checkout.paymentForm.confirmSubscription',\n defaultMessage: 'Confirm subscription',\n description: 'Submit button label',\n },\n continueWithPaypal: {\n id: 'checkout.paymentForm.continueWithPaypal',\n defaultMessage: 'Continue with PayPal',\n description: 'Submit button label when PayPal is the selected payment method',\n },\n processing: {\n id: 'checkout.paymentForm.processing',\n defaultMessage: 'Confirming Subscription',\n description: 'Submit button label while the subscription is being confirmed',\n },\n loadingPayment: {\n id: 'checkout.paymentForm.loadingPayment',\n defaultMessage: 'Loading payment…',\n description: 'Submit button label while Stripe loads',\n },\n country: {\n id: 'checkout.paymentForm.country',\n defaultMessage: 'Country',\n description: 'Country selector label',\n },\n spinnerScreenReaderText: {\n id: 'checkout.paymentForm.spinnerScreenReaderText',\n defaultMessage: 'Working',\n description: 'Screen reader text for the loading spinner',\n },\n});\n\nexport default messages;\n"]}
@@ -0,0 +1,28 @@
1
+ import type { Ref } from 'react';
2
+ import type { BillingInfo, CheckoutConsent, SupportedPaymentMethod } from '../../types';
3
+ import type { PlanPrice } from '../../utils/billingDetails';
4
+ export interface PaymentFormProps {
5
+ billing: BillingInfo;
6
+ setField: (field: keyof BillingInfo, value: string) => void;
7
+ numberMountRef: Ref<HTMLDivElement>;
8
+ expiryMountRef: Ref<HTMLDivElement>;
9
+ cvcMountRef: Ref<HTMLDivElement>;
10
+ cardError: string;
11
+ stripeReady: boolean;
12
+ sessionReady: boolean;
13
+ submitting: boolean;
14
+ onPlaceOrder: (consent: CheckoutConsent, paymentMethod: SupportedPaymentMethod) => void;
15
+ priceToShow: PlanPrice | null;
16
+ cycleToShow: string;
17
+ trialEnd?: string;
18
+ userCountry?: string | null;
19
+ /** Promotional monthly price e.g. "39" — monthly plans only. */
20
+ promoAmount?: string;
21
+ /** Length of the promotional period in months. */
22
+ promoMonths?: number;
23
+ /** Regular monthly price after the promo period e.g. "59". */
24
+ monthlyRegularAmount?: string;
25
+ geolocationUrl?: string;
26
+ }
27
+ declare const PaymentForm: ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, promoAmount, promoMonths, monthlyRegularAmount, geolocationUrl, }: PaymentFormProps) => import("react/jsx-runtime").JSX.Element;
28
+ export default PaymentForm;