@edx/frontend-app-subscription-checkout 1.5.0 → 1.7.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 (40) hide show
  1. package/dist/app.js +2 -6
  2. package/dist/app.js.map +1 -1
  3. package/dist/checkoutPage/CheckoutPage.js +1 -2
  4. package/dist/checkoutPage/CheckoutPage.js.map +1 -1
  5. package/dist/components/BrandMarks/BrandMarks.d.ts +5 -1
  6. package/dist/components/BrandMarks/BrandMarks.js +2 -1
  7. package/dist/components/BrandMarks/BrandMarks.js.map +1 -1
  8. package/dist/components/CartSummary/CartSummary.d.ts +2 -7
  9. package/dist/components/CartSummary/CartSummary.js +12 -8
  10. package/dist/components/CartSummary/CartSummary.js.map +1 -1
  11. package/dist/components/CartSummary/Messages.d.ts +15 -0
  12. package/dist/components/CartSummary/Messages.js +15 -0
  13. package/dist/components/CartSummary/Messages.js.map +1 -1
  14. package/dist/components/Checkout/Checkout.d.ts +1 -6
  15. package/dist/components/Checkout/Checkout.js +4 -13
  16. package/dist/components/Checkout/Checkout.js.map +1 -1
  17. package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +7 -1
  18. package/dist/components/EnrollmentSummary/EnrollmentSummary.js +10 -6
  19. package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -1
  20. package/dist/components/EnrollmentSummary/Messages.d.ts +10 -0
  21. package/dist/components/EnrollmentSummary/Messages.js +10 -0
  22. package/dist/components/EnrollmentSummary/Messages.js.map +1 -1
  23. package/dist/components/PaymentForm/Messages.d.ts +16 -1
  24. package/dist/components/PaymentForm/Messages.js +20 -5
  25. package/dist/components/PaymentForm/Messages.js.map +1 -1
  26. package/dist/components/PaymentForm/PaymentForm.d.ts +7 -1
  27. package/dist/components/PaymentForm/PaymentForm.js +33 -22
  28. package/dist/components/PaymentForm/PaymentForm.js.map +1 -1
  29. package/dist/data/hooks/useCheckout.js +7 -2
  30. package/dist/data/hooks/useCheckout.js.map +1 -1
  31. package/dist/styles/components/brandMarks.scss +9 -22
  32. package/dist/styles/components/cartSummary.scss +7 -0
  33. package/dist/styles/components/enrollmentSummary.scss +6 -0
  34. package/dist/styles/components/paymentForm.scss +20 -0
  35. package/dist/utils/planQuery.d.ts +16 -0
  36. package/dist/utils/planQuery.js +57 -0
  37. package/dist/utils/planQuery.js.map +1 -0
  38. package/dist/utils/provision.js +2 -2
  39. package/dist/utils/provision.js.map +1 -1
  40. package/package.json +1 -1
@@ -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;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"]}
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 })}\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 {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"]}
@@ -14,6 +14,16 @@ declare const messages: {
14
14
  defaultMessage: string;
15
15
  description: string;
16
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
+ };
17
27
  priceDisplay: {
18
28
  id: string;
19
29
  defaultMessage: string;
@@ -15,6 +15,16 @@ const messages = defineMessages({
15
15
  defaultMessage: 'Annual subscription',
16
16
  description: 'Label for annual billing cycle in purchase summary',
17
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',
26
+ description: 'Regular monthly price after the promo period e.g. then $59/mo',
27
+ },
18
28
  priceDisplay: {
19
29
  id: 'checkout.enrollmentSummary.priceDisplay',
20
30
  defaultMessage: '${amount}/{frequency} {currency}',
@@ -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,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"]}
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,mBAAmB;QACnC,WAAW,EAAE,+DAA+D;KAC7E;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 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',\n description: 'Regular monthly price after the promo period e.g. then $59/mo',\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"]}
@@ -39,6 +39,16 @@ declare const messages: {
39
39
  defaultMessage: string;
40
40
  description: string;
41
41
  };
42
+ termsPricingMonthly: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ termsPricingAnnual: {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
42
52
  termsOfUse: {
43
53
  id: string;
44
54
  defaultMessage: string;
@@ -49,7 +59,12 @@ declare const messages: {
49
59
  defaultMessage: string;
50
60
  description: string;
51
61
  };
52
- recurringConfirm: {
62
+ recurringConfirmMonthly: {
63
+ id: string;
64
+ defaultMessage: string;
65
+ description: string;
66
+ };
67
+ recurringConfirmAnnual: {
53
68
  id: string;
54
69
  defaultMessage: string;
55
70
  description: string;
@@ -40,9 +40,19 @@ const messages = defineMessages({
40
40
  // Terms
41
41
  termsNotice: {
42
42
  id: 'checkout.paymentForm.termsNotice',
43
- defaultMessage: 'Your subscription will start today with a 7-day free trial. Your subscription automatically renews on {renewalDate} for {price}/{frequency} USD (inclusive of applicable taxes). Cancel your subscription anytime from your dashboard. By clicking "Confirm subscription" you agree to our {termsLink}, and {refundLink}.',
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
44
  description: 'Subscription terms notice shown before the confirm button',
45
45
  },
46
+ termsPricingMonthly: {
47
+ id: 'checkout.paymentForm.termsPricingMonthly',
48
+ defaultMessage: '${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo',
49
+ description: 'Monthly promotional pricing in the terms notice e.g. $39/mo for 3 months then $59/mo',
50
+ },
51
+ termsPricingAnnual: {
52
+ id: 'checkout.paymentForm.termsPricingAnnual',
53
+ defaultMessage: '${amount}/{frequency}',
54
+ description: 'Annual plan pricing in the terms notice e.g. $299/year — no promotional pricing',
55
+ },
46
56
  termsOfUse: {
47
57
  id: 'checkout.paymentForm.termsOfUse',
48
58
  defaultMessage: 'Terms of Use',
@@ -54,10 +64,15 @@ const messages = defineMessages({
54
64
  description: 'Refund Policy link text',
55
65
  },
56
66
  // Checkboxes
57
- recurringConfirm: {
58
- id: 'checkout.paymentForm.recurringConfirm',
59
- defaultMessage: 'I agree to enroll in a recurring {cycle} subscription for {price}/{frequency} USD.',
60
- description: 'First checkbox confirming recurring charge',
67
+ recurringConfirmMonthly: {
68
+ id: 'checkout.paymentForm.recurringConfirmMonthly',
69
+ defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo USD.',
70
+ description: 'Monthly checkbox confirming recurring charge with promo then regular price',
71
+ },
72
+ recurringConfirmAnnual: {
73
+ id: 'checkout.paymentForm.recurringConfirmAnnual',
74
+ defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${amount}/yr USD.',
75
+ description: 'Annual checkbox confirming recurring charge',
61
76
  },
62
77
  ukCaResidentConfirm: {
63
78
  id: 'checkout.paymentForm.ukCaResidentConfirm',
@@ -1 +1 @@
1
- {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/Messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,mBAAmB;IACnB,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,uBAAuB;QACvC,WAAW,EAAE,kDAAkD;KAChE;IACD,cAAc,EAAE;QACd,EAAE,EAAE,qCAAqC;QACzC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,mBAAmB;KACjC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,0DAA0D;QAC1E,WAAW,EAAE,yCAAyC;KACvD;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,qBAAqB;QACrC,WAAW,EAAE,+BAA+B;KAC7C;IAED,yBAAyB;IACzB,IAAI,EAAE;QACJ,EAAE,EAAE,2BAA2B;QAC/B,cAAc,EAAE,MAAM;QACtB,WAAW,EAAE,wCAAwC;KACtD;IACD,SAAS,EAAE;QACT,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,YAAY;QAC5B,WAAW,EAAE,iCAAiC;KAC/C;IACD,MAAM,EAAE;QACN,EAAE,EAAE,6BAA6B;QACjC,cAAc,EAAE,QAAQ;QACxB,WAAW,EAAE,6BAA6B;KAC3C;IAED,QAAQ;IACR,WAAW,EAAE;QACX,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,2TAA2T;QAC3U,WAAW,EAAE,2DAA2D;KACzE;IACD,UAAU,EAAE;QACV,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,wBAAwB;KACtC;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,mCAAmC;QACvC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,yBAAyB;KACvC;IAED,aAAa;IACb,gBAAgB,EAAE;QAChB,EAAE,EAAE,uCAAuC;QAC3C,cAAc,EAAE,oFAAoF;QACpG,WAAW,EAAE,4CAA4C;KAC1D;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,8CAA8C;QAC9D,WAAW,EAAE,yCAAyC;KACvD;IAED,gBAAgB;IAChB,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,sBAAsB;QACtC,WAAW,EAAE,qBAAqB;KACnC;IACD,UAAU,EAAE;QACV,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,sCAAsC;KACpD;IACD,cAAc,EAAE;QACd,EAAE,EAAE,qCAAqC;QACzC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,wCAAwC;KACtD;IACD,OAAO,EAAE;QACP,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,wBAAwB;KACtC;IACD,uBAAuB,EAAE;QACvB,EAAE,EAAE,8CAA8C;QAClD,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,4CAA4C;KAC1D;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","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 subscription will start today with a 7-day free trial. Your subscription automatically renews on {renewalDate} for {price}/{frequency} USD (inclusive of applicable taxes). Cancel your subscription anytime from your dashboard. By clicking \"Confirm subscription\" you agree to our {termsLink}, and {refundLink}.',\n description: 'Subscription terms notice shown before the confirm button',\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 recurringConfirm: {\n id: 'checkout.paymentForm.recurringConfirm',\n defaultMessage: 'I agree to enroll in a recurring {cycle} subscription for {price}/{frequency} USD.',\n description: 'First checkbox confirming recurring charge',\n },\n ukCaResidentConfirm: {\n id: 'checkout.paymentForm.ukCaResidentConfirm',\n defaultMessage: 'Second checkbox only for UK and CA residents',\n description: 'Second checkbox for UK and CA residents',\n },\n\n // Submit button\n confirmSubscription: {\n id: 'checkout.paymentForm.confirmSubscription',\n defaultMessage: 'Confirm subscription',\n description: 'Submit button label',\n },\n processing: {\n id: 'checkout.paymentForm.processing',\n defaultMessage: 'Processing…',\n description: 'Submit button label while processing',\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"]}
1
+ {"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/Messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,mBAAmB;IACnB,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,uBAAuB;QACvC,WAAW,EAAE,kDAAkD;KAChE;IACD,cAAc,EAAE;QACd,EAAE,EAAE,qCAAqC;QACzC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,mBAAmB;KACjC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,0DAA0D;QAC1E,WAAW,EAAE,yCAAyC;KACvD;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,qBAAqB;QACrC,WAAW,EAAE,+BAA+B;KAC7C;IAED,yBAAyB;IACzB,IAAI,EAAE;QACJ,EAAE,EAAE,2BAA2B;QAC/B,cAAc,EAAE,MAAM;QACtB,WAAW,EAAE,wCAAwC;KACtD;IACD,SAAS,EAAE;QACT,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,YAAY;QAC5B,WAAW,EAAE,iCAAiC;KAC/C;IACD,MAAM,EAAE;QACN,EAAE,EAAE,6BAA6B;QACjC,cAAc,EAAE,QAAQ;QACxB,WAAW,EAAE,6BAA6B;KAC3C;IAED,QAAQ;IACR,WAAW,EAAE;QACX,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,yTAAyT;QACzU,WAAW,EAAE,2DAA2D;KACzE;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,qEAAqE;QACrF,WAAW,EAAE,sFAAsF;KACpG;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,uBAAuB;QACvC,WAAW,EAAE,iFAAiF;KAC/F;IACD,UAAU,EAAE;QACV,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,wBAAwB;KACtC;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,mCAAmC;QACvC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,yBAAyB;KACvC;IAED,aAAa;IACb,uBAAuB,EAAE;QACvB,EAAE,EAAE,8CAA8C;QAClD,cAAc,EAAE,oIAAoI;QACpJ,WAAW,EAAE,4EAA4E;KAC1F;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,6CAA6C;QACjD,cAAc,EAAE,6EAA6E;QAC7F,WAAW,EAAE,6CAA6C;KAC3D;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,8CAA8C;QAC9D,WAAW,EAAE,yCAAyC;KACvD;IAED,gBAAgB;IAChB,mBAAmB,EAAE;QACnB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,sBAAsB;QACtC,WAAW,EAAE,qBAAqB;KACnC;IACD,UAAU,EAAE;QACV,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,sCAAsC;KACpD;IACD,cAAc,EAAE;QACd,EAAE,EAAE,qCAAqC;QACzC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,wCAAwC;KACtD;IACD,OAAO,EAAE;QACP,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,wBAAwB;KACtC;IACD,uBAAuB,EAAE;QACvB,EAAE,EAAE,8CAA8C;QAClD,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,4CAA4C;KAC1D;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","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: 'Subscription terms notice 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 ukCaResidentConfirm: {\n id: 'checkout.paymentForm.ukCaResidentConfirm',\n defaultMessage: 'Second checkbox only for UK and CA residents',\n description: 'Second checkbox for UK and CA residents',\n },\n\n // Submit button\n confirmSubscription: {\n id: 'checkout.paymentForm.confirmSubscription',\n defaultMessage: 'Confirm subscription',\n description: 'Submit button label',\n },\n processing: {\n id: 'checkout.paymentForm.processing',\n defaultMessage: 'Processing…',\n description: 'Submit button label while processing',\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"]}
@@ -16,6 +16,12 @@ export interface PaymentFormProps {
16
16
  cycleToShow: string;
17
17
  trialEnd?: string;
18
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;
19
25
  }
20
- declare const PaymentForm: ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, userCountry, }: PaymentFormProps) => import("react/jsx-runtime").JSX.Element;
26
+ declare const PaymentForm: ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, userCountry, promoAmount, promoMonths, monthlyRegularAmount, }: PaymentFormProps) => import("react/jsx-runtime").JSX.Element;
21
27
  export default PaymentForm;
@@ -5,8 +5,8 @@ import { useIntl } from '@openedx/frontend-base';
5
5
  import PaymentFields from '../PaymentFields/PaymentFields';
6
6
  import { COUNTRIES_REQUIRING_EXTRA_CONFIRM, BILLING_COUNTRIES } from '../../constants';
7
7
  import messages from './Messages';
8
- const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, userCountry, }) => {
9
- var _a;
8
+ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, stripeReady, sessionReady, submitting, onPlaceOrder, priceToShow, cycleToShow, trialEnd, userCountry, promoAmount = '39', promoMonths = 3, monthlyRegularAmount = '59', }) => {
9
+ var _a, _b;
10
10
  const { formatMessage } = useIntl();
11
11
  const [paymentMethod, setPaymentMethod] = useState('card');
12
12
  const [confirmed, setConfirmed] = useState(false);
@@ -20,22 +20,37 @@ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMou
20
20
  buttonLabel = formatMessage(messages.loadingPayment);
21
21
  else if (!stripeReady)
22
22
  buttonLabel = formatMessage(messages.loadingPayment);
23
- const amount = (_a = priceToShow === null || priceToShow === void 0 ? void 0 : priceToShow.amount) !== null && _a !== void 0 ? _a : '';
23
+ const isMonthly = cycleToShow === 'monthly';
24
24
  const frequency = cycleToShow === 'annual' ? 'year' : 'month';
25
+ const trialDays = 7;
26
+ const pricing = isMonthly
27
+ ? formatMessage(messages.termsPricingMonthly, {
28
+ promoAmount,
29
+ promoMonths,
30
+ regularAmount: monthlyRegularAmount,
31
+ })
32
+ : formatMessage(messages.termsPricingAnnual, {
33
+ amount: (_a = priceToShow === null || priceToShow === void 0 ? void 0 : priceToShow.amount) !== null && _a !== void 0 ? _a : '',
34
+ frequency,
35
+ });
36
+ const recurringConfirmText = isMonthly
37
+ ? formatMessage(messages.recurringConfirmMonthly, {
38
+ promoAmount,
39
+ promoMonths,
40
+ regularAmount: monthlyRegularAmount,
41
+ })
42
+ : formatMessage(messages.recurringConfirmAnnual, {
43
+ amount: (_b = priceToShow === null || priceToShow === void 0 ? void 0 : priceToShow.amount) !== null && _b !== void 0 ? _b : '',
44
+ });
25
45
  const buildConsent = () => {
26
46
  const termsText = formatMessage(messages.termsNotice, {
27
- renewalDate: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
28
- price: amount,
29
- frequency,
47
+ trialDays,
48
+ date: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
49
+ pricing,
30
50
  termsLink: formatMessage(messages.termsOfUse),
31
51
  refundLink: formatMessage(messages.refundPolicy),
32
52
  });
33
- const recurringText = formatMessage(messages.recurringConfirm, {
34
- cycle: cycleToShow,
35
- price: amount,
36
- frequency,
37
- });
38
- const consentParts = [termsText, recurringText];
53
+ const consentParts = [termsText, recurringConfirmText];
39
54
  if (showExtraConfirm) {
40
55
  consentParts.push(formatMessage(messages.ukCaResidentConfirm));
41
56
  }
@@ -51,16 +66,12 @@ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMou
51
66
  }) })] }), _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
67
  return (_jsx("option", { value: country[0], children: country[1] }, country[0]));
53
68
  }) })] })] })] }), _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
- renewalDate: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
55
- price: amount,
56
- frequency,
57
- termsLink: (_jsx("a", { className: "text-gray-700", href: "/terms", target: "_blank", rel: "noreferrer", children: formatMessage(messages.termsOfUse) })),
58
- refundLink: (_jsx("a", { className: "text-gray-700", href: "/refund-policy", target: "_blank", rel: "noreferrer", children: formatMessage(messages.refundPolicy) })),
59
- }) }), _jsx(Form.Group, { controlId: "recurringConfirm", className: "mb-2", children: _jsx(Form.Checkbox, { id: "recurringConfirm", checked: confirmed, onChange: (e) => setConfirmed(e.target.checked), children: _jsx("span", { className: "text-gray-700", children: formatMessage(messages.recurringConfirm, {
60
- cycle: cycleToShow,
61
- price: amount,
62
- frequency,
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
69
+ trialDays,
70
+ date: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
71
+ pricing,
72
+ termsLink: (_jsx("a", { className: "text-gray-700", href: "/edx-terms-service", children: formatMessage(messages.termsOfUse) })),
73
+ refundLink: (_jsx("a", { className: "text-gray-700", href: "/edx-terms-service#refund-policy", children: formatMessage(messages.refundPolicy) })),
74
+ }) }), _jsx(Form.Group, { controlId: "recurringConfirm", className: "mb-3 payment-form__confirm", children: _jsx(Form.Checkbox, { id: "recurringConfirm", checked: confirmed, onChange: (e) => setConfirmed(e.target.checked), children: _jsx("span", { className: "text-gray-700 payment-form__confirm-label", children: recurringConfirmText }) }) }), showExtraConfirm && (_jsx(Form.Group, { controlId: "ukCaConfirm", className: "mb-4 payment-form__confirm", children: _jsx(Form.Checkbox, { id: "ukCaConfirm", checked: ukCaConfirmed, onChange: (e) => setUkCaConfirmed(e.target.checked), children: _jsx("span", { className: "text-gray-700 payment-form__confirm-label", children: formatMessage(messages.ukCaResidentConfirm) }) }) })), _jsxs(Button, { variant: "brand", className: "payment-form__submit", onClick: () => onPlaceOrder(buildConsent()), disabled: !stripeReady
64
75
  || submitting
65
76
  || !confirmed
66
77
  || paymentMethod === 'paypal'
@@ -1 +1 @@
1
- {"version":3,"file":"PaymentForm.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/PaymentForm.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAG3D,OAAO,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,QAAQ,MAAM,YAAY,CAAC;AAqBlC,MAAM,WAAW,GAAG,CAAC,EACnB,OAAO,EACP,QAAQ,EACR,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,GACM,EAAE,EAAE;;IACrB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,MAAM,CAAC,CAAC;IAC1E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1D,MAAM,gBAAgB,GAClB,CAAC,CAAC,WAAW,IAAI,iCAAiC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE7E,MAAM,IAAI,GAAG,UAAU,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,CAAC;IAEzD,IAAI,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAC9D,IAAI,UAAU;QAAE,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SAC5D,IAAI,CAAC,YAAY;QAAE,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;SACxE,IAAI,CAAC,WAAW;QAAE,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAE5E,MAAM,MAAM,GAAG,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,mCAAI,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAE9D,MAAM,YAAY,GAAG,GAAoB,EAAE;QACzC,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,WAAW,EAAE;YACpD,WAAW,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,QAAQ;YACjC,KAAK,EAAE,MAAM;YACb,SAAS;YACT,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC7C,UAAU,EAAE,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC;SACjD,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,gBAAgB,EAAE;YAC7D,KAAK,EAAE,WAAW;YAClB,KAAK,EAAE,MAAM;YACb,SAAS;SACV,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAChD,IAAI,gBAAgB,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,OAAO;YACL,iBAAiB,EAAE,SAAS;YAC5B,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;YACrD,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;SACxC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,aAAI,SAAS,EAAC,8DAA8D,YACzE,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GACzC,EAEL,aAAG,SAAS,EAAC,+BAA+B,aAC1C,iBAAQ,SAAS,EAAC,0BAA0B,YACzC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,GAChC,EAAC,GAAG,EACb,eAAM,SAAS,EAAC,eAAe,YAC5B,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE;4BAC1C,IAAI,EAAE,CACJ,YACE,IAAI,EAAC,yBAAyB,EAC9B,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,eAAe,YAExB,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CAAC,GACxC,CACL;yBACF,CAAC,GACG,IACL,EAGJ,eAAK,SAAS,EAAC,4BAA4B,aAEzC,eACE,SAAS,EAAE,uBAAuB,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,aAGrG,iBACE,OAAO,EAAC,oBAAoB,EAC5B,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,oBAAoB,EACvB,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,aAAa,KAAK,MAAM,EACjC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,EACxC,SAAS,EAAC,qBAAqB,GAC/B,EACF,cACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,YAEX,eACE,QAAQ,EAAC,SAAS,EAClB,QAAQ,EAAC,SAAS,EAClB,CAAC,EAAC,2nBAA2nB,EAC7nB,IAAI,EAAC,SAAS,GACd,GACE,EACN,eAAM,SAAS,EAAC,yCAAyC,YACtD,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,GACxB,IACD,EAGR,eACE,SAAS,EAAE,2BAA2B,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sCAAsC,EAAE,iBACjG,aAAa,KAAK,MAAM,aAErC,KAAC,aAAa,IACZ,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,GACpB,EACF,MAAC,IAAI,CAAC,KAAK,IACT,SAAS,EAAC,SAAS,EACnB,SAAS,EAAC,mCAAmC,aAE7C,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,mBAAmB,YACtC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,GACrB,EACb,KAAC,IAAI,CAAC,OAAO,IACX,EAAE,EAAC,QAAQ,EACX,KAAK,EAAE,OAAO,CAAC,OAAO,EACtB,QAAQ,EAAE,CAAC,CAAuC,EAAE,EAAE,CACpD,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,YAEpC,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;oDACjC,OAAO,CACL,iBAAyB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,YACvC,OAAO,CAAC,CAAC,CAAC,IADA,OAAO,CAAC,CAAC,CAAC,CAEd,CACV,CAAC;gDACJ,CAAC,CAAC,GACW,IACJ,IACT,IACF,EAGN,cACE,SAAS,EAAE,yDAAyD,aAAa,KAAK,WAAW,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,YAE5I,iBACE,OAAO,EAAC,yBAAyB,EACjC,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,yBAAyB,EAC5B,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAE,aAAa,KAAK,WAAW,EACtC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,EAC7C,SAAS,EAAC,qBAAqB,GAC/B,EACF,eACE,SAAS,EAAC,2DAA2D,iBACzD,MAAM,kBAGb,EACP,eAAM,SAAS,EAAC,2BAA2B,YACxC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,GAC7B,IACD,GACJ,EAGN,cACE,SAAS,EAAE,4BAA4B,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,YAE5G,iBACE,OAAO,EAAC,sBAAsB,EAC9B,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,sBAAsB,EACzB,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,QAAQ,EACd,OAAO,EAAE,aAAa,KAAK,QAAQ,EACnC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAC1C,SAAS,EAAC,qBAAqB,GAC/B,EACF,eACE,SAAS,EAAC,6DAA6D,iBAC3D,MAAM,kBAGb,EACP,eAAM,SAAS,EAAC,2BAA2B,YACxC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAC1B,IACD,GACJ,IACF,EAGN,YAAG,SAAS,EAAC,wCAAwC,YAClD,aAAa,CAAC,QAAQ,CAAC,WAAW,EAAE;oBACnC,WAAW,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,QAAQ;oBACjC,KAAK,EAAE,MAAM;oBACb,SAAS;oBACT,SAAS,EAAE,CACT,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAC,QAAQ,EACb,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,YAEf,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,GACjC,CACL;oBACD,UAAU,EAAE,CACV,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAC,gBAAgB,EACrB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,YAEf,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,GACnC,CACL;iBACF,CAAC,GACA,EAGJ,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,EAAC,SAAS,EAAC,MAAM,YACvD,KAAC,IAAI,CAAC,QAAQ,IACZ,EAAE,EAAC,kBAAkB,EACrB,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,CAAC,CAAsC,EAAE,EAAE,CACnD,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAEhC,eAAM,SAAS,EAAC,eAAe,YAC5B,aAAa,CAAC,QAAQ,CAAC,gBAAgB,EAAE;4BACxC,KAAK,EAAE,WAAW;4BAClB,KAAK,EAAE,MAAM;4BACb,SAAS;yBACV,CAAC,GACG,GACO,GACL,EAEZ,gBAAgB,IAAI,CACnB,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,aAAa,EAAC,SAAS,EAAC,MAAM,YAClD,KAAC,IAAI,CAAC,QAAQ,IACZ,EAAE,EAAC,aAAa,EAChB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,CAAC,CAAsC,EAAE,EAAE,CACnD,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAEpC,eAAM,SAAS,EAAC,eAAe,YAC5B,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GACvC,GACO,GACL,CACd,EAGD,MAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,sBAAsB,EAChC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAC3C,QAAQ,EACN,CAAC,WAAW;uBACT,UAAU;uBACV,CAAC,SAAS;uBACV,aAAa,KAAK,QAAQ;uBAC1B,CAAC,gBAAgB,IAAI,CAAC,aAAa,CAAC,aAGxC,IAAI,IAAI,CACP,KAAC,OAAO,IACN,SAAS,EAAC,QAAQ,EAClB,IAAI,EAAC,IAAI,EACT,SAAS,EAAC,MAAM,EAChB,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GACjE,CACH,EACA,WAAW,IACL,IACL,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC","sourcesContent":["import React, { useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport { COUNTRIES_REQUIRING_EXTRA_CONFIRM, BILLING_COUNTRIES } from '../../constants';\nimport messages from './Messages';\n\ntype PaymentMethod = 'card' | 'googlepay' | 'paypal';\n\nexport interface PaymentFormProps {\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n stripeReady: boolean,\n sessionReady: boolean,\n submitting: boolean,\n onPlaceOrder: (consent: CheckoutConsent) => void,\n priceToShow: PlanPrice | null,\n cycleToShow: string,\n trialEnd?: string,\n userCountry?: string | null,\n}\n\nconst PaymentForm = ({\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n stripeReady,\n sessionReady,\n submitting,\n onPlaceOrder,\n priceToShow,\n cycleToShow,\n trialEnd,\n userCountry,\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [ukCaConfirmed, setUkCaConfirmed] = useState(false);\n\n const showExtraConfirm\n = !!userCountry && COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(userCountry);\n\n const busy = submitting || !stripeReady || !sessionReady;\n\n let buttonLabel = formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady) buttonLabel = formatMessage(messages.loadingPayment);\n else if (!stripeReady) buttonLabel = formatMessage(messages.loadingPayment);\n\n const amount = priceToShow?.amount ?? '';\n const frequency = cycleToShow === 'annual' ? 'year' : 'month';\n\n const buildConsent = (): CheckoutConsent => {\n const termsText = formatMessage(messages.termsNotice, {\n renewalDate: trialEnd ?? '{date}',\n price: amount,\n frequency,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n });\n const recurringText = formatMessage(messages.recurringConfirm, {\n cycle: cycleToShow,\n price: amount,\n frequency,\n });\n const consentParts = [termsText, recurringText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(messages.ukCaResidentConfirm));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? ukCaConfirmed : null,\n tConsentAt: new Date().toISOString(),\n tConsentText: consentParts.join('\\n\\n'),\n };\n };\n\n return (\n <div className=\"payment-form bg-white\">\n <h2 className=\"payment-form__heading font-weight-bold mb-3 text-primary-500\">\n {formatMessage(messages.selectPaymentMethod)}\n </h2>\n\n <p className=\"payment-form__help small mb-4\">\n <strong className=\"d-block text-primary-500\">\n {formatMessage(messages.needAssistance)}\n </strong>{' '}\n <span className=\"text-gray-700\">\n {formatMessage(messages.needAssistanceBody, {\n link: (\n <a\n href=\"https://support.edx.org\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-gray-700\"\n >\n {formatMessage(messages.learnerHelpCenter)}\n </a>\n ),\n })}\n </span>\n </p>\n\n {/* ── Payment method accordion ── */}\n <div className=\"payment-form__methods mb-4\">\n {/* ── Card ── */}\n <div\n className={`payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`}\n >\n {/* Header row — always visible */}\n <label\n htmlFor=\"paymentMethod-card\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-card\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"card\"\n checked={paymentMethod === 'card'}\n onChange={() => setPaymentMethod('card')}\n className=\"payment-form__radio\"\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n 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\"\n fill=\"#0270DE\"\n />\n </svg>\n <span className=\"payment-form__method-name text-info-500\">\n {formatMessage(messages.card)}\n </span>\n </label>\n\n {/* Keep Stripe host nodes mounted so Elements stay interactive after toggling methods. */}\n <div\n className={`payment-form__card-panel${paymentMethod === 'card' ? '' : ' payment-form__card-panel--collapsed'}`}\n aria-hidden={paymentMethod !== 'card'}\n >\n <PaymentFields\n numberMountRef={numberMountRef}\n expiryMountRef={expiryMountRef}\n cvcMountRef={cvcMountRef}\n cardError={cardError}\n />\n <Form.Group\n controlId=\"country\"\n className=\"mt-3 mb-0 payment__field--country\"\n >\n <Form.Label className=\"small m-0 x-small\">\n {formatMessage(messages.country)}\n </Form.Label>\n <Form.Control\n as=\"select\"\n value={billing.country}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>\n setField('country', e.target.value)}\n >\n {BILLING_COUNTRIES.map((country) => {\n return (\n <option key={country[0]} value={country[0]}>\n {country[1]}\n </option>\n );\n })}\n </Form.Control>\n </Form.Group>\n </div>\n </div>\n\n {/* ── Google Pay (hidden for now) ── */}\n <div\n className={`my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-googlepay\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-googlepay\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"googlepay\"\n checked={paymentMethod === 'googlepay'}\n onChange={() => setPaymentMethod('googlepay')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--gpay\"\n aria-hidden=\"true\"\n >\n G\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.googlePay)}\n </span>\n </label>\n </div>\n\n {/* ── PayPal (UI only; backend wiring pending) ── */}\n <div\n className={`my-3 payment-form__method${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-paypal\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-paypal\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"paypal\"\n checked={paymentMethod === 'paypal'}\n onChange={() => setPaymentMethod('paypal')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--paypal\"\n aria-hidden=\"true\"\n >\n P\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.paypal)}\n </span>\n </label>\n </div>\n </div>\n\n {/* ── Terms ── */}\n <p className=\"payment-form__terms text-gray-700 mb-3\">\n {formatMessage(messages.termsNotice, {\n renewalDate: trialEnd ?? '{date}',\n price: amount,\n frequency,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href=\"/terms\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href=\"/refund-policy\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })}\n </p>\n\n {/* ── Checkboxes ── */}\n <Form.Group controlId=\"recurringConfirm\" className=\"mb-2\">\n <Form.Checkbox\n id=\"recurringConfirm\"\n checked={confirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700\">\n {formatMessage(messages.recurringConfirm, {\n cycle: cycleToShow,\n price: amount,\n frequency,\n })}\n </span>\n </Form.Checkbox>\n </Form.Group>\n\n {showExtraConfirm && (\n <Form.Group controlId=\"ukCaConfirm\" className=\"mb-4\">\n <Form.Checkbox\n id=\"ukCaConfirm\"\n checked={ukCaConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setUkCaConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700\">\n {formatMessage(messages.ukCaResidentConfirm)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => onPlaceOrder(buildConsent())}\n disabled={\n !stripeReady\n || submitting\n || !confirmed\n || paymentMethod === 'paypal'\n || (showExtraConfirm && !ukCaConfirmed)\n }\n >\n {busy && (\n <Spinner\n animation=\"border\"\n size=\"sm\"\n className=\"mr-2\"\n screenReaderText={formatMessage(messages.spinnerScreenReaderText)}\n />\n )}\n {buttonLabel}\n </Button>\n </div>\n );\n};\n\nexport default PaymentForm;\n"]}
1
+ {"version":3,"file":"PaymentForm.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/PaymentForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport { COUNTRIES_REQUIRING_EXTRA_CONFIRM, BILLING_COUNTRIES } from '../../constants';\nimport messages from './Messages';\n\ntype PaymentMethod = 'card' | 'googlepay' | 'paypal';\n\nexport interface PaymentFormProps {\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n stripeReady: boolean,\n sessionReady: boolean,\n submitting: boolean,\n onPlaceOrder: (consent: CheckoutConsent) => void,\n priceToShow: PlanPrice | null,\n cycleToShow: string,\n trialEnd?: string,\n userCountry?: string | null,\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}\n\nconst PaymentForm = ({\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n stripeReady,\n sessionReady,\n submitting,\n onPlaceOrder,\n priceToShow,\n cycleToShow,\n trialEnd,\n userCountry,\n promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount = '59',\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [ukCaConfirmed, setUkCaConfirmed] = useState(false);\n\n const showExtraConfirm\n = !!userCountry && COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(userCountry);\n\n const busy = submitting || !stripeReady || !sessionReady;\n\n let buttonLabel = formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady) buttonLabel = formatMessage(messages.loadingPayment);\n else if (!stripeReady) buttonLabel = formatMessage(messages.loadingPayment);\n\n const isMonthly = cycleToShow === 'monthly';\n const frequency = cycleToShow === 'annual' ? 'year' : 'month';\n const trialDays = 7;\n const pricing = isMonthly\n ? formatMessage(messages.termsPricingMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.termsPricingAnnual, {\n amount: priceToShow?.amount ?? '',\n frequency,\n });\n const recurringConfirmText = isMonthly\n ? formatMessage(messages.recurringConfirmMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.recurringConfirmAnnual, {\n amount: priceToShow?.amount ?? '',\n });\n\n const buildConsent = (): CheckoutConsent => {\n const termsText = formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n });\n const consentParts = [termsText, recurringConfirmText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(messages.ukCaResidentConfirm));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? ukCaConfirmed : null,\n tConsentAt: new Date().toISOString(),\n tConsentText: consentParts.join('\\n\\n'),\n };\n };\n\n return (\n <div className=\"payment-form bg-white\">\n <h2 className=\"payment-form__heading font-weight-bold mb-3 text-primary-500\">\n {formatMessage(messages.selectPaymentMethod)}\n </h2>\n\n <p className=\"payment-form__help small mb-4\">\n <strong className=\"d-block text-primary-500\">\n {formatMessage(messages.needAssistance)}\n </strong>{' '}\n <span className=\"text-gray-700\">\n {formatMessage(messages.needAssistanceBody, {\n link: (\n <a\n href=\"https://support.edx.org\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-gray-700\"\n >\n {formatMessage(messages.learnerHelpCenter)}\n </a>\n ),\n })}\n </span>\n </p>\n\n {/* ── Payment method accordion ── */}\n <div className=\"payment-form__methods mb-4\">\n {/* ── Card ── */}\n <div\n className={`payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`}\n >\n {/* Header row — always visible */}\n <label\n htmlFor=\"paymentMethod-card\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-card\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"card\"\n checked={paymentMethod === 'card'}\n onChange={() => setPaymentMethod('card')}\n className=\"payment-form__radio\"\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n 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\"\n fill=\"#0270DE\"\n />\n </svg>\n <span className=\"payment-form__method-name text-info-500\">\n {formatMessage(messages.card)}\n </span>\n </label>\n\n {/* Keep Stripe host nodes mounted so Elements stay interactive after toggling methods. */}\n <div\n className={`payment-form__card-panel${paymentMethod === 'card' ? '' : ' payment-form__card-panel--collapsed'}`}\n aria-hidden={paymentMethod !== 'card'}\n >\n <PaymentFields\n numberMountRef={numberMountRef}\n expiryMountRef={expiryMountRef}\n cvcMountRef={cvcMountRef}\n cardError={cardError}\n />\n <Form.Group\n controlId=\"country\"\n className=\"mt-3 mb-0 payment__field--country\"\n >\n <Form.Label className=\"small m-0 x-small\">\n {formatMessage(messages.country)}\n </Form.Label>\n <Form.Control\n as=\"select\"\n value={billing.country}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>\n setField('country', e.target.value)}\n >\n {BILLING_COUNTRIES.map((country) => {\n return (\n <option key={country[0]} value={country[0]}>\n {country[1]}\n </option>\n );\n })}\n </Form.Control>\n </Form.Group>\n </div>\n </div>\n\n {/* ── Google Pay (hidden for now) ── */}\n <div\n className={`my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-googlepay\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-googlepay\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"googlepay\"\n checked={paymentMethod === 'googlepay'}\n onChange={() => setPaymentMethod('googlepay')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--gpay\"\n aria-hidden=\"true\"\n >\n G\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.googlePay)}\n </span>\n </label>\n </div>\n\n {/* ── PayPal (UI only; backend wiring pending) ── */}\n <div\n className={`my-3 payment-form__method${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-paypal\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-paypal\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"paypal\"\n checked={paymentMethod === 'paypal'}\n onChange={() => setPaymentMethod('paypal')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--paypal\"\n aria-hidden=\"true\"\n >\n P\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.paypal)}\n </span>\n </label>\n </div>\n </div>\n\n {/* ── Terms ── */}\n <p className=\"payment-form__terms text-gray-700 mb-3\">\n {formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href=\"/edx-terms-service\"\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href=\"/edx-terms-service#refund-policy\"\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })}\n </p>\n\n {/* ── Checkboxes ── */}\n <Form.Group controlId=\"recurringConfirm\" className=\"mb-3 payment-form__confirm\">\n <Form.Checkbox\n id=\"recurringConfirm\"\n checked={confirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {recurringConfirmText}\n </span>\n </Form.Checkbox>\n </Form.Group>\n\n {showExtraConfirm && (\n <Form.Group controlId=\"ukCaConfirm\" className=\"mb-4 payment-form__confirm\">\n <Form.Checkbox\n id=\"ukCaConfirm\"\n checked={ukCaConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setUkCaConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {formatMessage(messages.ukCaResidentConfirm)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => onPlaceOrder(buildConsent())}\n disabled={\n !stripeReady\n || submitting\n || !confirmed\n || paymentMethod === 'paypal'\n || (showExtraConfirm && !ukCaConfirmed)\n }\n >\n {busy && (\n <Spinner\n animation=\"border\"\n size=\"sm\"\n className=\"mr-2\"\n screenReaderText={formatMessage(messages.spinnerScreenReaderText)}\n />\n )}\n {buttonLabel}\n </Button>\n </div>\n );\n};\n\nexport default PaymentForm;\n"]}
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
11
11
  import { createCheckoutClient } from '../../utils/checkout';
12
+ import { getPlanFromUrl, writePlanQueryParam } from '../../utils/planQuery';
12
13
  import { loadStripe } from '../../utils/stripe';
13
14
  import { STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS, } from '../../constants';
14
15
  import { useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery, useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery, } from './useCheckoutQueries';
@@ -65,8 +66,12 @@ export default function useCheckout(options = {}) {
65
66
  const [billing, setBilling] = useState({
66
67
  firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',
67
68
  });
68
- const [selectedCycle, setSelectedCycle] = useState('monthly');
69
+ const [selectedCycle, setSelectedCycle] = useState(getPlanFromUrl);
69
70
  const [processingSubscription, setProcessingSubscription] = useState(false);
71
+ const setCycle = useCallback((cycle) => {
72
+ setSelectedCycle(cycle);
73
+ writePlanQueryParam(cycle);
74
+ }, []);
70
75
  useEffect(() => {
71
76
  if (sessionQuery.error) {
72
77
  setError(sessionQuery.error.message);
@@ -290,7 +295,7 @@ export default function useCheckout(options = {}) {
290
295
  billingPlans: (_j = (_h = billingPlansQuery.data) === null || _h === void 0 ? void 0 : _h.plans) !== null && _j !== void 0 ? _j : [],
291
296
  activeSubscriberCount: (_l = (_k = activeSubscriptionsQuery.data) === null || _k === void 0 ? void 0 : _k.active) !== null && _l !== void 0 ? _l : null,
292
297
  selectedCycle,
293
- setCycle: setSelectedCycle,
298
+ setCycle,
294
299
  sessionReady,
295
300
  userCountry,
296
301
  course: (_m = courseDetailQuery.data) !== null && _m !== void 0 ? _m : null,
@@ -1 +1 @@
1
- {"version":3,"file":"useCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback, useEffect, useMemo, useRef, useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport type { BillingCycle } from '../../types';\nimport { createCheckoutClient } from '../../utils/checkout';\nimport { loadStripe } from '../../utils/stripe';\nimport {\n STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS,\n} from '../../constants';\nimport type {\n Status, Phase, Cart, BillingInfo, CheckoutClient, StripeLike, StripeElementLike,\n StripeElementsLike, BillingPlan, CheckoutConsent,\n} from '../../types';\nimport {\n useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery,\n useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery,\n} from './useCheckoutQueries';\nimport type { EdxSessionResult } from '../../utils/provision';\nimport { useCheckoutMutations } from './useCheckoutMutations';\n\n/**\n * Read ?course_run_key= from the current URL.\n * Avoid URLSearchParams — it treats bare `+` as a space, which would turn\n * HarvardX+CS50+X into \"HarvardX CS50 X\". decodeURIComponent keeps `+` intact.\n */\nfunction getCourseRunKeyFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n const match = /[?&]course_run_key=([^&]*)/.exec(window.location.search);\n if (!match) return null;\n try {\n // Preserve literal `+` (treat as %2B) then decode %XX sequences.\n return decodeURIComponent(match[1].replace(/\\+/g, '%2B')).trim() || null;\n } catch {\n return match[1].trim() || null;\n }\n}\n\nexport interface UseCheckoutOptions {\n apiUrl?: string,\n edxSessionUrl?: string,\n stripePublishableKey?: string,\n onComplete?: (subscriptionBiId: string | null) => void,\n /** Country code resolved by CheckoutGate — used to show/hide the UK/CA extra checkbox. */\n userCountry?: string | null,\n /**\n * Course run key from the URL (e.g. course-v1:HarvardX+CS50+X).\n * When omitted, read from ?course_run_key=.\n */\n courseRunKey?: string | null,\n}\n\nexport interface UseCheckoutResult {\n phase: Phase,\n status: Status | null,\n statusLabel: string,\n stripeReady: boolean,\n /** True once the Stripe card Element iframe is fully initialised and interactive. */\n cardReady: boolean,\n notConfigured: boolean,\n showBanner: boolean,\n dismissBanner: () => void,\n error: string,\n clearError: () => void,\n cardError: string,\n lastComment: string,\n /** Full subscription details including card last 4 — available after SUBSCRIPTION_CREATED. */\n subscriptionDetails: import('../../types').SubscriptionDetails | null,\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n submitting: boolean,\n /** True from Place order click until a terminal status is reached. */\n processingSubscription: boolean,\n placeOrder: (consent: CheckoutConsent) => void,\n /** Billing plans fetched on mount — includes prices for display in CartSummary. */\n billingPlans: BillingPlan[],\n /** Live active subscriber count for display in CartSummary. */\n activeSubscriberCount: number | null,\n /** Currently selected billing cycle. */\n selectedCycle: BillingCycle,\n /** Switch between monthly and annual billing. */\n setCycle: (cycle: BillingCycle) => void,\n /** True once GET /edx-session has returned and the viax token is set. */\n sessionReady: boolean,\n /** ISO 3166-1 alpha-2 country code — passed in from CheckoutGate for the UK/CA checkbox. */\n userCountry: string | null,\n /** Course details when arrived via ?course_run_key=; null for standard checkout. */\n course: import('../../types').CourseDetail | null,\n}\n\nexport default function useCheckout(options: UseCheckoutOptions = {}): UseCheckoutResult {\n const {\n apiUrl = DEFAULTS.apiUrl,\n edxSessionUrl,\n stripePublishableKey,\n onComplete,\n userCountry = null,\n courseRunKey: courseRunKeyProp,\n } = options;\n\n const courseRunKey = useMemo(\n () => courseRunKeyProp ?? getCourseRunKeyFromUrl(),\n [courseRunKeyProp],\n );\n\n const client = useMemo<CheckoutClient | null>(() => {\n if (!apiUrl) return null;\n return createCheckoutClient({ apiUrl });\n }, [apiUrl]);\n\n const notConfigured = !client || !stripePublishableKey || !edxSessionUrl;\n\n // Exchange edX session for viax token on page load.\n const sessionQuery = useViaxSessionQuery(notConfigured ? null : edxSessionUrl!);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n // Fetch billing plans, subscriber count, and optional course once the viax session is ready.\n const billingPlansQuery = useBillingPlansQuery(client, sessionReady);\n const activeSubscriptionsQuery = useActiveSubscriptionsQuery(client, sessionReady);\n const courseDetailQuery = useCourseDetailQuery(client, sessionReady, courseRunKey);\n\n // --- state ---\n const [showBanner, setShowBanner] = useState(true);\n const [cart, setCart] = useState<Cart | null>(null);\n const [stripe, setStripe] = useState<StripeLike | null>(null);\n const [stripeReady, setStripeReady] = useState(false);\n const [cardReady, setCardReady] = useState(false);\n const [error, setError] = useState('');\n const [cardError, setCardError] = useState('');\n const [billing, setBilling] = useState<BillingInfo>({\n firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',\n });\n const [selectedCycle, setSelectedCycle] = useState<BillingCycle>('monthly');\n const [processingSubscription, setProcessingSubscription] = useState(false);\n\n useEffect(() => {\n if (sessionQuery.error) {\n setError(sessionQuery.error.message);\n }\n }, [sessionQuery.error]);\n\n const setField = useCallback(\n (field: keyof BillingInfo, value: string) => setBilling((p: BillingInfo) => ({ ...p, [field]: value })),\n [],\n );\n\n // --- refs ---\n // Stripe instances — written inside useEffect and mutations.\n const stripeInstanceRef = useRef<StripeLike | null>(null);\n const cardNumberElementRef = useRef<StripeElementLike | null>(null);\n const cardExpiryElementRef = useRef<StripeElementLike | null>(null);\n const cardCvcElementRef = useRef<StripeElementLike | null>(null);\n const elementsRef = useRef<StripeElementsLike | null>(null);\n // DOM mount targets — callback refs so we remount when hosts leave and return.\n const numberMountNodeRef = useRef<HTMLDivElement | null>(null);\n const expiryMountNodeRef = useRef<HTMLDivElement | null>(null);\n const cvcMountNodeRef = useRef<HTMLDivElement | null>(null);\n const [cardHostsEpoch, setCardHostsEpoch] = useState(0);\n\n const assignCardHost = useCallback((\n store: { current: HTMLDivElement | null },\n node: HTMLDivElement | null,\n ) => {\n store.current = node;\n if (\n numberMountNodeRef.current\n && expiryMountNodeRef.current\n && cvcMountNodeRef.current\n ) {\n setCardHostsEpoch((n) => n + 1);\n return;\n }\n // Hosts are leaving the DOM — detach so Stripe is not bound to dead nodes.\n cardNumberElementRef.current?.unmount?.();\n cardExpiryElementRef.current?.unmount?.();\n cardCvcElementRef.current?.unmount?.();\n }, []);\n\n const numberMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(numberMountNodeRef, node);\n }, [assignCardHost]);\n const expiryMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(expiryMountNodeRef, node);\n }, [assignCardHost]);\n const cvcMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(cvcMountNodeRef, node);\n }, [assignCardHost]);\n const mountedRef = useRef(true);\n const completedRef = useRef(false);\n const sessionRef = useRef<EdxSessionResult | null>(null);\n\n useEffect(() => {\n sessionRef.current = sessionQuery.data ?? null;\n }, [sessionQuery.data]);\n\n // Mirror state into refs so mutations can read current values without stale closures.\n const cartRef = useRef<Cart | null>(null);\n const billingRef = useRef<BillingInfo>(billing);\n const selectedCycleRef = useRef<BillingCycle>(selectedCycle);\n useEffect(() => {\n cartRef.current = cart;\n }, [cart]);\n useEffect(() => {\n billingRef.current = billing;\n }, [billing]);\n useEffect(() => {\n selectedCycleRef.current = selectedCycle;\n }, [selectedCycle]);\n useEffect(() => {\n stripeInstanceRef.current = stripe;\n }, [stripe]);\n\n // --- server state ---\n const statusQuery = useCartStatusQuery(client, cart?.biId ?? null);\n const status: Status | null = statusQuery.data?.status ?? null;\n const lastComment = statusQuery.data?.lastComment ?? '';\n\n // Phase is 'ready' until a cart exists, then driven by bpStatus.\n const phase: Phase = cart ? phaseFor(status, status === STATUS.IN_CART) : 'ready';\n const subscriptionIdQuery = useSubscriptionIdQuery(\n client, cart?.biId ?? null, status === STATUS.SUBSCRIPTION_CREATED,\n );\n\n // --- mutations ---\n const { placeOrder: placeMutation } = useCheckoutMutations({\n client,\n sessionRef,\n stripeRef: stripeInstanceRef,\n cardNumberElRef: cardNumberElementRef,\n billingRef,\n selectedCycleRef,\n setError: (msg: string) => {\n setProcessingSubscription(false);\n setError(msg);\n },\n setCardError: (msg: string) => {\n setProcessingSubscription(false);\n setCardError(msg);\n },\n onCartCreated: (created: Cart) => {\n // Sync the ref immediately so any same-tick readers see the cart\n // before the setCart → useEffect mirror runs.\n cartRef.current = created;\n if (mountedRef.current) setCart(created);\n },\n });\n\n // --- load Stripe.js on mount ---\n useEffect(() => {\n mountedRef.current = true;\n if (!stripePublishableKey) return undefined;\n\n (async () => {\n try {\n const instance = await loadStripe(stripePublishableKey);\n if (mountedRef.current) {\n setStripe(instance);\n setStripeReady(true);\n }\n } catch (e: unknown) {\n if (mountedRef.current) setError((e as Error).message);\n }\n })();\n\n return () => {\n mountedRef.current = false;\n };\n }, [stripePublishableKey]);\n\n // --- mount Stripe Elements once Stripe is loaded; remount if hosts return ---\n useEffect(() => {\n if (!stripe) return;\n const numberNode = numberMountNodeRef.current;\n const expiryNode = expiryMountNodeRef.current;\n const cvcNode = cvcMountNodeRef.current;\n if (!numberNode || !expiryNode || !cvcNode) return;\n\n if (cardNumberElementRef.current && cardExpiryElementRef.current && cardCvcElementRef.current) {\n try {\n cardNumberElementRef.current.unmount?.();\n cardExpiryElementRef.current.unmount?.();\n cardCvcElementRef.current.unmount?.();\n cardNumberElementRef.current.mount(numberNode);\n cardExpiryElementRef.current.mount(expiryNode);\n cardCvcElementRef.current.mount(cvcNode);\n return;\n } catch {\n // Element is bound to a destroyed host — create a fresh Elements group.\n cardNumberElementRef.current = null;\n cardExpiryElementRef.current = null;\n cardCvcElementRef.current = null;\n elementsRef.current = null;\n }\n }\n\n setCardReady(false);\n\n const elements = stripe.elements();\n elementsRef.current = elements;\n\n const number = elements.create('cardNumber', { ...STRIPE_ELEMENT_OPTS, showIcon: true });\n const expiry = elements.create('cardExpiry', STRIPE_ELEMENT_OPTS);\n const cvc = elements.create('cardCvc', STRIPE_ELEMENT_OPTS);\n\n number.mount(numberNode);\n expiry.mount(expiryNode);\n cvc.mount(cvcNode);\n\n number.on('ready', () => {\n if (mountedRef.current) setCardReady(true);\n });\n number.on('change', (e: { error?: { message?: string } }) => {\n if (mountedRef.current) setCardError(e.error?.message || '');\n });\n\n cardNumberElementRef.current = number;\n cardExpiryElementRef.current = expiry;\n cardCvcElementRef.current = cvc;\n }, [stripe, cardHostsEpoch]);\n\n // --- on success ---\n useEffect(() => {\n if (status !== STATUS.SUBSCRIPTION_CREATED || completedRef.current) return;\n completedRef.current = true;\n if (onComplete) onComplete(subscriptionIdQuery.data?.biId ?? null);\n }, [status, subscriptionIdQuery.data, onComplete]);\n\n // --- actions ---\n const placeOrder = useCallback((consent: CheckoutConsent) => {\n setError('');\n setCardError('');\n if (phase === 'failed') setCart(null);\n setProcessingSubscription(true);\n placeMutation.mutate(consent);\n }, [placeMutation, phase]);\n\n // Turn off processingSubscription once we reach a terminal status.\n useEffect(() => {\n if (!status) return;\n const terminalStatuses: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.STRIPE_FAIL,\n STATUS.SANCTION_BLOCK,\n ];\n if (terminalStatuses.includes(status)) {\n setProcessingSubscription(false);\n }\n }, [status]);\n\n return {\n phase,\n status,\n statusLabel: (status && STATUS_LABELS[status]) || 'Processing your order…',\n stripeReady,\n cardReady,\n notConfigured,\n showBanner,\n dismissBanner: () => setShowBanner(false),\n error,\n clearError: () => setError(''),\n cardError,\n lastComment,\n subscriptionDetails: subscriptionIdQuery.data ?? null,\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n submitting: placeMutation.isPending,\n processingSubscription,\n placeOrder,\n billingPlans: billingPlansQuery.data?.plans ?? [],\n activeSubscriberCount: activeSubscriptionsQuery.data?.active ?? null,\n selectedCycle,\n setCycle: setSelectedCycle,\n sessionReady,\n userCountry,\n course: courseDetailQuery.data ?? null,\n };\n}\n"]}
1
+ {"version":3,"file":"useCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback, useEffect, useMemo, useRef, useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport type { BillingCycle } from '../../types';\nimport { createCheckoutClient } from '../../utils/checkout';\nimport { getPlanFromUrl, writePlanQueryParam } from '../../utils/planQuery';\nimport { loadStripe } from '../../utils/stripe';\nimport {\n STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS,\n} from '../../constants';\nimport type {\n Status, Phase, Cart, BillingInfo, CheckoutClient, StripeLike, StripeElementLike,\n StripeElementsLike, BillingPlan, CheckoutConsent,\n} from '../../types';\nimport {\n useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery,\n useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery,\n} from './useCheckoutQueries';\nimport type { EdxSessionResult } from '../../utils/provision';\nimport { useCheckoutMutations } from './useCheckoutMutations';\n\n/**\n * Read ?course_run_key= from the current URL.\n * Avoid URLSearchParams — it treats bare `+` as a space, which would turn\n * HarvardX+CS50+X into \"HarvardX CS50 X\". decodeURIComponent keeps `+` intact.\n */\nfunction getCourseRunKeyFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n const match = /[?&]course_run_key=([^&]*)/.exec(window.location.search);\n if (!match) return null;\n try {\n // Preserve literal `+` (treat as %2B) then decode %XX sequences.\n return decodeURIComponent(match[1].replace(/\\+/g, '%2B')).trim() || null;\n } catch {\n return match[1].trim() || null;\n }\n}\n\nexport interface UseCheckoutOptions {\n apiUrl?: string,\n edxSessionUrl?: string,\n stripePublishableKey?: string,\n onComplete?: (subscriptionBiId: string | null) => void,\n /** Country code resolved by CheckoutGate — used to show/hide the UK/CA extra checkbox. */\n userCountry?: string | null,\n /**\n * Course run key from the URL (e.g. course-v1:HarvardX+CS50+X).\n * When omitted, read from ?course_run_key=.\n */\n courseRunKey?: string | null,\n}\n\nexport interface UseCheckoutResult {\n phase: Phase,\n status: Status | null,\n statusLabel: string,\n stripeReady: boolean,\n /** True once the Stripe card Element iframe is fully initialised and interactive. */\n cardReady: boolean,\n notConfigured: boolean,\n showBanner: boolean,\n dismissBanner: () => void,\n error: string,\n clearError: () => void,\n cardError: string,\n lastComment: string,\n /** Full subscription details including card last 4 — available after SUBSCRIPTION_CREATED. */\n subscriptionDetails: import('../../types').SubscriptionDetails | null,\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n submitting: boolean,\n /** True from Place order click until a terminal status is reached. */\n processingSubscription: boolean,\n placeOrder: (consent: CheckoutConsent) => void,\n /** Billing plans fetched on mount — includes prices for display in CartSummary. */\n billingPlans: BillingPlan[],\n /** Live active subscriber count for display in CartSummary. */\n activeSubscriberCount: number | null,\n /** Currently selected billing cycle. */\n selectedCycle: BillingCycle,\n /** Switch between monthly and annual billing. */\n setCycle: (cycle: BillingCycle) => void,\n /** True once GET /edx-session has returned and the viax token is set. */\n sessionReady: boolean,\n /** ISO 3166-1 alpha-2 country code — passed in from CheckoutGate for the UK/CA checkbox. */\n userCountry: string | null,\n /** Course details when arrived via ?course_run_key=; null for standard checkout. */\n course: import('../../types').CourseDetail | null,\n}\n\nexport default function useCheckout(options: UseCheckoutOptions = {}): UseCheckoutResult {\n const {\n apiUrl = DEFAULTS.apiUrl,\n edxSessionUrl,\n stripePublishableKey,\n onComplete,\n userCountry = null,\n courseRunKey: courseRunKeyProp,\n } = options;\n\n const courseRunKey = useMemo(\n () => courseRunKeyProp ?? getCourseRunKeyFromUrl(),\n [courseRunKeyProp],\n );\n\n const client = useMemo<CheckoutClient | null>(() => {\n if (!apiUrl) return null;\n return createCheckoutClient({ apiUrl });\n }, [apiUrl]);\n\n const notConfigured = !client || !stripePublishableKey || !edxSessionUrl;\n\n // Exchange edX session for viax token on page load.\n const sessionQuery = useViaxSessionQuery(notConfigured ? null : edxSessionUrl!);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n // Fetch billing plans, subscriber count, and optional course once the viax session is ready.\n const billingPlansQuery = useBillingPlansQuery(client, sessionReady);\n const activeSubscriptionsQuery = useActiveSubscriptionsQuery(client, sessionReady);\n const courseDetailQuery = useCourseDetailQuery(client, sessionReady, courseRunKey);\n\n // --- state ---\n const [showBanner, setShowBanner] = useState(true);\n const [cart, setCart] = useState<Cart | null>(null);\n const [stripe, setStripe] = useState<StripeLike | null>(null);\n const [stripeReady, setStripeReady] = useState(false);\n const [cardReady, setCardReady] = useState(false);\n const [error, setError] = useState('');\n const [cardError, setCardError] = useState('');\n const [billing, setBilling] = useState<BillingInfo>({\n firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',\n });\n const [selectedCycle, setSelectedCycle] = useState<BillingCycle>(getPlanFromUrl);\n const [processingSubscription, setProcessingSubscription] = useState(false);\n\n const setCycle = useCallback((cycle: BillingCycle) => {\n setSelectedCycle(cycle);\n writePlanQueryParam(cycle);\n }, []);\n\n useEffect(() => {\n if (sessionQuery.error) {\n setError(sessionQuery.error.message);\n }\n }, [sessionQuery.error]);\n\n const setField = useCallback(\n (field: keyof BillingInfo, value: string) => setBilling((p: BillingInfo) => ({ ...p, [field]: value })),\n [],\n );\n\n // --- refs ---\n // Stripe instances — written inside useEffect and mutations.\n const stripeInstanceRef = useRef<StripeLike | null>(null);\n const cardNumberElementRef = useRef<StripeElementLike | null>(null);\n const cardExpiryElementRef = useRef<StripeElementLike | null>(null);\n const cardCvcElementRef = useRef<StripeElementLike | null>(null);\n const elementsRef = useRef<StripeElementsLike | null>(null);\n // DOM mount targets — callback refs so we remount when hosts leave and return.\n const numberMountNodeRef = useRef<HTMLDivElement | null>(null);\n const expiryMountNodeRef = useRef<HTMLDivElement | null>(null);\n const cvcMountNodeRef = useRef<HTMLDivElement | null>(null);\n const [cardHostsEpoch, setCardHostsEpoch] = useState(0);\n\n const assignCardHost = useCallback((\n store: { current: HTMLDivElement | null },\n node: HTMLDivElement | null,\n ) => {\n store.current = node;\n if (\n numberMountNodeRef.current\n && expiryMountNodeRef.current\n && cvcMountNodeRef.current\n ) {\n setCardHostsEpoch((n) => n + 1);\n return;\n }\n // Hosts are leaving the DOM — detach so Stripe is not bound to dead nodes.\n cardNumberElementRef.current?.unmount?.();\n cardExpiryElementRef.current?.unmount?.();\n cardCvcElementRef.current?.unmount?.();\n }, []);\n\n const numberMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(numberMountNodeRef, node);\n }, [assignCardHost]);\n const expiryMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(expiryMountNodeRef, node);\n }, [assignCardHost]);\n const cvcMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(cvcMountNodeRef, node);\n }, [assignCardHost]);\n const mountedRef = useRef(true);\n const completedRef = useRef(false);\n const sessionRef = useRef<EdxSessionResult | null>(null);\n\n useEffect(() => {\n sessionRef.current = sessionQuery.data ?? null;\n }, [sessionQuery.data]);\n\n // Mirror state into refs so mutations can read current values without stale closures.\n const cartRef = useRef<Cart | null>(null);\n const billingRef = useRef<BillingInfo>(billing);\n const selectedCycleRef = useRef<BillingCycle>(selectedCycle);\n useEffect(() => {\n cartRef.current = cart;\n }, [cart]);\n useEffect(() => {\n billingRef.current = billing;\n }, [billing]);\n useEffect(() => {\n selectedCycleRef.current = selectedCycle;\n }, [selectedCycle]);\n useEffect(() => {\n stripeInstanceRef.current = stripe;\n }, [stripe]);\n\n // --- server state ---\n const statusQuery = useCartStatusQuery(client, cart?.biId ?? null);\n const status: Status | null = statusQuery.data?.status ?? null;\n const lastComment = statusQuery.data?.lastComment ?? '';\n\n // Phase is 'ready' until a cart exists, then driven by bpStatus.\n const phase: Phase = cart ? phaseFor(status, status === STATUS.IN_CART) : 'ready';\n const subscriptionIdQuery = useSubscriptionIdQuery(\n client, cart?.biId ?? null, status === STATUS.SUBSCRIPTION_CREATED,\n );\n\n // --- mutations ---\n const { placeOrder: placeMutation } = useCheckoutMutations({\n client,\n sessionRef,\n stripeRef: stripeInstanceRef,\n cardNumberElRef: cardNumberElementRef,\n billingRef,\n selectedCycleRef,\n setError: (msg: string) => {\n setProcessingSubscription(false);\n setError(msg);\n },\n setCardError: (msg: string) => {\n setProcessingSubscription(false);\n setCardError(msg);\n },\n onCartCreated: (created: Cart) => {\n // Sync the ref immediately so any same-tick readers see the cart\n // before the setCart → useEffect mirror runs.\n cartRef.current = created;\n if (mountedRef.current) setCart(created);\n },\n });\n\n // --- load Stripe.js on mount ---\n useEffect(() => {\n mountedRef.current = true;\n if (!stripePublishableKey) return undefined;\n\n (async () => {\n try {\n const instance = await loadStripe(stripePublishableKey);\n if (mountedRef.current) {\n setStripe(instance);\n setStripeReady(true);\n }\n } catch (e: unknown) {\n if (mountedRef.current) setError((e as Error).message);\n }\n })();\n\n return () => {\n mountedRef.current = false;\n };\n }, [stripePublishableKey]);\n\n // --- mount Stripe Elements once Stripe is loaded; remount if hosts return ---\n useEffect(() => {\n if (!stripe) return;\n const numberNode = numberMountNodeRef.current;\n const expiryNode = expiryMountNodeRef.current;\n const cvcNode = cvcMountNodeRef.current;\n if (!numberNode || !expiryNode || !cvcNode) return;\n\n if (cardNumberElementRef.current && cardExpiryElementRef.current && cardCvcElementRef.current) {\n try {\n cardNumberElementRef.current.unmount?.();\n cardExpiryElementRef.current.unmount?.();\n cardCvcElementRef.current.unmount?.();\n cardNumberElementRef.current.mount(numberNode);\n cardExpiryElementRef.current.mount(expiryNode);\n cardCvcElementRef.current.mount(cvcNode);\n return;\n } catch {\n // Element is bound to a destroyed host — create a fresh Elements group.\n cardNumberElementRef.current = null;\n cardExpiryElementRef.current = null;\n cardCvcElementRef.current = null;\n elementsRef.current = null;\n }\n }\n\n setCardReady(false);\n\n const elements = stripe.elements();\n elementsRef.current = elements;\n\n const number = elements.create('cardNumber', { ...STRIPE_ELEMENT_OPTS, showIcon: true });\n const expiry = elements.create('cardExpiry', STRIPE_ELEMENT_OPTS);\n const cvc = elements.create('cardCvc', STRIPE_ELEMENT_OPTS);\n\n number.mount(numberNode);\n expiry.mount(expiryNode);\n cvc.mount(cvcNode);\n\n number.on('ready', () => {\n if (mountedRef.current) setCardReady(true);\n });\n number.on('change', (e: { error?: { message?: string } }) => {\n if (mountedRef.current) setCardError(e.error?.message || '');\n });\n\n cardNumberElementRef.current = number;\n cardExpiryElementRef.current = expiry;\n cardCvcElementRef.current = cvc;\n }, [stripe, cardHostsEpoch]);\n\n // --- on success ---\n useEffect(() => {\n if (status !== STATUS.SUBSCRIPTION_CREATED || completedRef.current) return;\n completedRef.current = true;\n if (onComplete) onComplete(subscriptionIdQuery.data?.biId ?? null);\n }, [status, subscriptionIdQuery.data, onComplete]);\n\n // --- actions ---\n const placeOrder = useCallback((consent: CheckoutConsent) => {\n setError('');\n setCardError('');\n if (phase === 'failed') setCart(null);\n setProcessingSubscription(true);\n placeMutation.mutate(consent);\n }, [placeMutation, phase]);\n\n // Turn off processingSubscription once we reach a terminal status.\n useEffect(() => {\n if (!status) return;\n const terminalStatuses: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.STRIPE_FAIL,\n STATUS.SANCTION_BLOCK,\n ];\n if (terminalStatuses.includes(status)) {\n setProcessingSubscription(false);\n }\n }, [status]);\n\n return {\n phase,\n status,\n statusLabel: (status && STATUS_LABELS[status]) || 'Processing your order…',\n stripeReady,\n cardReady,\n notConfigured,\n showBanner,\n dismissBanner: () => setShowBanner(false),\n error,\n clearError: () => setError(''),\n cardError,\n lastComment,\n subscriptionDetails: subscriptionIdQuery.data ?? null,\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n submitting: placeMutation.isPending,\n processingSubscription,\n placeOrder,\n billingPlans: billingPlansQuery.data?.plans ?? [],\n activeSubscriberCount: activeSubscriptionsQuery.data?.active ?? null,\n selectedCycle,\n setCycle,\n sessionReady,\n userCountry,\n course: courseDetailQuery.data ?? null,\n };\n}\n"]}
@@ -26,29 +26,16 @@
26
26
  align-items: center;
27
27
  justify-content: center;
28
28
  flex-shrink: 0;
29
- width: 56px;
30
- height: 40px;
31
- border-radius: 6px;
32
- background: #1f1f1f;
33
- line-height: 1;
29
+ padding: 0.5rem 0.625rem;
34
30
  margin-right: 0.75rem;
35
- }
36
-
37
- &__edx-logo-text {
38
- text-align: center;
39
- }
40
-
41
- &__edx-logo-edx {
42
- color: #fff;
43
- font-weight: 800;
44
- font-size: 0.8rem;
45
- letter-spacing: -0.02em;
46
- }
31
+ background: #fff;
32
+ border: 1px solid #e7e9ef;
33
+ border-radius: 8px;
47
34
 
48
- &__edx-logo-unlimited {
49
- color: #b1c2ff;
50
- font-size: 0.5rem;
51
- font-weight: 600;
52
- margin-top: 1px;
35
+ img {
36
+ display: block;
37
+ width: 48px;
38
+ height: 25px;
39
+ }
53
40
  }
54
41
  }