@edx/frontend-app-subscription-checkout 1.17.0 → 1.18.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.
|
@@ -112,7 +112,13 @@ const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMou
|
|
|
112
112
|
if (paymentMethod !== 'googlepay') {
|
|
113
113
|
// Track the event before placing order
|
|
114
114
|
trackConfirmSubscriptionClicked({
|
|
115
|
+
priceToShow,
|
|
116
|
+
cycleToShow,
|
|
117
|
+
trialEnd,
|
|
118
|
+
promoAmount,
|
|
115
119
|
paymentMethod,
|
|
120
|
+
promoMonths,
|
|
121
|
+
monthlyRegularAmount,
|
|
116
122
|
billingCountry: billing.country,
|
|
117
123
|
cycle: cycleToShow,
|
|
118
124
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentForm.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/PaymentForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl, getAppConfig } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent, PaymentMethod, SupportedPaymentMethod } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport {\n appId,\n COUNTRIES_REQUIRING_EXTRA_CONFIRM,\n BILLING_COUNTRIES,\n} from '../../constants';\nimport { fetchIpGeolocation, fetchPublicIp } from '../../utils/provision';\nimport messages from './Messages';\nimport { trackConfirmSubscriptionClicked } from '@src/tracking/subscription';\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, paymentMethod: SupportedPaymentMethod) => 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 geolocationUrl?: 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 promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount = '59',\n geolocationUrl,\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const config = getAppConfig(appId);\n const tosUrl = config.TOS_URL as string;\n const refundPolicyUrl = config.REFUND_POLICY_URL as string;\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [extraConfirmed, setExtraConfirmed] = useState(false);\n\n const showExtraConfirm = COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(billing.country);\n const extraConfirmMessage = billing.country === 'CA'\n ? messages.canadaQuebecConfirm\n : messages.ukWithdrawalConfirm;\n const extraConfirmId = billing.country === 'CA'\n ? 'canadaQuebecConfirm'\n : 'ukWithdrawalConfirm';\n\n useEffect(() => {\n if (!geolocationUrl) return;\n\n void fetchPublicIp()\n .then((ipAddress) => fetchIpGeolocation(geolocationUrl, ipAddress))\n .then((geolocation) => {\n const countryCode = geolocation.country_code?.toUpperCase();\n if (countryCode && BILLING_COUNTRIES.some(([code]) => code === countryCode)) {\n setField('country', countryCode);\n }\n })\n .catch(() => undefined);\n }, [geolocationUrl, setField]);\n\n const needsStripe = paymentMethod !== 'paypal';\n const busy = submitting || (needsStripe && !stripeReady) || !sessionReady;\n\n let buttonLabel = paymentMethod === 'paypal'\n ? formatMessage(messages.continueWithPaypal)\n : formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady || (needsStripe && !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 termsNoticeValues = {\n pricing,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n };\n\n const termsText = isMonthly\n ? formatMessage(messages.termsNotice, {\n ...termsNoticeValues,\n trialDays,\n date: trialEnd ?? '{date}',\n })\n : formatMessage(messages.termsNoticeAnnual, termsNoticeValues);\n\n const buildConsent = (): CheckoutConsent => {\n const consentParts = [termsText, recurringConfirmText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(extraConfirmMessage));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? extraConfirmed : 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 const selectedCountry = e.target.value;\n setField('country', selectedCountry);\n setExtraConfirmed(false);\n }}\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 ── */}\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 {isMonthly\n ? formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })\n : formatMessage(messages.termsNoticeAnnual, {\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\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={extraConfirmId} className=\"mb-4 payment-form__confirm\">\n <Form.Checkbox\n id={extraConfirmId}\n checked={extraConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setExtraConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {formatMessage(extraConfirmMessage)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => {\n if (paymentMethod !== 'googlepay') {\n // Track the event before placing order\n trackConfirmSubscriptionClicked({\n paymentMethod,\n billingCountry: billing.country,\n cycle: cycleToShow,\n });\n onPlaceOrder(buildConsent(), paymentMethod);\n }\n }}\n disabled={\n (needsStripe && !stripeReady)\n || submitting\n || !confirmed\n || paymentMethod === 'googlepay'\n || (showExtraConfirm && !extraConfirmed)\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, { useEffect, useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl, getAppConfig } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent, PaymentMethod, SupportedPaymentMethod } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport {\n appId,\n COUNTRIES_REQUIRING_EXTRA_CONFIRM,\n BILLING_COUNTRIES,\n} from '../../constants';\nimport { fetchIpGeolocation, fetchPublicIp } from '../../utils/provision';\nimport messages from './Messages';\nimport { trackConfirmSubscriptionClicked } from '@src/tracking/subscription';\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, paymentMethod: SupportedPaymentMethod) => 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 geolocationUrl?: 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 promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount = '59',\n geolocationUrl,\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const config = getAppConfig(appId);\n const tosUrl = config.TOS_URL as string;\n const refundPolicyUrl = config.REFUND_POLICY_URL as string;\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [extraConfirmed, setExtraConfirmed] = useState(false);\n\n const showExtraConfirm = COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(billing.country);\n const extraConfirmMessage = billing.country === 'CA'\n ? messages.canadaQuebecConfirm\n : messages.ukWithdrawalConfirm;\n const extraConfirmId = billing.country === 'CA'\n ? 'canadaQuebecConfirm'\n : 'ukWithdrawalConfirm';\n\n useEffect(() => {\n if (!geolocationUrl) return;\n\n void fetchPublicIp()\n .then((ipAddress) => fetchIpGeolocation(geolocationUrl, ipAddress))\n .then((geolocation) => {\n const countryCode = geolocation.country_code?.toUpperCase();\n if (countryCode && BILLING_COUNTRIES.some(([code]) => code === countryCode)) {\n setField('country', countryCode);\n }\n })\n .catch(() => undefined);\n }, [geolocationUrl, setField]);\n\n const needsStripe = paymentMethod !== 'paypal';\n const busy = submitting || (needsStripe && !stripeReady) || !sessionReady;\n\n let buttonLabel = paymentMethod === 'paypal'\n ? formatMessage(messages.continueWithPaypal)\n : formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady || (needsStripe && !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 termsNoticeValues = {\n pricing,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n };\n\n const termsText = isMonthly\n ? formatMessage(messages.termsNotice, {\n ...termsNoticeValues,\n trialDays,\n date: trialEnd ?? '{date}',\n })\n : formatMessage(messages.termsNoticeAnnual, termsNoticeValues);\n\n const buildConsent = (): CheckoutConsent => {\n const consentParts = [termsText, recurringConfirmText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(extraConfirmMessage));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? extraConfirmed : 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 const selectedCountry = e.target.value;\n setField('country', selectedCountry);\n setExtraConfirmed(false);\n }}\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 ── */}\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 {isMonthly\n ? formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })\n : formatMessage(messages.termsNoticeAnnual, {\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\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={extraConfirmId} className=\"mb-4 payment-form__confirm\">\n <Form.Checkbox\n id={extraConfirmId}\n checked={extraConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setExtraConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {formatMessage(extraConfirmMessage)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => {\n if (paymentMethod !== 'googlepay') {\n // Track the event before placing order\n trackConfirmSubscriptionClicked({\n priceToShow,\n cycleToShow,\n trialEnd,\n promoAmount,\n paymentMethod,\n promoMonths,\n monthlyRegularAmount,\n billingCountry: billing.country,\n cycle: cycleToShow,\n });\n onPlaceOrder(buildConsent(), paymentMethod);\n }\n }}\n disabled={\n (needsStripe && !stripeReady)\n || submitting\n || !confirmed\n || paymentMethod === 'googlepay'\n || (showExtraConfirm && !extraConfirmed)\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"]}
|