@edx/frontend-app-subscription-checkout 1.3.0 → 1.5.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 (37) hide show
  1. package/dist/app.js +6 -3
  2. package/dist/app.js.map +1 -1
  3. package/dist/checkoutPage/CheckoutPage.js +2 -1
  4. package/dist/checkoutPage/CheckoutPage.js.map +1 -1
  5. package/dist/components/CartSummary/CartSummary.d.ts +7 -2
  6. package/dist/components/CartSummary/CartSummary.js +16 -15
  7. package/dist/components/CartSummary/CartSummary.js.map +1 -1
  8. package/dist/components/Checkout/Checkout.d.ts +6 -1
  9. package/dist/components/Checkout/Checkout.js +25 -4
  10. package/dist/components/Checkout/Checkout.js.map +1 -1
  11. package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +3 -2
  12. package/dist/components/EnrollmentSummary/EnrollmentSummary.js +5 -3
  13. package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -1
  14. package/dist/components/EnrollmentSummary/Messages.js +2 -2
  15. package/dist/components/EnrollmentSummary/Messages.js.map +1 -1
  16. package/dist/components/PaymentForm/PaymentForm.js +4 -3
  17. package/dist/components/PaymentForm/PaymentForm.js.map +1 -1
  18. package/dist/constants.d.ts +2 -1
  19. package/dist/constants.js +201 -196
  20. package/dist/constants.js.map +1 -1
  21. package/dist/data/hooks/useCheckout.js +65 -15
  22. package/dist/data/hooks/useCheckout.js.map +1 -1
  23. package/dist/data/hooks/useCheckoutMutations.d.ts +3 -1
  24. package/dist/data/hooks/useCheckoutMutations.js +7 -4
  25. package/dist/data/hooks/useCheckoutMutations.js.map +1 -1
  26. package/dist/styles/components/paymentForm.scss +10 -0
  27. package/dist/utils/billingDetails.d.ts +1 -1
  28. package/dist/utils/billingDetails.js +6 -5
  29. package/dist/utils/billingDetails.js.map +1 -1
  30. package/dist/utils/cartApi.js +11 -9
  31. package/dist/utils/cartApi.js.map +1 -1
  32. package/dist/utils/provision.js +2 -2
  33. package/dist/utils/provision.js.map +1 -1
  34. package/dist/utils/queries.d.ts +1 -1
  35. package/dist/utils/queries.js +0 -2
  36. package/dist/utils/queries.js.map +1 -1
  37. package/package.json +1 -1
package/dist/app.js CHANGED
@@ -5,9 +5,12 @@ const app = {
5
5
  appId,
6
6
  routes,
7
7
  slots,
8
- // Environment-specific values (STRIPE_PUBLIC_KEY, VIAX_API_URL) are supplied
9
- // by site.config.{dev,stage,prod}.tsx at site build time.
10
- config: {},
8
+ // Environment-specific values (STRIPE_PUBLIC_KEY, VIAX_API_URL,
9
+ // ENABLE_ANNUAL_BILLING) are supplied by site.config.{dev,stage,prod}.tsx
10
+ // at site build time.
11
+ config: {
12
+ ENABLE_ANNUAL_BILLING: false,
13
+ },
11
14
  };
12
15
  export default app;
13
16
  //# sourceMappingURL=app.js.map
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,MAAM,GAAG,GAAQ;IACf,KAAK;IACL,MAAM;IACN,KAAK;IACL,6EAA6E;IAC7E,0DAA0D;IAC1D,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,eAAe,GAAG,CAAC","sourcesContent":["import { App } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport routes from '@src/routes';\nimport slots from '@src/slots';\n\nconst app: App = {\n appId,\n routes,\n slots,\n // Environment-specific values (STRIPE_PUBLIC_KEY, VIAX_API_URL) are supplied\n // by site.config.{dev,stage,prod}.tsx at site build time.\n config: {},\n};\n\nexport default app;\n"]}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,MAAM,GAAG,GAAQ;IACf,KAAK;IACL,MAAM;IACN,KAAK;IACL,gEAAgE;IAChE,0EAA0E;IAC1E,sBAAsB;IACtB,MAAM,EAAE;QACN,qBAAqB,EAAE,KAAK;KAC7B;CACF,CAAC;AAEF,eAAe,GAAG,CAAC","sourcesContent":["import { App } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport routes from '@src/routes';\nimport slots from '@src/slots';\n\nconst app: App = {\n appId,\n routes,\n slots,\n // Environment-specific values (STRIPE_PUBLIC_KEY, VIAX_API_URL,\n // ENABLE_ANNUAL_BILLING) are supplied by site.config.{dev,stage,prod}.tsx\n // at site build time.\n config: {\n ENABLE_ANNUAL_BILLING: false,\n },\n};\n\nexport default app;\n"]}
@@ -10,6 +10,7 @@ const CheckoutPage = () => {
10
10
  const LMS_BASE_URL = siteConfig.lmsBaseUrl.replace(/\/$/, '');
11
11
  const stripePublishableKey = config.STRIPE_PUBLIC_KEY;
12
12
  const apiUrl = config.VIAX_API_URL;
13
+ const enableAnnualBilling = Boolean(config.ENABLE_ANNUAL_BILLING);
13
14
  const isDevelopment = siteConfig.environment === 'development';
14
15
  const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;
15
16
  console.log('siteConfig ===> ', siteConfig);
@@ -20,7 +21,7 @@ const CheckoutPage = () => {
20
21
  if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {
21
22
  return (_jsx(PageWrapper, { children: _jsxs(Alert, { variant: "danger", children: ["We're having trouble loading the checkout. Please refresh the page or try again in a few moments. If the problem persists,", ' ', _jsx("a", { href: "https://courses.edx.org/support/contact_us", children: "contact support" }), "."] }) }));
22
23
  }
23
- return (_jsx(PageWrapper, { children: _jsx(CheckoutGate, { stripePublishableKey: stripePublishableKey, apiUrl: apiUrl, edxSessionUrl: edxSessionUrl, learnerDashboardUrl: `${LMS_BASE_URL}/dashboard`, homeUrl: LMS_BASE_URL || '/', onComplete: (_subscriptionBiId) => {
24
+ return (_jsx(PageWrapper, { children: _jsx(CheckoutGate, { stripePublishableKey: stripePublishableKey, apiUrl: apiUrl, edxSessionUrl: edxSessionUrl, enableAnnualBilling: enableAnnualBilling, learnerDashboardUrl: `${LMS_BASE_URL}/dashboard`, homeUrl: LMS_BASE_URL || '/', onComplete: (_subscriptionBiId) => {
24
25
  console.log(_subscriptionBiId);
25
26
  // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;
26
27
  // Success screen.
@@ -1 +1 @@
1
- {"version":3,"file":"CheckoutPage.js","sourceRoot":"","sources":["../../src/checkoutPage/CheckoutPage.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,YAAY,MAAM,yCAAyC,CAAC;AAEnE,MAAM,WAAW,GAA4C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7E,KAAC,SAAS,cAAE,QAAQ,GAAa,CAClC,CAAC;AAEF,MAAM,YAAY,GAAa,GAAG,EAAE;IAClC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAA2B,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAsB,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,KAAK,aAAa,CAAC;IAC/D,MAAM,aAAa,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC;IAE1G,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,oBAAoB,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;IAElD,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO,CACL,KAAC,WAAW,cACV,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,2IAEwC,GAAG,EAChE,YAAG,IAAI,EAAC,4CAA4C,gCAEhD,SAEE,GACI,CACf,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,WAAW,cACV,KAAC,YAAY,IACX,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,mBAAmB,EAAE,GAAG,YAAY,YAAY,EAChD,OAAO,EAAE,YAAY,IAAI,GAAG,EAC5B,UAAU,EAAE,CAAC,iBAAiB,EAAE,EAAE;gBAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAC/B,kFAAkF;gBAClF,kBAAkB;YACpB,CAAC,GACD,GACU,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import React from 'react';\nimport { Alert, Container } from '@openedx/paragon';\nimport { getAppConfig, getSiteConfig } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport CheckoutGate from '../components/CheckoutGate/CheckoutGate';\n\nconst PageWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <Container>{children}</Container>\n);\n\nconst CheckoutPage: React.FC = () => {\n const config = getAppConfig(appId);\n const siteConfig = getSiteConfig();\n const LMS_BASE_URL = siteConfig.lmsBaseUrl.replace(/\\/$/, '');\n const stripePublishableKey = config.STRIPE_PUBLIC_KEY as string;\n const apiUrl = config.VIAX_API_URL as string;\n const isDevelopment = siteConfig.environment === 'development';\n const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;\n\n console.log('siteConfig ===> ', siteConfig);\n console.log('config ====> ', config);\n console.log('stripePublishableKey ===> ', stripePublishableKey);\n console.log('apiURL ==> ', apiUrl);\n console.log('edxSessionUrl ===> ', edxSessionUrl);\n\n if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {\n return (\n <PageWrapper>\n <Alert variant=\"danger\">\n We&apos;re having trouble loading the checkout. Please refresh the\n page or try again in a few moments. If the problem persists,{' '}\n <a href=\"https://courses.edx.org/support/contact_us\">\n contact support\n </a>\n .\n </Alert>\n </PageWrapper>\n );\n }\n\n return (\n <PageWrapper>\n <CheckoutGate\n stripePublishableKey={stripePublishableKey}\n apiUrl={apiUrl}\n edxSessionUrl={edxSessionUrl}\n learnerDashboardUrl={`${LMS_BASE_URL}/dashboard`}\n homeUrl={LMS_BASE_URL || '/'}\n onComplete={(_subscriptionBiId) => {\n console.log(_subscriptionBiId);\n // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;\n // Success screen.\n }}\n />\n </PageWrapper>\n );\n};\n\nexport default CheckoutPage;\n"]}
1
+ {"version":3,"file":"CheckoutPage.js","sourceRoot":"","sources":["../../src/checkoutPage/CheckoutPage.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,YAAY,MAAM,yCAAyC,CAAC;AAEnE,MAAM,WAAW,GAA4C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC7E,KAAC,SAAS,cAAE,QAAQ,GAAa,CAClC,CAAC;AAEF,MAAM,YAAY,GAAa,GAAG,EAAE;IAClC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,MAAM,CAAC,iBAA2B,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAsB,CAAC;IAC7C,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,KAAK,aAAa,CAAC;IAC/D,MAAM,aAAa,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC;IAE1G,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,oBAAoB,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;IAElD,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO,CACL,KAAC,WAAW,cACV,MAAC,KAAK,IAAC,OAAO,EAAC,QAAQ,2IAEwC,GAAG,EAChE,YAAG,IAAI,EAAC,4CAA4C,gCAEhD,SAEE,GACI,CACf,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,WAAW,cACV,KAAC,YAAY,IACX,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,mBAAmB,EAAE,mBAAmB,EACxC,mBAAmB,EAAE,GAAG,YAAY,YAAY,EAChD,OAAO,EAAE,YAAY,IAAI,GAAG,EAC5B,UAAU,EAAE,CAAC,iBAAiB,EAAE,EAAE;gBAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAC/B,kFAAkF;gBAClF,kBAAkB;YACpB,CAAC,GACD,GACU,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import React from 'react';\nimport { Alert, Container } from '@openedx/paragon';\nimport { getAppConfig, getSiteConfig } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport CheckoutGate from '../components/CheckoutGate/CheckoutGate';\n\nconst PageWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <Container>{children}</Container>\n);\n\nconst CheckoutPage: React.FC = () => {\n const config = getAppConfig(appId);\n const siteConfig = getSiteConfig();\n const LMS_BASE_URL = siteConfig.lmsBaseUrl.replace(/\\/$/, '');\n const stripePublishableKey = config.STRIPE_PUBLIC_KEY as string;\n const apiUrl = config.VIAX_API_URL as string;\n const enableAnnualBilling = Boolean(config.ENABLE_ANNUAL_BILLING);\n const isDevelopment = siteConfig.environment === 'development';\n const edxSessionUrl = `${isDevelopment ? 'https://courses.stage.edx.org' : LMS_BASE_URL}/api/edx-session`;\n\n console.log('siteConfig ===> ', siteConfig);\n console.log('config ====> ', config);\n console.log('stripePublishableKey ===> ', stripePublishableKey);\n console.log('apiURL ==> ', apiUrl);\n console.log('edxSessionUrl ===> ', edxSessionUrl);\n\n if (!stripePublishableKey || !apiUrl || !edxSessionUrl) {\n return (\n <PageWrapper>\n <Alert variant=\"danger\">\n We&apos;re having trouble loading the checkout. Please refresh the\n page or try again in a few moments. If the problem persists,{' '}\n <a href=\"https://courses.edx.org/support/contact_us\">\n contact support\n </a>\n .\n </Alert>\n </PageWrapper>\n );\n }\n\n return (\n <PageWrapper>\n <CheckoutGate\n stripePublishableKey={stripePublishableKey}\n apiUrl={apiUrl}\n edxSessionUrl={edxSessionUrl}\n enableAnnualBilling={enableAnnualBilling}\n learnerDashboardUrl={`${LMS_BASE_URL}/dashboard`}\n homeUrl={LMS_BASE_URL || '/'}\n onComplete={(_subscriptionBiId) => {\n console.log(_subscriptionBiId);\n // window.location.href = `/checkout/confirmation?sub=${_subscriptionBiId ?? ''}`;\n // Success screen.\n }}\n />\n </PageWrapper>\n );\n};\n\nexport default CheckoutPage;\n"]}
@@ -16,11 +16,16 @@ export interface CartSummaryProps {
16
16
  defaultCycle?: BillingCycle;
17
17
  monthlyRenewalLabel?: string;
18
18
  annualRenewalLabel?: string;
19
- /** Reserved for re-enabling the annual/monthly cycle toggle. */
19
+ /** Called when the learner switches monthly ↔ annual (requires enableAnnualBilling). */
20
20
  onCycleChange?: (cycle: BillingCycle) => void;
21
+ /**
22
+ * When true, shows the Switch to annual/monthly control.
23
+ * Controlled via ENABLE_ANNUAL_BILLING in site.config.*.tsx.
24
+ */
25
+ enableAnnualBilling?: boolean;
21
26
  learnerCount?: number;
22
27
  /** When set, shows the course enrollment preview card below the summary card. */
23
28
  course?: CourseDetail | null;
24
29
  }
25
- declare const CartSummary: ({ productTitle, productBlurb, monthlyAmount, monthlyRegularAmount, promoMonths, annualAmount, currency, activeSubscriberCount, defaultCycle, learnerCount: learnerCountProp, course, }: CartSummaryProps) => import("react/jsx-runtime").JSX.Element;
30
+ declare const CartSummary: ({ productTitle, productBlurb, monthlyAmount, monthlyRegularAmount, promoMonths, annualAmount, currency, activeSubscriberCount, defaultCycle, onCycleChange, enableAnnualBilling, learnerCount: learnerCountProp, course, }: CartSummaryProps) => import("react/jsx-runtime").JSX.Element;
26
31
  export default CartSummary;
@@ -1,29 +1,30 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Badge, Card, Icon } from '@openedx/paragon';
2
+ import { Badge, Button, Card, Icon } from '@openedx/paragon';
3
3
  import { Group, People, Institution } from '@openedx/paragon/icons';
4
4
  import { useIntl } from '@openedx/frontend-base';
5
5
  import { EdxUnlimitedLogo } from '../BrandMarks/BrandMarks';
6
6
  import CourseEnrollmentCard from '../CourseEnrollmentCard/CourseEnrollmentCard';
7
7
  import messages from './Messages';
8
- const CartSummary = ({ productTitle = 'edX Subscription', productBlurb = 'Subscribe and get access to hundreds of courses and programs.', monthlyAmount = '39', monthlyRegularAmount = '59', promoMonths = 3, annualAmount = '299', currency = 'USD', activeSubscriberCount, defaultCycle = 'monthly', learnerCount: learnerCountProp = 2203, course = null, }) => {
8
+ const CartSummary = ({ productTitle = 'edX Subscription', productBlurb = 'Subscribe and get access to hundreds of courses and programs.', monthlyAmount = '39', monthlyRegularAmount = '59', promoMonths = 3, annualAmount = '299', currency = 'USD', activeSubscriberCount, defaultCycle = 'monthly', onCycleChange, enableAnnualBilling = false, learnerCount: learnerCountProp = 2203, course = null, }) => {
9
9
  const { formatMessage } = useIntl();
10
10
  const isMonthly = defaultCycle === 'monthly';
11
+ const showCycleToggle = enableAnnualBilling && !!onCycleChange;
11
12
  const learnerCount = (activeSubscriberCount != null ? activeSubscriberCount : learnerCountProp).toLocaleString();
12
13
  return (_jsxs("div", { className: "cart-summary ", children: [_jsxs(Card, { className: "cart-summary__card p-3", children: [_jsxs(Card.Section, { className: "d-flex justify-content-between align-items-center p-0 pb-3", children: [_jsx("span", { className: "font-weight-bold text-gray-900", children: formatMessage(messages.summaryHeading) }), _jsxs(Badge, { variant: "light", className: "d-flex align-items-center px-2 py-1", children: [_jsx(Icon, { src: Group, className: "mr-1", style: { width: '1rem', height: '1rem' } }), formatMessage(messages.learnersSubscribed, {
13
14
  count: learnerCount,
14
- })] })] }), _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 py-3", children: _jsxs("div", { className: "d-flex justify-content-between align-items-start mb-1", children: [_jsx("span", { className: "small text-gray-900", children: isMonthly
15
- ? formatMessage(messages.monthlySubscription)
16
- : formatMessage(messages.annualSubscription) }), _jsxs("div", { className: "cart-summary__pricing text-right", children: [_jsx("div", { className: "text-success font-weight-bold small", children: formatMessage(messages.trialLabel) }), isMonthly ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.promotionalPrice, {
17
- amount: monthlyAmount,
18
- months: promoMonths,
19
- }) }), _jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.regularPrice, {
20
- amount: monthlyRegularAmount,
21
- currency,
22
- }) })] })) : (_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.priceDisplay, {
23
- amount: annualAmount,
24
- frequency: 'year',
25
- currency,
26
- }) }))] })] }) }), _jsxs(Card.Section, { className: "d-flex justify-content-between align-items-center px-0", children: [_jsx("span", { className: "font-weight-bold text-gray-900", children: formatMessage(messages.todaysTotal) }), _jsx("span", { className: "font-weight-bold mb-0 text-gray-900", children: formatMessage(messages.todaysTotalValue) })] })] }), course && (_jsx(CourseEnrollmentCard, { course: course, variant: "checkout" })), _jsxs("div", { className: "cart-summary__stats d-none d-lg-flex mt-3", children: [_jsxs("div", { className: "cart-summary__stat d-flex align-items-center mr-4", children: [_jsx(Icon, { src: People, className: "mr-2 text-muted", style: { width: '1.5rem', height: '1.5rem' } }), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-0", children: formatMessage(messages.learnersCount) }), _jsx("p", { className: "text-muted small mb-0", children: formatMessage(messages.learnersLabel) })] })] }), _jsxs("div", { className: "cart-summary__stat d-flex align-items-center", children: [_jsx(Icon, { src: Institution, className: "mr-2 text-muted", style: { width: '1.5rem', height: '1.5rem' } }), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-0", children: formatMessage(messages.institutionsCount) }), _jsx("p", { className: "text-muted small mb-0", children: formatMessage(messages.institutionsLabel) })] })] })] })] }));
15
+ })] })] }), _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, {}), _jsxs(Card.Section, { className: "p-0 py-3", children: [_jsxs("div", { className: "d-flex justify-content-between align-items-start mb-1", children: [_jsx("span", { className: "small text-gray-900", children: isMonthly
16
+ ? formatMessage(messages.monthlySubscription)
17
+ : formatMessage(messages.annualSubscription) }), _jsxs("div", { className: "cart-summary__pricing text-right", children: [_jsx("div", { className: "text-success font-weight-bold small", children: formatMessage(messages.trialLabel) }), isMonthly ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.promotionalPrice, {
18
+ amount: monthlyAmount,
19
+ months: promoMonths,
20
+ }) }), _jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.regularPrice, {
21
+ amount: monthlyRegularAmount,
22
+ currency,
23
+ }) })] })) : (_jsx("div", { className: "small text-gray-900 font-weight-bold", children: formatMessage(messages.priceDisplay, {
24
+ amount: annualAmount,
25
+ frequency: 'year',
26
+ currency,
27
+ }) }))] })] }), showCycleToggle && (_jsx("div", { className: "mt-2", children: _jsx(Button, { variant: "link", className: "cart-summary__cycle-toggle p-0", onClick: () => onCycleChange === null || onCycleChange === void 0 ? void 0 : onCycleChange(isMonthly ? 'annual' : 'monthly'), children: formatMessage(isMonthly ? messages.switchToAnnual : messages.switchToMonthly) }) }))] }), _jsxs(Card.Section, { className: "d-flex justify-content-between align-items-center px-0", children: [_jsx("span", { className: "font-weight-bold text-gray-900", children: formatMessage(messages.todaysTotal) }), _jsx("span", { className: "font-weight-bold mb-0 text-gray-900", children: formatMessage(messages.todaysTotalValue) })] })] }), course && (_jsx(CourseEnrollmentCard, { course: course, variant: "checkout" })), _jsxs("div", { className: "cart-summary__stats d-none d-lg-flex mt-3", children: [_jsxs("div", { className: "cart-summary__stat d-flex align-items-center mr-4", children: [_jsx(Icon, { src: People, className: "mr-2 text-muted", style: { width: '1.5rem', height: '1.5rem' } }), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-0", children: formatMessage(messages.learnersCount) }), _jsx("p", { className: "text-muted small mb-0", children: formatMessage(messages.learnersLabel) })] })] }), _jsxs("div", { className: "cart-summary__stat d-flex align-items-center", children: [_jsx(Icon, { src: Institution, className: "mr-2 text-muted", style: { width: '1.5rem', height: '1.5rem' } }), _jsxs("div", { children: [_jsx("p", { className: "font-weight-bold mb-0", children: formatMessage(messages.institutionsCount) }), _jsx("p", { className: "text-muted small mb-0", children: formatMessage(messages.institutionsLabel) })] })] })] })] }));
27
28
  };
28
29
  export default CartSummary;
29
30
  //# sourceMappingURL=CartSummary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CartSummary.js","sourceRoot":"","sources":["../../../src/components/CartSummary/CartSummary.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Badge, Card, Icon } from '@openedx/paragon';\nimport { Group, People, Institution } from '@openedx/paragon/icons';\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 type BillingCycle = 'monthly' | 'annual';\n\nexport interface CartSummaryProps {\n productTitle?: string,\n productBlurb?: string,\n /** Promotional monthly price amount e.g. \"39\" */\n monthlyAmount?: string,\n /** Regular monthly price after the promo period e.g. \"59\" */\n monthlyRegularAmount?: string,\n /** Length of the promotional period in months */\n promoMonths?: number,\n /** Annual price amount e.g. \"299\" */\n annualAmount?: string,\n currency?: string,\n activeSubscriberCount?: number | null,\n defaultCycle?: BillingCycle,\n monthlyRenewalLabel?: string,\n annualRenewalLabel?: string,\n /** Reserved for re-enabling the annual/monthly cycle toggle. */\n onCycleChange?: (cycle: BillingCycle) => void,\n learnerCount?: number,\n /** When set, shows the course enrollment preview card below the summary card. */\n course?: CourseDetail | null,\n}\n\nconst CartSummary = ({\n productTitle = 'edX Subscription',\n productBlurb = 'Subscribe and get access to hundreds of courses and programs.',\n monthlyAmount = '39',\n monthlyRegularAmount = '59',\n promoMonths = 3,\n annualAmount = '299',\n currency = 'USD',\n activeSubscriberCount,\n defaultCycle = 'monthly',\n learnerCount: learnerCountProp = 2203,\n course = null,\n}: CartSummaryProps) => {\n const { formatMessage } = useIntl();\n const isMonthly = defaultCycle === 'monthly';\n\n const learnerCount = (\n activeSubscriberCount != null ? activeSubscriberCount : learnerCountProp\n ).toLocaleString();\n\n return (\n <div className=\"cart-summary \">\n <Card className=\"cart-summary__card p-3\">\n <Card.Section className=\"d-flex justify-content-between align-items-center p-0 pb-3\">\n <span className=\"font-weight-bold text-gray-900\">\n {formatMessage(messages.summaryHeading)}\n </span>\n <Badge\n variant=\"light\"\n className=\"d-flex align-items-center px-2 py-1\"\n >\n <Icon\n src={Group}\n className=\"mr-1\"\n style={{ width: '1rem', height: '1rem' }}\n />\n {formatMessage(messages.learnersSubscribed, {\n count: learnerCount,\n })}\n </Badge>\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 py-3\">\n <div className=\"d-flex justify-content-between align-items-start mb-1\">\n <span className=\"small text-gray-900\">\n {isMonthly\n ? formatMessage(messages.monthlySubscription)\n : formatMessage(messages.annualSubscription)}\n </span>\n <div className=\"cart-summary__pricing text-right\">\n <div className=\"text-success font-weight-bold small\">\n {formatMessage(messages.trialLabel)}\n </div>\n {isMonthly ? (\n <>\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.promotionalPrice, {\n amount: monthlyAmount,\n months: promoMonths,\n })}\n </div>\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.regularPrice, {\n amount: monthlyRegularAmount,\n currency,\n })}\n </div>\n </>\n ) : (\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.priceDisplay, {\n amount: annualAmount,\n frequency: 'year',\n currency,\n })}\n </div>\n )}\n </div>\n </div>\n </Card.Section>\n\n <Card.Section className=\"d-flex justify-content-between align-items-center px-0\">\n <span className=\"font-weight-bold text-gray-900\">\n {formatMessage(messages.todaysTotal)}\n </span>\n <span className=\"font-weight-bold mb-0 text-gray-900\">\n {formatMessage(messages.todaysTotalValue)}\n </span>\n </Card.Section>\n </Card>\n\n {course && (\n <CourseEnrollmentCard course={course} variant=\"checkout\" />\n )}\n\n {/* Stats row */}\n <div className=\"cart-summary__stats d-none d-lg-flex mt-3\">\n <div className=\"cart-summary__stat d-flex align-items-center mr-4\">\n <Icon\n src={People}\n className=\"mr-2 text-muted\"\n style={{ width: '1.5rem', height: '1.5rem' }}\n />\n <div>\n <p className=\"font-weight-bold mb-0\">\n {formatMessage(messages.learnersCount)}\n </p>\n <p className=\"text-muted small mb-0\">\n {formatMessage(messages.learnersLabel)}\n </p>\n </div>\n </div>\n <div className=\"cart-summary__stat d-flex align-items-center\">\n <Icon\n src={Institution}\n className=\"mr-2 text-muted\"\n style={{ width: '1.5rem', height: '1.5rem' }}\n />\n <div>\n <p className=\"font-weight-bold mb-0\">\n {formatMessage(messages.institutionsCount)}\n </p>\n <p className=\"text-muted small mb-0\">\n {formatMessage(messages.institutionsLabel)}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CartSummary;\n"]}
1
+ {"version":3,"file":"CartSummary.js","sourceRoot":"","sources":["../../../src/components/CartSummary/CartSummary.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Badge, Button, Card, Icon } from '@openedx/paragon';\nimport { Group, People, Institution } from '@openedx/paragon/icons';\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 type BillingCycle = 'monthly' | 'annual';\n\nexport interface CartSummaryProps {\n productTitle?: string,\n productBlurb?: string,\n /** Promotional monthly price amount e.g. \"39\" */\n monthlyAmount?: string,\n /** Regular monthly price after the promo period e.g. \"59\" */\n monthlyRegularAmount?: string,\n /** Length of the promotional period in months */\n promoMonths?: number,\n /** Annual price amount e.g. \"299\" */\n annualAmount?: string,\n currency?: string,\n activeSubscriberCount?: number | null,\n defaultCycle?: BillingCycle,\n monthlyRenewalLabel?: string,\n annualRenewalLabel?: string,\n /** Called when the learner switches monthly ↔ annual (requires enableAnnualBilling). */\n onCycleChange?: (cycle: BillingCycle) => void,\n /**\n * When true, shows the Switch to annual/monthly control.\n * Controlled via ENABLE_ANNUAL_BILLING in site.config.*.tsx.\n */\n enableAnnualBilling?: boolean,\n learnerCount?: number,\n /** When set, shows the course enrollment preview card below the summary card. */\n course?: CourseDetail | null,\n}\n\nconst CartSummary = ({\n productTitle = 'edX Subscription',\n productBlurb = 'Subscribe and get access to hundreds of courses and programs.',\n monthlyAmount = '39',\n monthlyRegularAmount = '59',\n promoMonths = 3,\n annualAmount = '299',\n currency = 'USD',\n activeSubscriberCount,\n defaultCycle = 'monthly',\n onCycleChange,\n enableAnnualBilling = false,\n learnerCount: learnerCountProp = 2203,\n course = null,\n}: CartSummaryProps) => {\n const { formatMessage } = useIntl();\n const isMonthly = defaultCycle === 'monthly';\n const showCycleToggle = enableAnnualBilling && !!onCycleChange;\n\n const learnerCount = (\n activeSubscriberCount != null ? activeSubscriberCount : learnerCountProp\n ).toLocaleString();\n\n return (\n <div className=\"cart-summary \">\n <Card className=\"cart-summary__card p-3\">\n <Card.Section className=\"d-flex justify-content-between align-items-center p-0 pb-3\">\n <span className=\"font-weight-bold text-gray-900\">\n {formatMessage(messages.summaryHeading)}\n </span>\n <Badge\n variant=\"light\"\n className=\"d-flex align-items-center px-2 py-1\"\n >\n <Icon\n src={Group}\n className=\"mr-1\"\n style={{ width: '1rem', height: '1rem' }}\n />\n {formatMessage(messages.learnersSubscribed, {\n count: learnerCount,\n })}\n </Badge>\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 py-3\">\n <div className=\"d-flex justify-content-between align-items-start mb-1\">\n <span className=\"small text-gray-900\">\n {isMonthly\n ? formatMessage(messages.monthlySubscription)\n : formatMessage(messages.annualSubscription)}\n </span>\n <div className=\"cart-summary__pricing text-right\">\n <div className=\"text-success font-weight-bold small\">\n {formatMessage(messages.trialLabel)}\n </div>\n {isMonthly ? (\n <>\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.promotionalPrice, {\n amount: monthlyAmount,\n months: promoMonths,\n })}\n </div>\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.regularPrice, {\n amount: monthlyRegularAmount,\n currency,\n })}\n </div>\n </>\n ) : (\n <div className=\"small text-gray-900 font-weight-bold\">\n {formatMessage(messages.priceDisplay, {\n amount: annualAmount,\n frequency: 'year',\n currency,\n })}\n </div>\n )}\n </div>\n </div>\n {showCycleToggle && (\n <div className=\"mt-2\">\n <Button\n variant=\"link\"\n className=\"cart-summary__cycle-toggle p-0\"\n onClick={() => onCycleChange?.(isMonthly ? 'annual' : 'monthly')}\n >\n {formatMessage(\n isMonthly ? messages.switchToAnnual : messages.switchToMonthly,\n )}\n </Button>\n </div>\n )}\n </Card.Section>\n\n <Card.Section className=\"d-flex justify-content-between align-items-center px-0\">\n <span className=\"font-weight-bold text-gray-900\">\n {formatMessage(messages.todaysTotal)}\n </span>\n <span className=\"font-weight-bold mb-0 text-gray-900\">\n {formatMessage(messages.todaysTotalValue)}\n </span>\n </Card.Section>\n </Card>\n\n {course && (\n <CourseEnrollmentCard course={course} variant=\"checkout\" />\n )}\n\n {/* Stats row */}\n <div className=\"cart-summary__stats d-none d-lg-flex mt-3\">\n <div className=\"cart-summary__stat d-flex align-items-center mr-4\">\n <Icon\n src={People}\n className=\"mr-2 text-muted\"\n style={{ width: '1.5rem', height: '1.5rem' }}\n />\n <div>\n <p className=\"font-weight-bold mb-0\">\n {formatMessage(messages.learnersCount)}\n </p>\n <p className=\"text-muted small mb-0\">\n {formatMessage(messages.learnersLabel)}\n </p>\n </div>\n </div>\n <div className=\"cart-summary__stat d-flex align-items-center\">\n <Icon\n src={Institution}\n className=\"mr-2 text-muted\"\n style={{ width: '1.5rem', height: '1.5rem' }}\n />\n <div>\n <p className=\"font-weight-bold mb-0\">\n {formatMessage(messages.institutionsCount)}\n </p>\n <p className=\"text-muted small mb-0\">\n {formatMessage(messages.institutionsLabel)}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CartSummary;\n"]}
@@ -2,6 +2,11 @@ import type { UseCheckoutOptions } from '../../data/hooks/useCheckout';
2
2
  export type CheckoutProps = UseCheckoutOptions & {
3
3
  /** Homepage URL for the country-unavailable modal CTA. */
4
4
  homeUrl?: string;
5
+ /**
6
+ * When true, learners can switch between monthly and annual billing.
7
+ * Sourced from ENABLE_ANNUAL_BILLING in site.config.*.tsx.
8
+ */
9
+ enableAnnualBilling?: boolean;
5
10
  };
6
- declare const Checkout: ({ homeUrl, ...props }: CheckoutProps) => import("react/jsx-runtime").JSX.Element;
11
+ declare const Checkout: ({ homeUrl, enableAnnualBilling, ...props }: CheckoutProps) => import("react/jsx-runtime").JSX.Element;
7
12
  export default Checkout;
@@ -10,6 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { useEffect } from 'react';
13
14
  import { Alert, Col, Row } from '@openedx/paragon';
14
15
  import { Error as ErrorIcon } from '@openedx/paragon/icons';
15
16
  import useCheckout from '../../data/hooks/useCheckout';
@@ -21,10 +22,24 @@ import CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailab
21
22
  import { getPlanPrice, getRenewalLabel } from '../../utils/billingDetails';
22
23
  import { getTrialDateRange } from '../../utils';
23
24
  import { SuccessScreen, BlockedScreen } from '../StatusScreens/StatusScreens';
25
+ /** Resolve purchased cycle from subscription details, falling back to checkout selection. */
26
+ function resolvePurchasedCycle(selectedCycle, planName, renewalType) {
27
+ const haystack = `${planName !== null && planName !== void 0 ? planName : ''} ${renewalType !== null && renewalType !== void 0 ? renewalType : ''}`.toLowerCase();
28
+ if (haystack.includes('annual') || haystack.includes('year'))
29
+ return 'annual';
30
+ if (haystack.includes('month'))
31
+ return 'monthly';
32
+ return selectedCycle;
33
+ }
24
34
  const Checkout = (_a) => {
25
- var _b, _c, _d;
26
- var { homeUrl = '/' } = _a, props = __rest(_a, ["homeUrl"]);
35
+ var _b, _c, _d, _e, _f;
36
+ var { homeUrl = '/', enableAnnualBilling = false } = _a, props = __rest(_a, ["homeUrl", "enableAnnualBilling"]);
27
37
  const c = useCheckout(props);
38
+ useEffect(() => {
39
+ if (!enableAnnualBilling && c.selectedCycle !== 'monthly') {
40
+ c.setCycle('monthly');
41
+ }
42
+ }, [enableAnnualBilling, c.selectedCycle, c.setCycle]);
28
43
  const showForm = c.phase === 'init'
29
44
  || c.phase === 'ready'
30
45
  || c.phase === 'failed'
@@ -36,6 +51,12 @@ const Checkout = (_a) => {
36
51
  const isBillingCountryBlocked = GATE_CHECK_COUNTRY
37
52
  && !!c.billing.country
38
53
  && !ALLOWED_CHECKOUT_COUNTRIES.includes(c.billing.country);
54
+ // Keep annual selection only when the feature flag is on.
55
+ const selectedCycle = enableAnnualBilling
56
+ ? c.selectedCycle
57
+ : 'monthly';
58
+ const purchasedCycle = resolvePurchasedCycle(selectedCycle, (_b = c.subscriptionDetails) === null || _b === void 0 ? void 0 : _b.planName, (_c = c.subscriptionDetails) === null || _c === void 0 ? void 0 : _c.renewalType);
59
+ const purchasedPrice = getPlanPrice(c.billingPlans, purchasedCycle);
39
60
  const handleStartCourse = () => {
40
61
  var _a;
41
62
  if ((_a = c.course) === null || _a === void 0 ? void 0 : _a.tUrlCourse) {
@@ -49,9 +70,9 @@ const Checkout = (_a) => {
49
70
  ? [c.course.tBrandText, c.course.maName].filter(Boolean).join(': ')
50
71
  : null;
51
72
  return (_jsxs(Row, { className: "checkout__container bg-light-200", children: [_jsx(CountryUnavailableModal, { isOpen: isBillingCountryBlocked, homeUrl: homeUrl }), _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
52
- || '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: ((_b = c.subscriptionDetails) === null || _b === void 0 ? void 0 : _b.biId) || '', cardLast4: ((_c = c.subscriptionDetails) === null || _c === void 0 ? void 0 : _c.cardLast4) || '', trialStart: displayStart, trialEnd: displayEnd, priceToShow: c.selectedCycle === 'monthly'
73
+ || '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: selectedCycle === 'monthly' ? monthlyPrice : annualPrice, cycleToShow: selectedCycle === 'monthly' ? 'monthly' : 'annual', userCountry: c.userCountry })] })), c.phase === 'success' && (_jsx(SuccessScreen, { subscriptionBiId: ((_d = c.subscriptionDetails) === null || _d === void 0 ? void 0 : _d.biId) || '', cardLast4: ((_e = c.subscriptionDetails) === null || _e === void 0 ? void 0 : _e.cardLast4) || '', purchaseDate: displayStart, trialStart: displayStart, trialEnd: displayEnd, priceToShow: purchasedCycle === 'monthly'
53
74
  ? monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.label
54
- : 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, { monthlyAmount: monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.amount, annualAmount: annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.amount, currency: (_d = monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.currency) !== null && _d !== void 0 ? _d : annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.currency, monthlyRenewalLabel: getRenewalLabel(c.billingPlans, 'monthly'), annualRenewalLabel: getRenewalLabel(c.billingPlans, 'annual'), activeSubscriberCount: c.activeSubscriberCount, defaultCycle: c.selectedCycle, onCycleChange: c.setCycle, course: c.course })) })] }) })] }));
75
+ : annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.label, cycleToShow: purchasedCycle === '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, { amount: purchasedPrice === null || purchasedPrice === void 0 ? void 0 : purchasedPrice.amount, currency: purchasedPrice === null || purchasedPrice === void 0 ? void 0 : purchasedPrice.currency, cycleToShow: purchasedCycle, course: c.course, onStartCourse: handleStartCourse })) : (_jsx(CartSummary, { monthlyRegularAmount: monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.amount, annualAmount: annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.amount, currency: (_f = monthlyPrice === null || monthlyPrice === void 0 ? void 0 : monthlyPrice.currency) !== null && _f !== void 0 ? _f : annualPrice === null || annualPrice === void 0 ? void 0 : annualPrice.currency, monthlyRenewalLabel: getRenewalLabel(c.billingPlans, 'monthly'), annualRenewalLabel: getRenewalLabel(c.billingPlans, 'annual'), activeSubscriberCount: c.activeSubscriberCount, defaultCycle: selectedCycle, onCycleChange: c.setCycle, enableAnnualBilling: enableAnnualBilling, course: c.course })) })] }) })] }));
55
76
  };
56
77
  export default Checkout;
57
78
  //# sourceMappingURL=Checkout.js.map
@@ -1 +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 { ALLOWED_CHECKOUT_COUNTRIES, GATE_CHECK_COUNTRY } from '../../constants';\nimport CartSummary from '../CartSummary/CartSummary';\nimport EnrollmentSummary from '../EnrollmentSummary/EnrollmentSummary';\nimport PaymentForm from '../PaymentForm/PaymentForm';\nimport CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailableModal';\nimport { getPlanPrice, getRenewalLabel } from '../../utils/billingDetails';\nimport { getTrialDateRange } from '@src/utils';\nimport { SuccessScreen, BlockedScreen } from '../StatusScreens/StatusScreens';\n\nexport type CheckoutProps = UseCheckoutOptions & {\n /** Homepage URL for the country-unavailable modal CTA. */\n homeUrl?: string,\n};\n\nconst Checkout = ({ homeUrl = '/', ...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 isBillingCountryBlocked = GATE_CHECK_COUNTRY\n && !!c.billing.country\n && !ALLOWED_CHECKOUT_COUNTRIES.includes(c.billing.country);\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 <CountryUnavailableModal\n isOpen={isBillingCountryBlocked}\n homeUrl={homeUrl}\n />\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 monthlyAmount={monthlyPrice?.amount}\n annualAmount={annualPrice?.amount}\n currency={monthlyPrice?.currency ?? annualPrice?.currency}\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"]}
1
+ {"version":3,"file":"Checkout.js","sourceRoot":"","sources":["../../../src/components/Checkout/Checkout.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect } 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 { ALLOWED_CHECKOUT_COUNTRIES, GATE_CHECK_COUNTRY } from '../../constants';\nimport CartSummary from '../CartSummary/CartSummary';\nimport EnrollmentSummary from '../EnrollmentSummary/EnrollmentSummary';\nimport PaymentForm from '../PaymentForm/PaymentForm';\nimport CountryUnavailableModal from '../CountryUnavailableModal/CountryUnavailableModal';\nimport { getPlanPrice, getRenewalLabel } from '../../utils/billingDetails';\nimport { getTrialDateRange } from '@src/utils';\nimport { SuccessScreen, BlockedScreen } from '../StatusScreens/StatusScreens';\nimport type { BillingCycle } from '../../types';\n\n/** Resolve purchased cycle from subscription details, falling back to checkout selection. */\nfunction resolvePurchasedCycle(\n selectedCycle: BillingCycle,\n planName?: string | null,\n renewalType?: string | null,\n): BillingCycle {\n const haystack = `${planName ?? ''} ${renewalType ?? ''}`.toLowerCase();\n if (haystack.includes('annual') || haystack.includes('year')) return 'annual';\n if (haystack.includes('month')) return 'monthly';\n return selectedCycle;\n}\n\nexport type CheckoutProps = UseCheckoutOptions & {\n /** Homepage URL for the country-unavailable modal CTA. */\n homeUrl?: string,\n /**\n * When true, learners can switch between monthly and annual billing.\n * Sourced from ENABLE_ANNUAL_BILLING in site.config.*.tsx.\n */\n enableAnnualBilling?: boolean,\n};\n\nconst Checkout = ({\n homeUrl = '/',\n enableAnnualBilling = false,\n ...props\n}: CheckoutProps) => {\n const c = useCheckout(props);\n\n useEffect(() => {\n if (!enableAnnualBilling && c.selectedCycle !== 'monthly') {\n c.setCycle('monthly');\n }\n }, [enableAnnualBilling, c.selectedCycle, c.setCycle]);\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 isBillingCountryBlocked = GATE_CHECK_COUNTRY\n && !!c.billing.country\n && !ALLOWED_CHECKOUT_COUNTRIES.includes(c.billing.country);\n\n // Keep annual selection only when the feature flag is on.\n const selectedCycle: BillingCycle = enableAnnualBilling\n ? c.selectedCycle\n : 'monthly';\n\n const purchasedCycle = resolvePurchasedCycle(\n selectedCycle,\n c.subscriptionDetails?.planName,\n c.subscriptionDetails?.renewalType,\n );\n const purchasedPrice = getPlanPrice(c.billingPlans, purchasedCycle);\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 <CountryUnavailableModal\n isOpen={isBillingCountryBlocked}\n homeUrl={homeUrl}\n />\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 selectedCycle === 'monthly' ? monthlyPrice : annualPrice\n }\n cycleToShow={\n 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 purchaseDate={displayStart}\n trialStart={displayStart}\n trialEnd={displayEnd}\n priceToShow={\n purchasedCycle === 'monthly'\n ? monthlyPrice?.label\n : annualPrice?.label\n }\n cycleToShow={\n purchasedCycle === '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 amount={purchasedPrice?.amount}\n currency={purchasedPrice?.currency}\n cycleToShow={purchasedCycle}\n course={c.course}\n onStartCourse={handleStartCourse}\n />\n ) : (\n <CartSummary\n monthlyRegularAmount={monthlyPrice?.amount}\n annualAmount={annualPrice?.amount}\n currency={monthlyPrice?.currency ?? annualPrice?.currency}\n monthlyRenewalLabel={getRenewalLabel(c.billingPlans, 'monthly')}\n annualRenewalLabel={getRenewalLabel(c.billingPlans, 'annual')}\n activeSubscriberCount={c.activeSubscriberCount}\n defaultCycle={selectedCycle}\n onCycleChange={c.setCycle}\n enableAnnualBilling={enableAnnualBilling}\n course={c.course}\n />\n )}\n </Col>\n </Row>\n </Col>\n </Row>\n );\n};\n\nexport default Checkout;\n"]}
@@ -2,11 +2,12 @@ import type { CourseDetail } from '../../types';
2
2
  export interface EnrollmentSummaryProps {
3
3
  productTitle?: string;
4
4
  productBlurb?: string;
5
- /** e.g. "39" */
5
+ /** e.g. "59" or "396" from getBillingPlans */
6
6
  amount?: string;
7
7
  /** e.g. "USD" */
8
8
  currency?: string;
9
- cycleToShow?: string;
9
+ /** Billing cycle for the purchased plan. */
10
+ cycleToShow?: 'monthly' | 'annual';
10
11
  /** When set, shows the enrolled course card below the purchase summary. */
11
12
  course?: CourseDetail | null;
12
13
  onStartCourse?: () => void;
@@ -4,18 +4,20 @@ import { useIntl } from '@openedx/frontend-base';
4
4
  import { EdxUnlimitedLogo } from '../BrandMarks/BrandMarks';
5
5
  import CourseEnrollmentCard from '../CourseEnrollmentCard/CourseEnrollmentCard';
6
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, }) => {
7
+ const EnrollmentSummary = ({ productTitle = 'edX Plus', productBlurb = 'Access to hundreds of courses and programs.', amount, currency = 'USD', cycleToShow = 'monthly', course = null, onStartCourse, }) => {
8
8
  const { formatMessage } = useIntl();
9
9
  const isMonthly = cycleToShow === 'monthly';
10
10
  const frequency = isMonthly ? 'month' : 'year';
11
11
  const cycleLabel = isMonthly
12
12
  ? formatMessage(messages.monthlySubscription)
13
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, {
14
+ 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("span", { className: "small text-gray-900 font-weight-bold", children: amount
15
+ ? formatMessage(messages.priceDisplay, {
15
16
  amount,
16
17
  frequency,
17
18
  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
+ : null })] }) }), _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: formatMessage(messages.todaysTotalValue) })] })] }), course && (_jsx(CourseEnrollmentCard, { course: course, variant: "success", onStartCourse: onStartCourse }))] }));
19
21
  };
20
22
  export default EnrollmentSummary;
21
23
  //# sourceMappingURL=EnrollmentSummary.js.map
@@ -1 +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"]}
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;AAgBlC,MAAM,iBAAiB,GAAG,CAAC,EACzB,YAAY,GAAG,UAAU,EACzB,YAAY,GAAG,6CAA6C,EAC5D,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,8BAA8B,aAC5C,KAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAC,UAAU,YAChC,YAAG,SAAS,EAAC,qCAAqC,YAC/C,aAAa,CAAC,QAAQ,CAAC,eAAe,CAAC,GACtC,GACS,EAEf,KAAC,IAAI,CAAC,OAAO,KAAG,EAEhB,KAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAC,UAAU,YAChC,eAAK,SAAS,EAAC,0BAA0B,aACvC,KAAC,gBAAgB,KAAG,EACpB,0BACE,YAAG,SAAS,EAAC,wCAAwC,YAClD,YAAY,GACX,EACJ,YAAG,SAAS,EAAC,0BAA0B,YAAE,YAAY,GAAK,IACtD,IACF,GACO,EAEf,KAAC,IAAI,CAAC,OAAO,KAAG,EAEhB,KAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAC,eAAe,YACrC,eAAK,SAAS,EAAC,kDAAkD,aAC/D,eAAM,SAAS,EAAC,qBAAqB,YAAE,UAAU,GAAQ,EACzD,eAAM,SAAS,EAAC,sCAAsC,YACnD,MAAM;wCACL,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,EAAE;4CACnC,MAAM;4CACN,SAAS;4CACT,QAAQ;yCACT,CAAC;wCACJ,CAAC,CAAC,IAAI,GACH,IACH,GACO,EAEf,MAAC,IAAI,CAAC,OAAO,IAAC,SAAS,EAAC,6DAA6D,aACnF,eAAM,SAAS,EAAC,gCAAgC,YAC7C,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAC/B,EACP,eAAM,SAAS,EAAC,oCAAoC,YACjD,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. \"59\" or \"396\" from getBillingPlans */\n amount?: 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 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__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 <span className=\"small text-gray-900 font-weight-bold\">\n {amount\n ? formatMessage(messages.priceDisplay, {\n amount,\n frequency,\n currency,\n })\n : null}\n </span>\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 {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"]}
@@ -17,8 +17,8 @@ const messages = defineMessages({
17
17
  },
18
18
  priceDisplay: {
19
19
  id: 'checkout.enrollmentSummary.priceDisplay',
20
- defaultMessage: '${amount}/{frequency} USD',
21
- description: 'Price display in the purchase summary',
20
+ defaultMessage: '${amount}/{frequency} {currency}',
21
+ description: 'Price display in the purchase summary e.g. $396/year USD',
22
22
  },
23
23
  todaysTotal: {
24
24
  id: 'checkout.enrollmentSummary.todaysTotal',
@@ -1 +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"]}
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,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,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} {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\",\n },\n});\n\nexport default messages;\n"]}
@@ -3,7 +3,7 @@ import { useState } from 'react';
3
3
  import { Button, Form, Spinner } from '@openedx/paragon';
4
4
  import { useIntl } from '@openedx/frontend-base';
5
5
  import PaymentFields from '../PaymentFields/PaymentFields';
6
- import { COUNTRIES_REQUIRING_EXTRA_CONFIRM, COUNTRIES } from '../../constants';
6
+ import { COUNTRIES_REQUIRING_EXTRA_CONFIRM, BILLING_COUNTRIES } from '../../constants';
7
7
  import messages from './Messages';
8
8
  const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, userCountry, }) => {
9
9
  var _a;
@@ -48,9 +48,9 @@ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMou
48
48
  };
49
49
  return (_jsxs("div", { className: "payment-form bg-white", children: [_jsx("h2", { className: "payment-form__heading font-weight-bold mb-3 text-primary-500", children: formatMessage(messages.selectPaymentMethod) }), _jsxs("p", { className: "payment-form__help small mb-4", children: [_jsx("strong", { className: "d-block text-primary-500", children: formatMessage(messages.needAssistance) }), ' ', _jsx("span", { className: "text-gray-700", children: formatMessage(messages.needAssistanceBody, {
50
50
  link: (_jsx("a", { href: "https://support.edx.org", target: "_blank", rel: "noreferrer", className: "text-gray-700", children: formatMessage(messages.learnerHelpCenter) })),
51
- }) })] }), _jsxs("div", { className: "payment-form__methods mb-4", children: [_jsxs("div", { className: `payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`, children: [_jsxs("label", { htmlFor: "paymentMethod-card", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-card", type: "radio", name: "paymentMethod", value: "card", checked: paymentMethod === 'card', onChange: () => setPaymentMethod('card'), className: "payment-form__radio" }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M0 4C0 3.46957 0.210714 2.96086 0.585786 2.58579C0.960859 2.21071 1.46957 2 2 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4H0ZM0 6V12C0 12.5304 0.210714 13.0391 0.585786 13.4142C0.960859 13.7893 1.46957 14 2 14H14C14.5304 14 15.0391 13.7893 15.4142 13.4142C15.7893 13.0391 16 12.5304 16 12V6H0ZM3 11C3 10.7348 3.10536 10.4804 3.29289 10.2929C3.48043 10.1054 3.73478 10 4 10H5C5.26522 10 5.51957 10.1054 5.70711 10.2929C5.89464 10.4804 6 10.7348 6 11C6 11.2652 5.89464 11.5196 5.70711 11.7071C5.51957 11.8946 5.26522 12 5 12H4C3.73478 12 3.48043 11.8946 3.29289 11.7071C3.10536 11.5196 3 11.2652 3 11Z", fill: "#0270DE" }) }), _jsx("span", { className: "payment-form__method-name text-info-500", children: formatMessage(messages.card) })] }), paymentMethod === 'card' && (_jsxs("div", { className: "payment-form__card-panel", children: [_jsx(PaymentFields, { numberMountRef: numberMountRef, expiryMountRef: expiryMountRef, cvcMountRef: cvcMountRef, cardError: cardError }), _jsxs(Form.Group, { controlId: "country", className: "mt-3 mb-0 payment__field--country", children: [_jsx(Form.Label, { className: "small m-0 x-small", children: formatMessage(messages.country) }), _jsx(Form.Control, { as: "select", value: billing.country, onChange: (e) => setField('country', e.target.value), children: COUNTRIES.map((country) => {
51
+ }) })] }), _jsxs("div", { className: "payment-form__methods mb-4", children: [_jsxs("div", { className: `payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`, children: [_jsxs("label", { htmlFor: "paymentMethod-card", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-card", type: "radio", name: "paymentMethod", value: "card", checked: paymentMethod === 'card', onChange: () => setPaymentMethod('card'), className: "payment-form__radio" }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M0 4C0 3.46957 0.210714 2.96086 0.585786 2.58579C0.960859 2.21071 1.46957 2 2 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4H0ZM0 6V12C0 12.5304 0.210714 13.0391 0.585786 13.4142C0.960859 13.7893 1.46957 14 2 14H14C14.5304 14 15.0391 13.7893 15.4142 13.4142C15.7893 13.0391 16 12.5304 16 12V6H0ZM3 11C3 10.7348 3.10536 10.4804 3.29289 10.2929C3.48043 10.1054 3.73478 10 4 10H5C5.26522 10 5.51957 10.1054 5.70711 10.2929C5.89464 10.4804 6 10.7348 6 11C6 11.2652 5.89464 11.5196 5.70711 11.7071C5.51957 11.8946 5.26522 12 5 12H4C3.73478 12 3.48043 11.8946 3.29289 11.7071C3.10536 11.5196 3 11.2652 3 11Z", fill: "#0270DE" }) }), _jsx("span", { className: "payment-form__method-name text-info-500", children: formatMessage(messages.card) })] }), _jsxs("div", { className: `payment-form__card-panel${paymentMethod === 'card' ? '' : ' payment-form__card-panel--collapsed'}`, "aria-hidden": paymentMethod !== 'card', children: [_jsx(PaymentFields, { numberMountRef: numberMountRef, expiryMountRef: expiryMountRef, cvcMountRef: cvcMountRef, cardError: cardError }), _jsxs(Form.Group, { controlId: "country", className: "mt-3 mb-0 payment__field--country", children: [_jsx(Form.Label, { className: "small m-0 x-small", children: formatMessage(messages.country) }), _jsx(Form.Control, { as: "select", value: billing.country, onChange: (e) => setField('country', e.target.value), children: BILLING_COUNTRIES.map((country) => {
52
52
  return (_jsx("option", { value: country[0], children: country[1] }, country[0]));
53
- }) })] })] }))] }), _jsx("div", { className: `my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`, children: _jsxs("label", { htmlFor: "paymentMethod-googlepay", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-googlepay", type: "radio", name: "paymentMethod", value: "googlepay", checked: paymentMethod === 'googlepay', onChange: () => setPaymentMethod('googlepay'), className: "payment-form__radio" }), _jsx("span", { className: "payment-form__method-icon payment-form__method-icon--gpay", "aria-hidden": "true", children: "G" }), _jsx("span", { className: "payment-form__method-name", children: formatMessage(messages.googlePay) })] }) }), _jsx("div", { className: `payment-form__method payment-form__method--hidden${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`, children: _jsxs("label", { htmlFor: "paymentMethod-paypal", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-paypal", type: "radio", name: "paymentMethod", value: "paypal", checked: paymentMethod === 'paypal', onChange: () => setPaymentMethod('paypal'), className: "payment-form__radio" }), _jsx("span", { className: "payment-form__method-icon payment-form__method-icon--paypal", "aria-hidden": "true", children: "P" }), _jsx("span", { className: "payment-form__method-name", children: formatMessage(messages.paypal) })] }) })] }), _jsx("p", { className: "payment-form__terms text-gray-700 mb-3", children: formatMessage(messages.termsNotice, {
53
+ }) })] })] })] }), _jsx("div", { className: `my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`, children: _jsxs("label", { htmlFor: "paymentMethod-googlepay", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-googlepay", type: "radio", name: "paymentMethod", value: "googlepay", checked: paymentMethod === 'googlepay', onChange: () => setPaymentMethod('googlepay'), className: "payment-form__radio" }), _jsx("span", { className: "payment-form__method-icon payment-form__method-icon--gpay", "aria-hidden": "true", children: "G" }), _jsx("span", { className: "payment-form__method-name", children: formatMessage(messages.googlePay) })] }) }), _jsx("div", { className: `my-3 payment-form__method${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`, children: _jsxs("label", { htmlFor: "paymentMethod-paypal", className: "payment-form__method-header", children: [_jsx("input", { id: "paymentMethod-paypal", type: "radio", name: "paymentMethod", value: "paypal", checked: paymentMethod === 'paypal', onChange: () => setPaymentMethod('paypal'), className: "payment-form__radio" }), _jsx("span", { className: "payment-form__method-icon payment-form__method-icon--paypal", "aria-hidden": "true", children: "P" }), _jsx("span", { className: "payment-form__method-name", children: formatMessage(messages.paypal) })] }) })] }), _jsx("p", { className: "payment-form__terms text-gray-700 mb-3", children: formatMessage(messages.termsNotice, {
54
54
  renewalDate: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
55
55
  price: amount,
56
56
  frequency,
@@ -63,6 +63,7 @@ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMou
63
63
  }) }) }) }), showExtraConfirm && (_jsx(Form.Group, { controlId: "ukCaConfirm", className: "mb-4", children: _jsx(Form.Checkbox, { id: "ukCaConfirm", checked: ukCaConfirmed, onChange: (e) => setUkCaConfirmed(e.target.checked), children: _jsx("span", { className: "text-gray-700", children: formatMessage(messages.ukCaResidentConfirm) }) }) })), _jsxs(Button, { variant: "brand", className: "payment-form__submit", onClick: () => onPlaceOrder(buildConsent()), disabled: !stripeReady
64
64
  || submitting
65
65
  || !confirmed
66
+ || paymentMethod === 'paypal'
66
67
  || (showExtraConfirm && !ukCaConfirmed), children: [busy && (_jsx(Spinner, { animation: "border", size: "sm", className: "mr-2", screenReaderText: formatMessage(messages.spinnerScreenReaderText) })), buttonLabel] })] }));
67
68
  };
68
69
  export default PaymentForm;