@edx/frontend-app-alacarte-checkout 1.0.0 → 1.2.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.
- package/dist/components/CartSummary/CartSummary.d.ts +1 -1
- package/dist/components/CartSummary/CartSummary.js +12 -26
- package/dist/components/CartSummary/CartSummary.js.map +1 -1
- package/dist/components/CartSummary/Messages.d.ts +2 -37
- package/dist/components/CartSummary/Messages.js +10 -45
- package/dist/components/CartSummary/Messages.js.map +1 -1
- package/dist/components/Checkout/Checkout.js +1 -1
- package/dist/components/Checkout/Checkout.js.map +1 -1
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +1 -1
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +8 -3
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +1 -1
- package/dist/components/CourseEnrollmentCard/Messages.d.ts +15 -0
- package/dist/components/CourseEnrollmentCard/Messages.js +15 -0
- package/dist/components/CourseEnrollmentCard/Messages.js.map +1 -1
- package/dist/components/ExpressCheckout/ExpressCheckout.d.ts +2 -0
- package/dist/components/ExpressCheckout/ExpressCheckout.js +12 -0
- package/dist/components/ExpressCheckout/ExpressCheckout.js.map +1 -0
- package/dist/components/ExpressCheckout/Messages.d.ts +23 -0
- package/dist/components/ExpressCheckout/Messages.js +25 -0
- package/dist/components/ExpressCheckout/Messages.js.map +1 -0
- package/dist/components/PaymentFields/PaymentFields.js +2 -1
- package/dist/components/PaymentFields/PaymentFields.js.map +1 -1
- package/dist/components/PaymentForm/Messages.d.ts +6 -66
- package/dist/components/PaymentForm/Messages.js +27 -89
- package/dist/components/PaymentForm/Messages.js.map +1 -1
- package/dist/components/PaymentForm/PaymentForm.d.ts +1 -1
- package/dist/components/PaymentForm/PaymentForm.js +18 -114
- package/dist/components/PaymentForm/PaymentForm.js.map +1 -1
- package/dist/components/PromoCode/Messages.d.ts +28 -0
- package/dist/components/PromoCode/Messages.js +30 -0
- package/dist/components/PromoCode/Messages.js.map +1 -0
- package/dist/components/PromoCode/PromoCode.d.ts +2 -0
- package/dist/components/PromoCode/PromoCode.js +14 -0
- package/dist/components/PromoCode/PromoCode.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +12 -1
- package/dist/constants.js.map +1 -1
- package/dist/data/hooks/useCheckout.js +2 -2
- package/dist/data/hooks/useCheckout.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/style.scss +2 -0
- package/dist/styles/components/cartSummary.scss +45 -3
- package/dist/styles/components/checkout.scss +12 -1
- package/dist/styles/components/courseEnrollmentCard.scss +58 -0
- package/dist/styles/components/expressCheckout.scss +58 -0
- package/dist/styles/components/paymentFields.scss +7 -0
- package/dist/styles/components/paymentForm.scss +53 -87
- package/dist/styles/components/promoCode.scss +71 -0
- package/dist/utils/provision.js +2 -2
- package/dist/utils/provision.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineMessages } from '@openedx/frontend-base';
|
|
2
|
+
const messages = defineMessages({
|
|
3
|
+
heading: {
|
|
4
|
+
id: 'checkout.expressCheckout.heading',
|
|
5
|
+
defaultMessage: 'Express checkout',
|
|
6
|
+
description: 'Heading for the express checkout section',
|
|
7
|
+
},
|
|
8
|
+
paypal: {
|
|
9
|
+
id: 'checkout.expressCheckout.paypal',
|
|
10
|
+
defaultMessage: 'PayPal',
|
|
11
|
+
description: 'Accessible label for the PayPal express checkout button',
|
|
12
|
+
},
|
|
13
|
+
applePay: {
|
|
14
|
+
id: 'checkout.expressCheckout.applePay',
|
|
15
|
+
defaultMessage: 'Apple Pay',
|
|
16
|
+
description: 'Accessible label for the Apple Pay express checkout button',
|
|
17
|
+
},
|
|
18
|
+
googlePay: {
|
|
19
|
+
id: 'checkout.expressCheckout.googlePay',
|
|
20
|
+
defaultMessage: 'Google Pay',
|
|
21
|
+
description: 'Accessible label for the Google Pay express checkout button',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
export default messages;
|
|
25
|
+
//# sourceMappingURL=Messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../../src/components/ExpressCheckout/Messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,OAAO,EAAE;QACP,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,0CAA0C;KACxD;IACD,MAAM,EAAE;QACN,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,QAAQ;QACxB,WAAW,EAAE,yDAAyD;KACvE;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,mCAAmC;QACvC,cAAc,EAAE,WAAW;QAC3B,WAAW,EAAE,4DAA4D;KAC1E;IACD,SAAS,EAAE;QACT,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,YAAY;QAC5B,WAAW,EAAE,6DAA6D;KAC3E;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n heading: {\n id: 'checkout.expressCheckout.heading',\n defaultMessage: 'Express checkout',\n description: 'Heading for the express checkout section',\n },\n paypal: {\n id: 'checkout.expressCheckout.paypal',\n defaultMessage: 'PayPal',\n description: 'Accessible label for the PayPal express checkout button',\n },\n applePay: {\n id: 'checkout.expressCheckout.applePay',\n defaultMessage: 'Apple Pay',\n description: 'Accessible label for the Apple Pay express checkout button',\n },\n googlePay: {\n id: 'checkout.expressCheckout.googlePay',\n defaultMessage: 'Google Pay',\n description: 'Accessible label for the Google Pay express checkout button',\n },\n});\n\nexport default messages;\n"]}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Form } from '@openedx/paragon';
|
|
3
3
|
import { STRIPE_FIELD_STYLE } from '../../constants';
|
|
4
4
|
import { CardBrands } from '../BrandMarks/BrandMarks';
|
|
5
|
-
|
|
5
|
+
import creditCardCvc from './creditCardCvc.png';
|
|
6
|
+
const PaymentFields = ({ numberMountRef, expiryMountRef, cvcMountRef, cardError, }) => (_jsxs("div", { className: "payment--field", children: [_jsxs("div", { className: "d-flex flex-column mb-3 gap-4", children: [_jsxs(Form.Group, { controlId: "cardNumber", className: "mb-0 flex-grow-1", children: [_jsx(Form.Label, { className: "payment--field__label text-gray-900", children: "Card number (16 digits)" }), _jsxs("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: [_jsx("div", { ref: numberMountRef, className: "flex-grow-1" }), _jsx(CardBrands, {})] })] }), _jsxs("div", { className: "d-flex gap-4", children: [_jsxs(Form.Group, { controlId: "cardExpiry", className: "card__expiry mb-0 w-50", children: [_jsx(Form.Label, { className: "payment--field__label text-gray-900", children: "Expiration (MM/YY)" }), _jsx("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: _jsx("div", { ref: expiryMountRef, className: "flex-grow-1" }) })] }), _jsxs(Form.Group, { controlId: "cardCvc", className: "card__cvc mb-0 w-50", children: [_jsx(Form.Label, { className: "payment--field__label text-gray-900", children: "CVC (3-4 digits)" }), _jsxs("div", { className: "form-control", style: STRIPE_FIELD_STYLE, children: [_jsx("div", { ref: cvcMountRef, className: "flex-grow-1" }), _jsx("img", { src: creditCardCvc, alt: "", width: 24, height: 24 })] })] })] })] }), cardError && _jsx("p", { className: "text-danger small mb-2", children: cardError })] }));
|
|
6
7
|
export default PaymentFields;
|
|
7
8
|
//# sourceMappingURL=PaymentFields.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentFields.js","sourceRoot":"","sources":["../../../src/components/PaymentFields/PaymentFields.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"PaymentFields.js","sourceRoot":"","sources":["../../../src/components/PaymentFields/PaymentFields.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAShD,MAAM,aAAa,GAAG,CAAC,EACrB,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,GACU,EAAE,EAAE,CAAC,CACxB,eAAK,SAAS,EAAC,gBAAgB,aAE7B,eAAK,SAAS,EAAC,+BAA+B,aAE5C,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,SAAS,EAAC,kBAAkB,aAC7D,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,qCAAqC,wCAE9C,EACb,eAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,aACrD,cAAK,GAAG,EAAE,cAAc,EAAE,SAAS,EAAC,aAAa,GAAG,EACpD,KAAC,UAAU,KAAG,IACV,IACK,EAEb,eAAK,SAAS,EAAC,cAAc,aAE3B,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,SAAS,EAAC,wBAAwB,aACnE,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,qCAAqC,mCAE9C,EACb,cAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,YACrD,cAAK,GAAG,EAAE,cAAc,EAAE,SAAS,EAAC,aAAa,GAAG,GAChD,IACK,EAGb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,SAAS,EAAC,SAAS,EAAC,qBAAqB,aAC7D,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,qCAAqC,iCAA8B,EACzF,eAAK,SAAS,EAAC,cAAc,EAAC,KAAK,EAAE,kBAAkB,aACrD,cAAK,GAAG,EAAE,WAAW,EAAE,SAAS,EAAC,aAAa,GAAG,EACjD,cAAK,GAAG,EAAE,aAAa,EAAE,GAAG,EAAC,EAAE,EAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,IACrD,IACK,IACT,IACF,EAEL,SAAS,IAAI,YAAG,SAAS,EAAC,wBAAwB,YAAE,SAAS,GAAK,IAC/D,CACP,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import React from 'react';\nimport type { Ref } from 'react';\nimport { Form } from '@openedx/paragon';\nimport { STRIPE_FIELD_STYLE } from '../../constants';\nimport { CardBrands } from '../BrandMarks/BrandMarks';\nimport creditCardCvc from './creditCardCvc.png';\n\nexport interface PaymentFieldsProps {\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n}\n\nconst PaymentFields = ({\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n}: PaymentFieldsProps) => (\n <div className=\"payment--field\">\n {/* Single-row wrapper on desktop, stacked on mobile */}\n <div className=\"d-flex flex-column mb-3 gap-4\">\n {/* Card number — grows to fill available space */}\n <Form.Group controlId=\"cardNumber\" className=\"mb-0 flex-grow-1\">\n <Form.Label className=\"payment--field__label text-gray-900\">\n Card number (16 digits)\n </Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={numberMountRef} className=\"flex-grow-1\" />\n <CardBrands />\n </div>\n </Form.Group>\n\n <div className=\"d-flex gap-4\">\n {/* Expiry — fixed width on desktop */}\n <Form.Group controlId=\"cardExpiry\" className=\"card__expiry mb-0 w-50\">\n <Form.Label className=\"payment--field__label text-gray-900\">\n Expiration (MM/YY)\n </Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={expiryMountRef} className=\"flex-grow-1\" />\n </div>\n </Form.Group>\n\n {/* CVC — fixed width on desktop */}\n <Form.Group controlId=\"cardCvc\" className=\"card__cvc mb-0 w-50\">\n <Form.Label className=\"payment--field__label text-gray-900\">CVC (3-4 digits)</Form.Label>\n <div className=\"form-control\" style={STRIPE_FIELD_STYLE}>\n <div ref={cvcMountRef} className=\"flex-grow-1\" />\n <img src={creditCardCvc} alt=\"\" width={24} height={24} />\n </div>\n </Form.Group>\n </div>\n </div>\n\n {cardError && <p className=\"text-danger small mb-2\">{cardError}</p>}\n </div>\n);\n\nexport default PaymentFields;\n"]}
|
|
@@ -19,87 +19,27 @@ declare const messages: {
|
|
|
19
19
|
defaultMessage: string;
|
|
20
20
|
description: string;
|
|
21
21
|
};
|
|
22
|
-
|
|
22
|
+
payWithCard: {
|
|
23
23
|
id: string;
|
|
24
24
|
defaultMessage: string;
|
|
25
25
|
description: string;
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
orderDisclaimer: {
|
|
28
28
|
id: string;
|
|
29
29
|
defaultMessage: string;
|
|
30
30
|
description: string;
|
|
31
31
|
};
|
|
32
|
-
|
|
32
|
+
total: {
|
|
33
33
|
id: string;
|
|
34
34
|
defaultMessage: string;
|
|
35
35
|
description: string;
|
|
36
36
|
};
|
|
37
|
-
|
|
37
|
+
totalAmount: {
|
|
38
38
|
id: string;
|
|
39
39
|
defaultMessage: string;
|
|
40
40
|
description: string;
|
|
41
41
|
};
|
|
42
|
-
|
|
43
|
-
id: string;
|
|
44
|
-
defaultMessage: string;
|
|
45
|
-
description: string;
|
|
46
|
-
};
|
|
47
|
-
termsPricingMonthly: {
|
|
48
|
-
id: string;
|
|
49
|
-
defaultMessage: string;
|
|
50
|
-
description: string;
|
|
51
|
-
};
|
|
52
|
-
termsPricingAnnual: {
|
|
53
|
-
id: string;
|
|
54
|
-
defaultMessage: string;
|
|
55
|
-
description: string;
|
|
56
|
-
};
|
|
57
|
-
termsOfUse: {
|
|
58
|
-
id: string;
|
|
59
|
-
defaultMessage: string;
|
|
60
|
-
description: string;
|
|
61
|
-
};
|
|
62
|
-
refundPolicy: {
|
|
63
|
-
id: string;
|
|
64
|
-
defaultMessage: string;
|
|
65
|
-
description: string;
|
|
66
|
-
};
|
|
67
|
-
recurringConfirmMonthly: {
|
|
68
|
-
id: string;
|
|
69
|
-
defaultMessage: string;
|
|
70
|
-
description: string;
|
|
71
|
-
};
|
|
72
|
-
recurringConfirmAnnual: {
|
|
73
|
-
id: string;
|
|
74
|
-
defaultMessage: string;
|
|
75
|
-
description: string;
|
|
76
|
-
};
|
|
77
|
-
ukWithdrawalConfirm: {
|
|
78
|
-
id: string;
|
|
79
|
-
defaultMessage: string;
|
|
80
|
-
description: string;
|
|
81
|
-
};
|
|
82
|
-
canadaQuebecConfirm: {
|
|
83
|
-
id: string;
|
|
84
|
-
defaultMessage: string;
|
|
85
|
-
description: string;
|
|
86
|
-
};
|
|
87
|
-
confirmSubscription: {
|
|
88
|
-
id: string;
|
|
89
|
-
defaultMessage: string;
|
|
90
|
-
description: string;
|
|
91
|
-
};
|
|
92
|
-
continueWithPaypal: {
|
|
93
|
-
id: string;
|
|
94
|
-
defaultMessage: string;
|
|
95
|
-
description: string;
|
|
96
|
-
};
|
|
97
|
-
processing: {
|
|
98
|
-
id: string;
|
|
99
|
-
defaultMessage: string;
|
|
100
|
-
description: string;
|
|
101
|
-
};
|
|
102
|
-
loadingPayment: {
|
|
42
|
+
payNow: {
|
|
103
43
|
id: string;
|
|
104
44
|
defaultMessage: string;
|
|
105
45
|
description: string;
|
|
@@ -109,7 +49,7 @@ declare const messages: {
|
|
|
109
49
|
defaultMessage: string;
|
|
110
50
|
description: string;
|
|
111
51
|
};
|
|
112
|
-
|
|
52
|
+
countryPlaceholder: {
|
|
113
53
|
id: string;
|
|
114
54
|
defaultMessage: string;
|
|
115
55
|
description: string;
|
|
@@ -21,104 +21,42 @@ const messages = defineMessages({
|
|
|
21
21
|
defaultMessage: 'Learner Help Center',
|
|
22
22
|
description: 'Learner help center link text',
|
|
23
23
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
id: 'checkout.paymentForm.
|
|
32
|
-
defaultMessage: '
|
|
33
|
-
description: '
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
id: 'checkout.paymentForm.
|
|
37
|
-
defaultMessage: '
|
|
38
|
-
description: '
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
description: 'Monthly subscription terms notice with free trial, shown before the confirm button',
|
|
45
|
-
},
|
|
46
|
-
termsNoticeAnnual: {
|
|
47
|
-
id: 'checkout.paymentForm.termsNoticeAnnual',
|
|
48
|
-
defaultMessage: 'Your edX Plus subscription will start today. You will be charged {pricing} today (inclusive of applicable taxes). Your subscription automatically renews annually. Cancel your subscription anytime from your dashboard. By clicking “Confirm subscription” you agree to our {termsLink}, and {refundLink}.',
|
|
49
|
-
description: 'Annual subscription terms notice without free trial, shown before the confirm button',
|
|
50
|
-
},
|
|
51
|
-
termsPricingMonthly: {
|
|
52
|
-
id: 'checkout.paymentForm.termsPricingMonthly',
|
|
53
|
-
defaultMessage: '${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo',
|
|
54
|
-
description: 'Monthly promotional pricing in the terms notice e.g. $39/mo for 3 months then $59/mo',
|
|
55
|
-
},
|
|
56
|
-
termsPricingAnnual: {
|
|
57
|
-
id: 'checkout.paymentForm.termsPricingAnnual',
|
|
58
|
-
defaultMessage: '${amount}/{frequency}',
|
|
59
|
-
description: 'Annual plan pricing in the terms notice e.g. $299/year — no promotional pricing',
|
|
60
|
-
},
|
|
61
|
-
termsOfUse: {
|
|
62
|
-
id: 'checkout.paymentForm.termsOfUse',
|
|
63
|
-
defaultMessage: 'Terms of Use',
|
|
64
|
-
description: 'Terms of Use link text',
|
|
65
|
-
},
|
|
66
|
-
refundPolicy: {
|
|
67
|
-
id: 'checkout.paymentForm.refundPolicy',
|
|
68
|
-
defaultMessage: 'Refund Policy',
|
|
69
|
-
description: 'Refund Policy link text',
|
|
70
|
-
},
|
|
71
|
-
// Checkboxes
|
|
72
|
-
recurringConfirmMonthly: {
|
|
73
|
-
id: 'checkout.paymentForm.recurringConfirmMonthly',
|
|
74
|
-
defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${promoAmount}/mo for {promoMonths} months then ${regularAmount}/mo USD.',
|
|
75
|
-
description: 'Monthly checkbox confirming recurring charge with promo then regular price',
|
|
76
|
-
},
|
|
77
|
-
recurringConfirmAnnual: {
|
|
78
|
-
id: 'checkout.paymentForm.recurringConfirmAnnual',
|
|
79
|
-
defaultMessage: 'I agree to enroll in a recurring monthly subscription for ${amount}/yr USD.',
|
|
80
|
-
description: 'Annual checkbox confirming recurring charge',
|
|
81
|
-
},
|
|
82
|
-
ukWithdrawalConfirm: {
|
|
83
|
-
id: 'checkout.paymentForm.ukWithdrawalConfirm',
|
|
84
|
-
defaultMessage: 'I hereby consent to immediate performance of the contract and acknowledge that I will lose my right of withdrawal from the contract once the download or streaming of the digital content has begun.',
|
|
85
|
-
description: 'UK consent to immediate performance of the contract and loss of withdrawal rights',
|
|
86
|
-
},
|
|
87
|
-
canadaQuebecConfirm: {
|
|
88
|
-
id: 'checkout.paymentForm.canadaQuebecConfirm',
|
|
89
|
-
defaultMessage: 'I hereby verify I am not a resident of Quebec province',
|
|
90
|
-
description: 'Canadian consent verifying that the customer is not a resident of Quebec province',
|
|
24
|
+
payWithCard: {
|
|
25
|
+
id: 'checkout.paymentForm.payWithCard',
|
|
26
|
+
defaultMessage: 'Pay with card',
|
|
27
|
+
description: 'Heading for the card payment fields',
|
|
28
|
+
},
|
|
29
|
+
// Order total
|
|
30
|
+
orderDisclaimer: {
|
|
31
|
+
id: 'checkout.paymentForm.orderDisclaimer',
|
|
32
|
+
defaultMessage: 'The above total includes any applicable taxes. After you complete your order you will be automatically enrolled in the verified track of the course.',
|
|
33
|
+
description: 'Disclaimer shown above the order total explaining taxes and enrollment',
|
|
34
|
+
},
|
|
35
|
+
total: {
|
|
36
|
+
id: 'checkout.paymentForm.total',
|
|
37
|
+
defaultMessage: 'Total:',
|
|
38
|
+
description: 'Label for the order total amount',
|
|
39
|
+
},
|
|
40
|
+
totalAmount: {
|
|
41
|
+
id: 'checkout.paymentForm.totalAmount',
|
|
42
|
+
defaultMessage: '${amount} {currency}',
|
|
43
|
+
description: 'Formatted order total with currency code e.g. $219.00 USD',
|
|
91
44
|
},
|
|
92
45
|
// Submit button
|
|
93
|
-
|
|
94
|
-
id: 'checkout.paymentForm.
|
|
95
|
-
defaultMessage: '
|
|
46
|
+
payNow: {
|
|
47
|
+
id: 'checkout.paymentForm.payNow',
|
|
48
|
+
defaultMessage: 'Pay now',
|
|
96
49
|
description: 'Submit button label',
|
|
97
50
|
},
|
|
98
|
-
continueWithPaypal: {
|
|
99
|
-
id: 'checkout.paymentForm.continueWithPaypal',
|
|
100
|
-
defaultMessage: 'Continue with PayPal',
|
|
101
|
-
description: 'Submit button label when PayPal is the selected payment method',
|
|
102
|
-
},
|
|
103
|
-
processing: {
|
|
104
|
-
id: 'checkout.paymentForm.processing',
|
|
105
|
-
defaultMessage: 'Confirming Subscription',
|
|
106
|
-
description: 'Submit button label while the subscription is being confirmed',
|
|
107
|
-
},
|
|
108
|
-
loadingPayment: {
|
|
109
|
-
id: 'checkout.paymentForm.loadingPayment',
|
|
110
|
-
defaultMessage: 'Loading payment…',
|
|
111
|
-
description: 'Submit button label while Stripe loads',
|
|
112
|
-
},
|
|
113
51
|
country: {
|
|
114
52
|
id: 'checkout.paymentForm.country',
|
|
115
53
|
defaultMessage: 'Country',
|
|
116
54
|
description: 'Country selector label',
|
|
117
55
|
},
|
|
118
|
-
|
|
119
|
-
id: 'checkout.paymentForm.
|
|
120
|
-
defaultMessage: '
|
|
121
|
-
description: '
|
|
56
|
+
countryPlaceholder: {
|
|
57
|
+
id: 'checkout.paymentForm.countryPlaceholder',
|
|
58
|
+
defaultMessage: 'Select your country',
|
|
59
|
+
description: 'Placeholder option shown before a country is selected',
|
|
122
60
|
},
|
|
123
61
|
});
|
|
124
62
|
export default messages;
|
|
@@ -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,
|
|
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,WAAW,EAAE;QACX,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,qCAAqC;KACnD;IAED,cAAc;IACd,eAAe,EAAE;QACf,EAAE,EAAE,sCAAsC;QAC1C,cAAc,EAAE,sJAAsJ;QACtK,WAAW,EAAE,wEAAwE;KACtF;IACD,KAAK,EAAE;QACL,EAAE,EAAE,4BAA4B;QAChC,cAAc,EAAE,QAAQ;QACxB,WAAW,EAAE,kCAAkC;KAChD;IACD,WAAW,EAAE;QACX,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,sBAAsB;QACtC,WAAW,EAAE,2DAA2D;KACzE;IAED,gBAAgB;IAChB,MAAM,EAAE;QACN,EAAE,EAAE,6BAA6B;QACjC,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,qBAAqB;KACnC;IACD,OAAO,EAAE;QACP,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,wBAAwB;KACtC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,qBAAqB;QACrC,WAAW,EAAE,uDAAuD;KACrE;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 payWithCard: {\n id: 'checkout.paymentForm.payWithCard',\n defaultMessage: 'Pay with card',\n description: 'Heading for the card payment fields',\n },\n\n // Order total\n orderDisclaimer: {\n id: 'checkout.paymentForm.orderDisclaimer',\n defaultMessage: 'The above total includes any applicable taxes. After you complete your order you will be automatically enrolled in the verified track of the course.',\n description: 'Disclaimer shown above the order total explaining taxes and enrollment',\n },\n total: {\n id: 'checkout.paymentForm.total',\n defaultMessage: 'Total:',\n description: 'Label for the order total amount',\n },\n totalAmount: {\n id: 'checkout.paymentForm.totalAmount',\n defaultMessage: '${amount} {currency}',\n description: 'Formatted order total with currency code e.g. $219.00 USD',\n },\n\n // Submit button\n payNow: {\n id: 'checkout.paymentForm.payNow',\n defaultMessage: 'Pay now',\n description: 'Submit button label',\n },\n country: {\n id: 'checkout.paymentForm.country',\n defaultMessage: 'Country',\n description: 'Country selector label',\n },\n countryPlaceholder: {\n id: 'checkout.paymentForm.countryPlaceholder',\n defaultMessage: 'Select your country',\n description: 'Placeholder option shown before a country is selected',\n },\n});\n\nexport default messages;\n"]}
|
|
@@ -24,5 +24,5 @@ export interface PaymentFormProps {
|
|
|
24
24
|
monthlyRegularAmount?: string;
|
|
25
25
|
geolocationUrl?: string;
|
|
26
26
|
}
|
|
27
|
-
declare const PaymentForm: ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError,
|
|
27
|
+
declare const PaymentForm: ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, }: PaymentFormProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
28
|
export default PaymentForm;
|
|
@@ -1,121 +1,25 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { useIntl, getAppConfig } from '@openedx/frontend-base';
|
|
2
|
+
import { Button, Form } from '@openedx/paragon';
|
|
3
|
+
import { useIntl } from '@openedx/frontend-base';
|
|
5
4
|
import PaymentFields from '../PaymentFields/PaymentFields';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
5
|
+
import ExpressCheckout from '../ExpressCheckout/ExpressCheckout';
|
|
6
|
+
import { BILLING_COUNTRIES } from '../../constants';
|
|
8
7
|
import messages from './Messages';
|
|
9
|
-
const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError,
|
|
10
|
-
var _a, _b;
|
|
8
|
+
const PaymentForm = ({ billing, setField, numberMountRef, expiryMountRef, cvcMountRef, cardError, }) => {
|
|
11
9
|
const { formatMessage } = useIntl();
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (!geolocationUrl)
|
|
27
|
-
return;
|
|
28
|
-
void fetchPublicIp()
|
|
29
|
-
.then((ipAddress) => fetchIpGeolocation(geolocationUrl, ipAddress))
|
|
30
|
-
.then((geolocation) => {
|
|
31
|
-
var _a;
|
|
32
|
-
const countryCode = (_a = geolocation.country_code) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
33
|
-
if (countryCode && BILLING_COUNTRIES.some(([code]) => code === countryCode)) {
|
|
34
|
-
setField('country', countryCode);
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
.catch(() => undefined);
|
|
38
|
-
}, [geolocationUrl, setField]);
|
|
39
|
-
const needsStripe = paymentMethod !== 'paypal';
|
|
40
|
-
const busy = submitting || (needsStripe && !stripeReady) || !sessionReady;
|
|
41
|
-
let buttonLabel = paymentMethod === 'paypal'
|
|
42
|
-
? formatMessage(messages.continueWithPaypal)
|
|
43
|
-
: formatMessage(messages.confirmSubscription);
|
|
44
|
-
if (submitting)
|
|
45
|
-
buttonLabel = formatMessage(messages.processing);
|
|
46
|
-
else if (!sessionReady || (needsStripe && !stripeReady))
|
|
47
|
-
buttonLabel = formatMessage(messages.loadingPayment);
|
|
48
|
-
const isMonthly = cycleToShow === 'monthly';
|
|
49
|
-
const frequency = cycleToShow === 'annual' ? 'year' : 'month';
|
|
50
|
-
const trialDays = 7;
|
|
51
|
-
const pricing = isMonthly
|
|
52
|
-
? formatMessage(messages.termsPricingMonthly, {
|
|
53
|
-
promoAmount,
|
|
54
|
-
promoMonths,
|
|
55
|
-
regularAmount: monthlyRegularAmount,
|
|
56
|
-
})
|
|
57
|
-
: formatMessage(messages.termsPricingAnnual, {
|
|
58
|
-
amount: (_a = priceToShow === null || priceToShow === void 0 ? void 0 : priceToShow.amount) !== null && _a !== void 0 ? _a : '',
|
|
59
|
-
frequency,
|
|
60
|
-
});
|
|
61
|
-
const recurringConfirmText = isMonthly
|
|
62
|
-
? formatMessage(messages.recurringConfirmMonthly, {
|
|
63
|
-
promoAmount,
|
|
64
|
-
promoMonths,
|
|
65
|
-
regularAmount: monthlyRegularAmount,
|
|
66
|
-
})
|
|
67
|
-
: formatMessage(messages.recurringConfirmAnnual, {
|
|
68
|
-
amount: (_b = priceToShow === null || priceToShow === void 0 ? void 0 : priceToShow.amount) !== null && _b !== void 0 ? _b : '',
|
|
69
|
-
});
|
|
70
|
-
const termsNoticeValues = {
|
|
71
|
-
pricing,
|
|
72
|
-
termsLink: formatMessage(messages.termsOfUse),
|
|
73
|
-
refundLink: formatMessage(messages.refundPolicy),
|
|
74
|
-
};
|
|
75
|
-
const termsText = isMonthly
|
|
76
|
-
? formatMessage(messages.termsNotice, Object.assign(Object.assign({}, termsNoticeValues), { trialDays, date: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}' }))
|
|
77
|
-
: formatMessage(messages.termsNoticeAnnual, termsNoticeValues);
|
|
78
|
-
const buildConsent = () => {
|
|
79
|
-
const consentParts = [termsText, recurringConfirmText];
|
|
80
|
-
if (showExtraConfirm) {
|
|
81
|
-
consentParts.push(formatMessage(extraConfirmMessage));
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
tConsentRecurring: confirmed,
|
|
85
|
-
tConsentUkCa: showExtraConfirm ? extraConfirmed : null,
|
|
86
|
-
tConsentAt: new Date().toISOString(),
|
|
87
|
-
tConsentText: consentParts.join('\n\n'),
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
return (_jsxs("div", { className: "payment-form bg-white", children: [_jsx("h2", { className: "payment-form__heading font-weight-bold mb-3 text-primary-500", children: formatMessage(messages.selectPaymentMethod) }), _jsxs("p", { className: "payment-form__help small mb-4", children: [_jsx("strong", { className: "d-block text-primary-500", children: formatMessage(messages.needAssistance) }), ' ', _jsx("span", { className: "text-gray-700", children: formatMessage(messages.needAssistanceBody, {
|
|
91
|
-
link: (_jsx("a", { href: "https://support.edx.org", target: "_blank", rel: "noreferrer", className: "text-gray-700", children: formatMessage(messages.learnerHelpCenter) })),
|
|
92
|
-
}) })] }), _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) => {
|
|
93
|
-
const selectedCountry = e.target.value;
|
|
94
|
-
setField('country', selectedCountry);
|
|
95
|
-
setExtraConfirmed(false);
|
|
96
|
-
}, children: BILLING_COUNTRIES.map((country) => {
|
|
97
|
-
return (_jsx("option", { value: country[0], children: country[1] }, country[0]));
|
|
98
|
-
}) })] })] })] }), _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: isMonthly
|
|
99
|
-
? formatMessage(messages.termsNotice, {
|
|
100
|
-
trialDays,
|
|
101
|
-
date: trialEnd !== null && trialEnd !== void 0 ? trialEnd : '{date}',
|
|
102
|
-
pricing,
|
|
103
|
-
termsLink: (_jsx("a", { className: "text-gray-700", href: tosUrl, children: formatMessage(messages.termsOfUse) })),
|
|
104
|
-
refundLink: (_jsx("a", { className: "text-gray-700", href: refundPolicyUrl, children: formatMessage(messages.refundPolicy) })),
|
|
105
|
-
})
|
|
106
|
-
: formatMessage(messages.termsNoticeAnnual, {
|
|
107
|
-
pricing,
|
|
108
|
-
termsLink: (_jsx("a", { className: "text-gray-700", href: tosUrl, children: formatMessage(messages.termsOfUse) })),
|
|
109
|
-
refundLink: (_jsx("a", { className: "text-gray-700", href: refundPolicyUrl, children: formatMessage(messages.refundPolicy) })),
|
|
110
|
-
}) }), _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: extraConfirmId, className: "mb-4 payment-form__confirm", children: _jsx(Form.Checkbox, { id: extraConfirmId, checked: extraConfirmed, onChange: (e) => setExtraConfirmed(e.target.checked), children: _jsx("span", { className: "text-gray-700 payment-form__confirm-label", children: formatMessage(extraConfirmMessage) }) }) })), _jsxs(Button, { variant: "brand", className: "payment-form__submit", onClick: () => {
|
|
111
|
-
if (paymentMethod !== 'googlepay') {
|
|
112
|
-
onPlaceOrder(buildConsent(), paymentMethod);
|
|
113
|
-
}
|
|
114
|
-
}, disabled: (needsStripe && !stripeReady)
|
|
115
|
-
|| submitting
|
|
116
|
-
|| !confirmed
|
|
117
|
-
|| paymentMethod === 'googlepay'
|
|
118
|
-
|| (showExtraConfirm && !extraConfirmed), children: [busy && (_jsx(Spinner, { animation: "border", size: "sm", className: "mr-2", screenReaderText: formatMessage(messages.spinnerScreenReaderText) })), buttonLabel] })] }));
|
|
10
|
+
// TODO: replace with the real order total and currency once wired to checkout state.
|
|
11
|
+
const totalAmount = '219.00';
|
|
12
|
+
const totalCurrency = 'USD';
|
|
13
|
+
return (_jsxs("div", { className: "payment-form bg-white", children: [_jsxs("div", { children: [_jsx("h2", { className: "payment-form__heading font-weight-bold mb-3 text-primary-500", children: formatMessage(messages.selectPaymentMethod) }), _jsxs("p", { className: "payment-form__help small mb-0", children: [_jsx("strong", { className: "d-block text-primary-500", children: formatMessage(messages.needAssistance) }), ' ', _jsx("span", { className: "text-gray-700 gap-y-2", children: formatMessage(messages.needAssistanceBody, {
|
|
14
|
+
link: (_jsx("a", { href: "https://support.edx.org", target: "_blank", rel: "noreferrer", className: "text-gray-700", children: formatMessage(messages.learnerHelpCenter) })),
|
|
15
|
+
}) })] })] }), _jsx(ExpressCheckout, {}), _jsx("div", { className: "payment-form__methods", children: _jsx("div", { className: "payment-form__method payment-form__method--selected", children: _jsxs("div", { className: "payment-form__card-panel", children: [_jsx("h3", { className: "payment-form__card-heading font-weight-bold text-center text-primary-500 mb-3", children: formatMessage(messages.payWithCard) }), _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: "payment--field__label text-gray-900", children: formatMessage(messages.country) }), _jsxs(Form.Control, { as: "select", value: billing.country, onChange: (e) => {
|
|
16
|
+
setField('country', e.target.value);
|
|
17
|
+
}, children: [_jsx("option", { value: "", disabled: true, hidden: true, children: formatMessage(messages.countryPlaceholder) }), BILLING_COUNTRIES.map((country) => {
|
|
18
|
+
return (_jsx("option", { value: country[0], children: country[1] }, country[0]));
|
|
19
|
+
})] })] })] }) }) }), _jsxs("div", { className: "payment-form__total", children: [_jsx("p", { className: "payment-form__total-disclaimer text-gray-700 mb-3", children: formatMessage(messages.orderDisclaimer) }), _jsxs("div", { className: "payment-form__total-row", children: [_jsxs("p", { className: "mb-0 text-gray-900", children: [_jsx("strong", { className: "payment-form__total-label", children: formatMessage(messages.total) }), ' ', _jsx("span", { className: "payment-form__total-value", children: formatMessage(messages.totalAmount, {
|
|
20
|
+
amount: totalAmount,
|
|
21
|
+
currency: totalCurrency,
|
|
22
|
+
}) })] }), _jsx(Button, { variant: "brand", className: "payment-form__submit", children: formatMessage(messages.payNow) })] })] })] }));
|
|
119
23
|
};
|
|
120
24
|
export default PaymentForm;
|
|
121
25
|
//# sourceMappingURL=PaymentForm.js.map
|
|
@@ -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';\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 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 from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport ExpressCheckout from '../ExpressCheckout/ExpressCheckout';\nimport type { BillingInfo, CheckoutConsent, SupportedPaymentMethod } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport { BILLING_COUNTRIES } from '../../constants';\nimport messages from './Messages';\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}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n\n // TODO: replace with the real order total and currency once wired to checkout state.\n const totalAmount = '219.00';\n const totalCurrency = 'USD';\n\n return (\n <div className=\"payment-form bg-white\">\n <div>\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-0\">\n <strong className=\"d-block text-primary-500\">\n {formatMessage(messages.needAssistance)}\n </strong>{' '}\n <span className=\"text-gray-700 gap-y-2\">\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 </div>\n\n <ExpressCheckout />\n\n {/* ── Payment method ── */}\n <div className=\"payment-form__methods\">\n <div className=\"payment-form__method payment-form__method--selected\">\n <div className=\"payment-form__card-panel\">\n <h3 className=\"payment-form__card-heading font-weight-bold text-center text-primary-500 mb-3\">\n {formatMessage(messages.payWithCard)}\n </h3>\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=\"payment--field__label text-gray-900\">\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 >\n <option value=\"\" disabled hidden>\n {formatMessage(messages.countryPlaceholder)}\n </option>\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 </div>\n\n {/* ── Order total ── */}\n <div className=\"payment-form__total\">\n <p className=\"payment-form__total-disclaimer text-gray-700 mb-3\">\n {formatMessage(messages.orderDisclaimer)}\n </p>\n <div className=\"payment-form__total-row\">\n <p className=\"mb-0 text-gray-900\">\n <strong className=\"payment-form__total-label\">{formatMessage(messages.total)}</strong>{' '}\n <span className=\"payment-form__total-value\">\n {formatMessage(messages.totalAmount, {\n amount: totalAmount,\n currency: totalCurrency,\n })}\n </span>\n </p>\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n >\n {formatMessage(messages.payNow)}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default PaymentForm;\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare const messages: {
|
|
2
|
+
banner: {
|
|
3
|
+
id: string;
|
|
4
|
+
defaultMessage: string;
|
|
5
|
+
description: string;
|
|
6
|
+
};
|
|
7
|
+
bannerInfo: {
|
|
8
|
+
id: string;
|
|
9
|
+
defaultMessage: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
placeholder: {
|
|
13
|
+
id: string;
|
|
14
|
+
defaultMessage: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
inputLabel: {
|
|
18
|
+
id: string;
|
|
19
|
+
defaultMessage: string;
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
apply: {
|
|
23
|
+
id: string;
|
|
24
|
+
defaultMessage: string;
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export default messages;
|