@edx/frontend-app-subscription-manage 1.3.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +2 -2
- package/dist/app.js.map +1 -1
- package/dist/components/ActiveSubscription/ActiveSubscription.d.ts +7 -0
- package/dist/components/ActiveSubscription/ActiveSubscription.js +24 -0
- package/dist/components/ActiveSubscription/ActiveSubscription.js.map +1 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.d.ts +7 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.js +19 -0
- package/dist/components/BecomeSubscriber/BecomeSubscriber.js.map +1 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.d.ts +12 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.js +21 -0
- package/dist/components/CancelConfirmation/CancelConfirmation.js.map +1 -0
- package/dist/components/CancelSuccess/CancelSuccess.d.ts +7 -0
- package/dist/components/CancelSuccess/CancelSuccess.js +17 -0
- package/dist/components/CancelSuccess/CancelSuccess.js.map +1 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.d.ts +13 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.js +27 -0
- package/dist/components/CanceledSubscription/CanceledSubscription.js.map +1 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.d.ts +8 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.js +19 -0
- package/dist/components/EnrolledCoursesList/EnrolledCoursesList.js.map +1 -0
- package/dist/components/HelpFooter/HelpFooter.d.ts +3 -0
- package/dist/components/HelpFooter/HelpFooter.js +12 -0
- package/dist/components/HelpFooter/HelpFooter.js.map +1 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.d.ts +3 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.js +9 -0
- package/dist/components/OrderHistoryHeader/OrderHistoryHeader.js.map +1 -0
- package/dist/components/PaymentHistory/PaymentHistory.d.ts +10 -0
- package/dist/components/PaymentHistory/PaymentHistory.js +23 -0
- package/dist/components/PaymentHistory/PaymentHistory.js.map +1 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.d.ts +17 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.js +63 -0
- package/dist/components/RenewSubscriptionModal/RenewSubscriptionModal.js.map +1 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.d.ts +9 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.js +25 -0
- package/dist/components/ResubscribeCard/ResubscribeCard.js.map +1 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.d.ts +8 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.js +9 -0
- package/dist/components/SubscriptionTabs/SubscriptionTabs.js.map +1 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.d.ts +9 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.js +135 -0
- package/dist/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.js.map +1 -0
- package/dist/components/messages.d.ts +473 -0
- package/dist/components/messages.js +482 -0
- package/dist/components/messages.js.map +1 -0
- package/dist/constants.d.ts +14 -56
- package/dist/constants.js +23 -272
- package/dist/constants.js.map +1 -1
- package/dist/data/hooks/keys.d.ts +8 -13
- package/dist/data/hooks/keys.js +8 -13
- package/dist/data/hooks/keys.js.map +1 -1
- package/dist/data/hooks/useManageQueries.d.ts +37 -0
- package/dist/data/hooks/useManageQueries.js +206 -0
- package/dist/data/hooks/useManageQueries.js.map +1 -0
- package/dist/data/services/subs/urls.d.ts +2 -2
- package/dist/data/services/subs/urls.js.map +1 -1
- package/dist/data/services/subscription/cancelSubscription.d.ts +6 -0
- package/dist/data/services/subscription/cancelSubscription.js +31 -0
- package/dist/data/services/subscription/cancelSubscription.js.map +1 -0
- package/dist/data/services/subscription/getBillingPlans.d.ts +3 -0
- package/dist/{utils/fetchBillingPlans.js → data/services/subscription/getBillingPlans.js} +10 -21
- package/dist/data/services/subscription/getBillingPlans.js.map +1 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.d.ts +3 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.js +37 -0
- package/dist/data/services/subscription/getIsCurrentUserSubscriber.js.map +1 -0
- package/dist/data/services/subscription/getPaymentHistory.d.ts +6 -0
- package/dist/data/services/subscription/getPaymentHistory.js +65 -0
- package/dist/data/services/subscription/getPaymentHistory.js.map +1 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.d.ts +7 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.js +88 -0
- package/dist/data/services/subscription/getSubscriptionEnrollments.js.map +1 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.d.ts +8 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.js +42 -0
- package/dist/data/services/subscription/getSubscriptionPaymentMethod.js.map +1 -0
- package/dist/data/services/subscription/reactivateSubscription.d.ts +6 -0
- package/dist/data/services/subscription/reactivateSubscription.js +30 -0
- package/dist/data/services/subscription/reactivateSubscription.js.map +1 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.d.ts +10 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.js +31 -0
- package/dist/data/services/subscription/updateSubscriptionPaymentMethod.js.map +1 -0
- package/dist/icons/ExternalLinkIcon.d.ts +6 -0
- package/dist/icons/ExternalLinkIcon.js +18 -0
- package/dist/icons/ExternalLinkIcon.js.map +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +2 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.js +53 -0
- package/dist/manageSubscriptionPage/CancelSubscriptionPage.js.map +1 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.js +24 -0
- package/dist/manageSubscriptionPage/CancelSuccessPage.js.map +1 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.d.ts +3 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.js +87 -0
- package/dist/manageSubscriptionPage/ManageSubscriptionPage.js.map +1 -0
- package/dist/messages.js +2 -2
- package/dist/messages.js.map +1 -1
- package/dist/routes.d.ts +9 -2
- package/dist/routes.js +26 -6
- package/dist/routes.js.map +1 -1
- package/dist/style.scss +1 -14
- package/dist/styles/components/manageSubscription.scss +454 -0
- package/dist/types.d.ts +61 -201
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/billingDetails.d.ts +3 -20
- package/dist/utils/billingDetails.js +4 -25
- package/dist/utils/billingDetails.js.map +1 -1
- package/dist/utils/edxSession.d.ts +18 -0
- package/dist/utils/edxSession.js +72 -0
- package/dist/utils/edxSession.js.map +1 -0
- package/dist/utils/formatDate.d.ts +16 -0
- package/dist/utils/formatDate.js +69 -0
- package/dist/utils/formatDate.js.map +1 -0
- package/dist/utils/graphqlClient.d.ts +9 -10
- package/dist/utils/graphqlClient.js +22 -11
- package/dist/utils/graphqlClient.js.map +1 -1
- package/dist/utils/invoiceAmount.d.ts +22 -0
- package/dist/utils/invoiceAmount.js +59 -0
- package/dist/utils/invoiceAmount.js.map +1 -0
- package/dist/utils/queries.d.ts +38 -33
- package/dist/utils/queries.js +85 -123
- package/dist/utils/queries.js.map +1 -1
- package/dist/utils/subscriptionView.d.ts +15 -0
- package/dist/utils/subscriptionView.js +50 -0
- package/dist/utils/subscriptionView.js.map +1 -0
- package/dist/utils/urls.d.ts +20 -0
- package/dist/utils/urls.js +76 -0
- package/dist/utils/urls.js.map +1 -0
- package/package.json +7 -2
- package/dist/checkoutPage/CheckoutPage.d.ts +0 -3
- package/dist/checkoutPage/CheckoutPage.js +0 -30
- package/dist/checkoutPage/CheckoutPage.js.map +0 -1
- package/dist/components/BrandMarks/BrandMarks.d.ts +0 -3
- package/dist/components/BrandMarks/BrandMarks.js +0 -9
- package/dist/components/BrandMarks/BrandMarks.js.map +0 -1
- package/dist/components/CartSummary/CartSummary.d.ts +0 -21
- package/dist/components/CartSummary/CartSummary.js +0 -30
- package/dist/components/CartSummary/CartSummary.js.map +0 -1
- package/dist/components/CartSummary/Messages.d.ts +0 -73
- package/dist/components/CartSummary/Messages.js +0 -76
- package/dist/components/CartSummary/Messages.js.map +0 -1
- package/dist/components/Checkout/Checkout.d.ts +0 -4
- package/dist/components/Checkout/Checkout.js +0 -40
- package/dist/components/Checkout/Checkout.js.map +0 -1
- package/dist/components/CheckoutGate/CheckoutGate.d.ts +0 -7
- package/dist/components/CheckoutGate/CheckoutGate.js +0 -35
- package/dist/components/CheckoutGate/CheckoutGate.js.map +0 -1
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.d.ts +0 -9
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js +0 -31
- package/dist/components/CourseEnrollmentCard/CourseEnrollmentCard.js.map +0 -1
- package/dist/components/CourseEnrollmentCard/Messages.d.ts +0 -33
- package/dist/components/CourseEnrollmentCard/Messages.js +0 -35
- package/dist/components/CourseEnrollmentCard/Messages.js.map +0 -1
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.d.ts +0 -13
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js +0 -11
- package/dist/components/EdxUnlimitedBanner/EdxUnlimitedBanner.js.map +0 -1
- package/dist/components/EnrollmentSummary/EnrollmentSummary.d.ts +0 -15
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js +0 -21
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +0 -1
- package/dist/components/EnrollmentSummary/Messages.d.ts +0 -33
- package/dist/components/EnrollmentSummary/Messages.js +0 -35
- package/dist/components/EnrollmentSummary/Messages.js.map +0 -1
- package/dist/components/PaymentFields/PaymentFields.d.ts +0 -9
- package/dist/components/PaymentFields/PaymentFields.js +0 -7
- package/dist/components/PaymentFields/PaymentFields.js.map +0 -1
- package/dist/components/PaymentForm/Messages.d.ts +0 -88
- package/dist/components/PaymentForm/Messages.js +0 -95
- package/dist/components/PaymentForm/Messages.js.map +0 -1
- package/dist/components/PaymentForm/PaymentForm.d.ts +0 -21
- package/dist/components/PaymentForm/PaymentForm.js +0 -69
- package/dist/components/PaymentForm/PaymentForm.js.map +0 -1
- package/dist/components/StatusScreens/Messages.d.ts +0 -103
- package/dist/components/StatusScreens/Messages.js +0 -108
- package/dist/components/StatusScreens/Messages.js.map +0 -1
- package/dist/components/StatusScreens/StatusScreens.d.ts +0 -23
- package/dist/components/StatusScreens/StatusScreens.js +0 -25
- package/dist/components/StatusScreens/StatusScreens.js.map +0 -1
- package/dist/data/hooks/useCheckout.d.ts +0 -57
- package/dist/data/hooks/useCheckout.js +0 -249
- package/dist/data/hooks/useCheckout.js.map +0 -1
- package/dist/data/hooks/useCheckoutGate.d.ts +0 -15
- package/dist/data/hooks/useCheckoutGate.js +0 -39
- package/dist/data/hooks/useCheckoutGate.js.map +0 -1
- package/dist/data/hooks/useCheckoutMutations.d.ts +0 -16
- package/dist/data/hooks/useCheckoutMutations.js +0 -131
- package/dist/data/hooks/useCheckoutMutations.js.map +0 -1
- package/dist/data/hooks/useCheckoutQueries.d.ts +0 -30
- package/dist/data/hooks/useCheckoutQueries.js +0 -97
- package/dist/data/hooks/useCheckoutQueries.js.map +0 -1
- package/dist/styles/components/brandMarks.scss +0 -54
- package/dist/styles/components/cartSummary.scss +0 -18
- package/dist/styles/components/checkout.scss +0 -29
- package/dist/styles/components/checkoutStepper.scss +0 -9
- package/dist/styles/components/courseEnrollmentCard.scss +0 -38
- package/dist/styles/components/edxUnlimitedBanner.scss +0 -138
- package/dist/styles/components/enrollmentSummary.scss +0 -13
- package/dist/styles/components/paymentFields.scss +0 -15
- package/dist/styles/components/paymentForm.scss +0 -105
- package/dist/styles/components/statusScreens.scss +0 -29
- package/dist/styles/components/successScreen.scss +0 -0
- package/dist/utils/auth.d.ts +0 -7
- package/dist/utils/auth.js +0 -28
- package/dist/utils/auth.js.map +0 -1
- package/dist/utils/bootstrapApi.d.ts +0 -20
- package/dist/utils/bootstrapApi.js +0 -142
- package/dist/utils/bootstrapApi.js.map +0 -1
- package/dist/utils/cartApi.d.ts +0 -16
- package/dist/utils/cartApi.js +0 -118
- package/dist/utils/cartApi.js.map +0 -1
- package/dist/utils/checkout.d.ts +0 -6
- package/dist/utils/checkout.js +0 -28
- package/dist/utils/checkout.js.map +0 -1
- package/dist/utils/fetchActiveSubscriptions.d.ts +0 -4
- package/dist/utils/fetchActiveSubscriptions.js +0 -36
- package/dist/utils/fetchActiveSubscriptions.js.map +0 -1
- package/dist/utils/fetchBillingPlans.d.ts +0 -2
- package/dist/utils/fetchBillingPlans.js.map +0 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.js +0 -17
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/provision.d.ts +0 -25
- package/dist/utils/provision.js +0 -95
- package/dist/utils/provision.js.map +0 -1
- package/dist/utils/stripe.d.ts +0 -7
- package/dist/utils/stripe.js +0 -43
- package/dist/utils/stripe.js.map +0 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@openedx/paragon';
|
|
3
|
+
import { useIntl } from '@openedx/frontend-base';
|
|
4
|
+
import { formatDisplayDate } from '../../utils/formatDate';
|
|
5
|
+
import { getCheckoutUrl } from '../../utils/urls';
|
|
6
|
+
import messages from '../messages';
|
|
7
|
+
const ResubscribeCard = ({ subscriber, price = null, currency = null, }) => {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
const { formatMessage } = useIntl();
|
|
10
|
+
const checkoutUrl = getCheckoutUrl();
|
|
11
|
+
const canceledOn = formatDisplayDate((_b = (_a = subscriber === null || subscriber === void 0 ? void 0 : subscriber.canceledAt) !== null && _a !== void 0 ? _a : subscriber === null || subscriber === void 0 ? void 0 : subscriber.subscriptionEndDate) !== null && _b !== void 0 ? _b : subscriber === null || subscriber === void 0 ? void 0 : subscriber.currentPeriodEnd);
|
|
12
|
+
const displayPrice = (subscriber === null || subscriber === void 0 ? void 0 : subscriber.amount) || price || null;
|
|
13
|
+
const displayCurrency = (subscriber === null || subscriber === void 0 ? void 0 : subscriber.currency) || currency || null;
|
|
14
|
+
const hasPrice = Boolean(displayPrice);
|
|
15
|
+
return (_jsxs("section", { className: "manage-section mt-4", children: [_jsx("h2", { className: "manage-section__title h3 font-weight-bold text-primary-500 mb-1", children: formatMessage(messages['manage.expired.heading']) }), _jsx("p", { className: "manage-section__subtitle text-gray-700 mb-3", children: formatMessage(messages['manage.expired.subheading']) }), _jsxs("div", { className: "manage-card d-flex flex-column flex-md-row align-items-md-center justify-content-md-between bg-white border p-4 rounded", children: [_jsxs("div", { className: "manage-card__content", children: [_jsx("h3", { className: "manage-card__title font-weight-bold text-primary-500 mb-1", children: hasPrice
|
|
16
|
+
? formatMessage(messages['manage.expired.resubscribeTitle'], {
|
|
17
|
+
price: displayPrice,
|
|
18
|
+
currency: displayCurrency !== null && displayCurrency !== void 0 ? displayCurrency : '',
|
|
19
|
+
})
|
|
20
|
+
: formatMessage(messages['manage.expired.resubscribeTitleNoPrice']) }), _jsx("p", { className: "manage-card__body text-gray-700 mb-0", children: canceledOn
|
|
21
|
+
? formatMessage(messages['manage.expired.canceledOn'], { date: canceledOn })
|
|
22
|
+
: formatMessage(messages['manage.expired.canceledOnNoDate']) })] }), _jsx("div", { className: "manage-card__actions d-flex flex-wrap align-items-center flex-shrink-0", children: _jsx(Button, { className: "manage-btn manage-btn--brand", href: checkoutUrl, children: formatMessage(messages['manage.canceled.renew']) }) })] })] }));
|
|
23
|
+
};
|
|
24
|
+
export default ResubscribeCard;
|
|
25
|
+
//# sourceMappingURL=ResubscribeCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResubscribeCard.js","sourceRoot":"","sources":["../../../src/components/ResubscribeCard/ResubscribeCard.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,QAAQ,MAAM,aAAa,CAAC;AAQnC,MAAM,eAAe,GAAmC,CAAC,EACvD,UAAU,EACV,KAAK,GAAG,IAAI,EACZ,QAAQ,GAAG,IAAI,GAChB,EAAE,EAAE;;IACH,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,iBAAiB,CAClC,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,mCAAI,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,mBAAmB,mCAAI,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,gBAAgB,CAC1F,CAAC;IACF,MAAM,YAAY,GAAG,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,MAAM,KAAI,KAAK,IAAI,IAAI,CAAC;IACzD,MAAM,eAAe,GAAG,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,QAAQ,KAAI,QAAQ,IAAI,IAAI,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAEvC,OAAO,CACL,mBAAS,SAAS,EAAC,qBAAqB,aACtC,aAAI,SAAS,EAAC,iEAAiE,YAC5E,aAAa,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,GAC/C,EACL,YAAG,SAAS,EAAC,6CAA6C,YACvD,aAAa,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,GACnD,EAEJ,eAAK,SAAS,EAAC,yHAAyH,aACtI,eAAK,SAAS,EAAC,sBAAsB,aACnC,aAAI,SAAS,EAAC,2DAA2D,YACtE,QAAQ;oCACP,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,iCAAiC,CAAC,EAAE;wCACzD,KAAK,EAAE,YAAY;wCACnB,QAAQ,EAAE,eAAe,aAAf,eAAe,cAAf,eAAe,GAAI,EAAE;qCAChC,CAAC;oCACJ,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,wCAAwC,CAAC,CAAC,GAClE,EACL,YAAG,SAAS,EAAC,sCAAsC,YAChD,UAAU;oCACT,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,2BAA2B,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;oCAC5E,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC,GAC5D,IACA,EACN,cAAK,SAAS,EAAC,wEAAwE,YACrF,KAAC,MAAM,IAAC,SAAS,EAAC,8BAA8B,EAAC,IAAI,EAAE,WAAW,YAC/D,aAAa,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,GAC1C,GACL,IACF,IACE,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC","sourcesContent":["import React from 'react';\nimport { Button } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\n\nimport type { CurrentUserSubscriberResult } from '../../types';\nimport { formatDisplayDate } from '../../utils/formatDate';\nimport { getCheckoutUrl } from '../../utils/urls';\nimport messages from '../messages';\n\ninterface ResubscribeCardProps {\n subscriber: CurrentUserSubscriberResult | null,\n price?: string | null,\n currency?: string | null,\n}\n\nconst ResubscribeCard: React.FC<ResubscribeCardProps> = ({\n subscriber,\n price = null,\n currency = null,\n}) => {\n const { formatMessage } = useIntl();\n const checkoutUrl = getCheckoutUrl();\n const canceledOn = formatDisplayDate(\n subscriber?.canceledAt ?? subscriber?.subscriptionEndDate ?? subscriber?.currentPeriodEnd,\n );\n const displayPrice = subscriber?.amount || price || null;\n const displayCurrency = subscriber?.currency || currency || null;\n const hasPrice = Boolean(displayPrice);\n\n return (\n <section className=\"manage-section mt-4\">\n <h2 className=\"manage-section__title h3 font-weight-bold text-primary-500 mb-1\">\n {formatMessage(messages['manage.expired.heading'])}\n </h2>\n <p className=\"manage-section__subtitle text-gray-700 mb-3\">\n {formatMessage(messages['manage.expired.subheading'])}\n </p>\n\n <div className=\"manage-card d-flex flex-column flex-md-row align-items-md-center justify-content-md-between bg-white border p-4 rounded\">\n <div className=\"manage-card__content\">\n <h3 className=\"manage-card__title font-weight-bold text-primary-500 mb-1\">\n {hasPrice\n ? formatMessage(messages['manage.expired.resubscribeTitle'], {\n price: displayPrice,\n currency: displayCurrency ?? '',\n })\n : formatMessage(messages['manage.expired.resubscribeTitleNoPrice'])}\n </h3>\n <p className=\"manage-card__body text-gray-700 mb-0\">\n {canceledOn\n ? formatMessage(messages['manage.expired.canceledOn'], { date: canceledOn })\n : formatMessage(messages['manage.expired.canceledOnNoDate'])}\n </p>\n </div>\n <div className=\"manage-card__actions d-flex flex-wrap align-items-center flex-shrink-0\">\n <Button className=\"manage-btn manage-btn--brand\" href={checkoutUrl}>\n {formatMessage(messages['manage.canceled.renew'])}\n </Button>\n </div>\n </div>\n </section>\n );\n};\n\nexport default ResubscribeCard;\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ManageTab } from '../../types';
|
|
3
|
+
interface SubscriptionTabsProps {
|
|
4
|
+
activeTab: ManageTab;
|
|
5
|
+
onChange: (tab: ManageTab) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const SubscriptionTabs: React.FC<SubscriptionTabsProps>;
|
|
8
|
+
export default SubscriptionTabs;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useIntl } from '@openedx/frontend-base';
|
|
3
|
+
import messages from '../messages';
|
|
4
|
+
const SubscriptionTabs = ({ activeTab, onChange }) => {
|
|
5
|
+
const { formatMessage } = useIntl();
|
|
6
|
+
return (_jsxs("div", { className: "manage-tabs d-flex border-bottom mt-4", role: "tablist", "aria-label": formatMessage(messages['manage.header.title']), children: [_jsx("button", { type: "button", role: "tab", id: "manage-tab-subscription", "aria-selected": activeTab === 'subscription', "aria-controls": "manage-tabpanel-subscription", className: `manage-tabs__tab${activeTab === 'subscription' ? ' manage-tabs__tab--active' : ''}`, onClick: () => onChange('subscription'), children: formatMessage(messages['manage.tab.subscription']) }), _jsx("button", { type: "button", role: "tab", id: "manage-tab-payment-history", "aria-selected": activeTab === 'payment-history', "aria-controls": "manage-tabpanel-payment-history", className: `manage-tabs__tab${activeTab === 'payment-history' ? ' manage-tabs__tab--active' : ''}`, onClick: () => onChange('payment-history'), children: formatMessage(messages['manage.tab.paymentHistory']) })] }));
|
|
7
|
+
};
|
|
8
|
+
export default SubscriptionTabs;
|
|
9
|
+
//# sourceMappingURL=SubscriptionTabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscriptionTabs.js","sourceRoot":"","sources":["../../../src/components/SubscriptionTabs/SubscriptionTabs.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,QAAQ,MAAM,aAAa,CAAC;AAOnC,MAAM,gBAAgB,GAAoC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;IACpF,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IAEpC,OAAO,CACL,eACE,SAAS,EAAC,uCAAuC,EACjD,IAAI,EAAC,SAAS,gBACF,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,aAE1D,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,KAAK,EACV,EAAE,EAAC,yBAAyB,mBACb,SAAS,KAAK,cAAc,mBAC7B,8BAA8B,EAC5C,SAAS,EAAE,mBAAmB,SAAS,KAAK,cAAc,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,EAAE,EAAE,EAC/F,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,YAEtC,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,GAC5C,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,KAAK,EACV,EAAE,EAAC,4BAA4B,mBAChB,SAAS,KAAK,iBAAiB,mBAChC,iCAAiC,EAC/C,SAAS,EAAE,mBAAmB,SAAS,KAAK,iBAAiB,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,EAAE,EAAE,EAClG,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,YAEzC,aAAa,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,GAC9C,IACL,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["import React from 'react';\nimport { useIntl } from '@openedx/frontend-base';\n\nimport type { ManageTab } from '../../types';\nimport messages from '../messages';\n\ninterface SubscriptionTabsProps {\n activeTab: ManageTab,\n onChange: (tab: ManageTab) => void,\n}\n\nconst SubscriptionTabs: React.FC<SubscriptionTabsProps> = ({ activeTab, onChange }) => {\n const { formatMessage } = useIntl();\n\n return (\n <div\n className=\"manage-tabs d-flex border-bottom mt-4\"\n role=\"tablist\"\n aria-label={formatMessage(messages['manage.header.title'])}\n >\n <button\n type=\"button\"\n role=\"tab\"\n id=\"manage-tab-subscription\"\n aria-selected={activeTab === 'subscription'}\n aria-controls=\"manage-tabpanel-subscription\"\n className={`manage-tabs__tab${activeTab === 'subscription' ? ' manage-tabs__tab--active' : ''}`}\n onClick={() => onChange('subscription')}\n >\n {formatMessage(messages['manage.tab.subscription'])}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n id=\"manage-tab-payment-history\"\n aria-selected={activeTab === 'payment-history'}\n aria-controls=\"manage-tabpanel-payment-history\"\n className={`manage-tabs__tab${activeTab === 'payment-history' ? ' manage-tabs__tab--active' : ''}`}\n onClick={() => onChange('payment-history')}\n >\n {formatMessage(messages['manage.tab.paymentHistory'])}\n </button>\n </div>\n );\n};\n\nexport default SubscriptionTabs;\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface UpdatePaymentMethodModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
subscriptionBiId: string | null | undefined;
|
|
6
|
+
nextBillingDate: string | null;
|
|
7
|
+
}
|
|
8
|
+
declare const UpdatePaymentMethodModal: React.FC<UpdatePaymentMethodModalProps>;
|
|
9
|
+
export default UpdatePaymentMethodModal;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { useCallback, useEffect, useMemo, useState, } from 'react';
|
|
12
|
+
import { Alert, Form, ModalDialog, Button, ActionRow, Icon, } from '@openedx/paragon';
|
|
13
|
+
import { getAppConfig, useIntl } from '@openedx/frontend-base';
|
|
14
|
+
import { CreditCard } from '@openedx/paragon/icons';
|
|
15
|
+
import { Elements, CardNumberElement, CardCvcElement, CardExpiryElement, useElements, useStripe, } from '@stripe/react-stripe-js';
|
|
16
|
+
import { loadStripe } from '@stripe/stripe-js';
|
|
17
|
+
import { appId } from '../../constants';
|
|
18
|
+
import { useUpdatePaymentMethodMutation, useViaxClient, } from '../../data/hooks/useManageQueries';
|
|
19
|
+
import messages from '../messages';
|
|
20
|
+
const ELEMENT_STYLE = {
|
|
21
|
+
base: {
|
|
22
|
+
color: '#00262b',
|
|
23
|
+
fontSize: '16px',
|
|
24
|
+
lineHeight: '24px',
|
|
25
|
+
fontFamily: '"Open Sans", "Helvetica Neue", Arial, sans-serif',
|
|
26
|
+
fontSmoothing: 'antialiased',
|
|
27
|
+
'::placeholder': {
|
|
28
|
+
color: '#707070',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
invalid: {
|
|
32
|
+
color: '#b91c1c',
|
|
33
|
+
iconColor: '#b91c1c',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const PaymentForm = ({ subscriptionBiId, onClose, onSuccess, }) => {
|
|
37
|
+
const { formatMessage } = useIntl();
|
|
38
|
+
const stripe = useStripe();
|
|
39
|
+
const elements = useElements();
|
|
40
|
+
const client = useViaxClient();
|
|
41
|
+
const updateMutation = useUpdatePaymentMethodMutation(client);
|
|
42
|
+
const [postalCode, setPostalCode] = useState('');
|
|
43
|
+
const [cardError, setCardError] = useState(null);
|
|
44
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
45
|
+
const handleSubmit = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
setCardError(null);
|
|
48
|
+
if (!stripe || !elements) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const cardNumber = elements.getElement(CardNumberElement);
|
|
52
|
+
if (!cardNumber) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const trimmedPostal = postalCode.trim();
|
|
56
|
+
if (!trimmedPostal) {
|
|
57
|
+
setCardError(formatMessage(messages['manage.updatePayment.postalRequired']));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
setIsSubmitting(true);
|
|
61
|
+
try {
|
|
62
|
+
const { error, paymentMethod } = yield stripe.createPaymentMethod({
|
|
63
|
+
type: 'card',
|
|
64
|
+
card: cardNumber,
|
|
65
|
+
billing_details: {
|
|
66
|
+
address: {
|
|
67
|
+
postal_code: trimmedPostal,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
if (error || !(paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id)) {
|
|
72
|
+
setCardError((error === null || error === void 0 ? void 0 : error.message) || formatMessage(messages['manage.updatePayment.error']));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
yield updateMutation.mutateAsync({
|
|
76
|
+
biId: subscriptionBiId,
|
|
77
|
+
tStripePaymentMethodId: paymentMethod.id,
|
|
78
|
+
});
|
|
79
|
+
onSuccess();
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const message = err instanceof Error && err.message
|
|
83
|
+
? err.message
|
|
84
|
+
: formatMessage(messages['manage.updatePayment.error']);
|
|
85
|
+
setCardError(message);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
setIsSubmitting(false);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return (_jsxs("form", { className: "manage-update-payment", onSubmit: handleSubmit, children: [_jsx("p", { className: "manage-update-payment__intro text-primary-500 mb-4", children: formatMessage(messages['manage.updatePayment.intro']) }), _jsx("h3", { className: "manage-update-payment__section font-weight-bold text-primary-500 mb-3", children: formatMessage(messages['manage.updatePayment.sectionTitle']) }), _jsxs("div", { className: "manage-update-payment__row manage-update-payment__row--card mb-0", children: [_jsxs(Form.Group, { className: "manage-update-payment__field manage-update-payment__field--card-number mb-3", children: [_jsx(Form.Label, { className: "manage-update-payment__label d-block text-primary-500 mb-1", children: formatMessage(messages['manage.updatePayment.cardNumber']) }), _jsx("div", { className: "manage-update-payment__element bg-white d-flex align-items-center", children: _jsx(CardNumberElement, { options: {
|
|
92
|
+
style: ELEMENT_STYLE,
|
|
93
|
+
showIcon: true,
|
|
94
|
+
placeholder: '1234 1234 1234 1234',
|
|
95
|
+
} }) })] }), _jsxs(Form.Group, { className: "manage-update-payment__field manage-update-payment__field--cvc mb-3", children: [_jsx(Form.Label, { className: "manage-update-payment__label d-block text-primary-500 mb-1", children: formatMessage(messages['manage.updatePayment.cvc']) }), _jsxs("div", { className: "manage-update-payment__element manage-update-payment__element--cvc bg-white d-flex align-items-center", children: [_jsx(CardCvcElement, { options: { style: ELEMENT_STYLE, placeholder: 'CVC' } }), _jsx(Icon, { src: CreditCard, className: "manage-update-payment__cvc-icon", "aria-hidden": true })] })] }), _jsxs(Form.Group, { className: "manage-update-payment__field manage-update-payment__field--expiry mb-3", children: [_jsx(Form.Label, { className: "manage-update-payment__label d-block text-primary-500 mb-1", children: formatMessage(messages['manage.updatePayment.expiry']) }), _jsx("div", { className: "manage-update-payment__element bg-white d-flex align-items-center", children: _jsx(CardExpiryElement, { options: { style: ELEMENT_STYLE, placeholder: 'MM / YY' } }) })] })] }), _jsx("div", { className: "manage-update-payment__row manage-update-payment__row--postal mb-0", children: _jsxs(Form.Group, { className: "manage-update-payment__field manage-update-payment__field--postal mb-3", children: [_jsx(Form.Label, { className: "manage-update-payment__label d-block text-primary-500 mb-1", children: formatMessage(messages['manage.updatePayment.postal']) }), _jsx("div", { className: "manage-update-payment__element bg-white d-flex align-items-center", children: _jsx("input", { className: "manage-update-payment__control w-100 m-0 p-0 bg-transparent border-0", type: "text", name: "postal-code", value: postalCode, onChange: (e) => setPostalCode(e.target.value), autoComplete: "postal-code", required: true }) })] }) }), cardError && (_jsx(Alert, { variant: "danger", className: "mt-3 mb-0", children: cardError })), _jsxs(ActionRow, { className: "manage-update-payment__actions mt-4 w-100 justify-content-end flex-wrap flex-column-reverse flex-sm-row align-items-stretch align-items-sm-center", children: [_jsx(Button, { type: "button", variant: "tertiary", className: "w-100 w-sm-auto", onClick: onClose, disabled: isSubmitting, children: formatMessage(messages['manage.updatePayment.close']) }), _jsx(Button, { type: "submit", variant: "primary", className: "manage-btn manage-btn--dark w-100 w-sm-auto", disabled: !stripe || isSubmitting, children: isSubmitting
|
|
96
|
+
? formatMessage(messages['manage.updatePayment.submitting'])
|
|
97
|
+
: formatMessage(messages['manage.updatePayment.submit']) })] })] }));
|
|
98
|
+
};
|
|
99
|
+
const UpdatePaymentMethodModal = ({ isOpen, onClose, subscriptionBiId, nextBillingDate, }) => {
|
|
100
|
+
const { formatMessage } = useIntl();
|
|
101
|
+
const config = getAppConfig(appId);
|
|
102
|
+
const publishableKey = config.STRIPE_PUBLIC_KEY || '';
|
|
103
|
+
const [stripePromise, setStripePromise] = useState(null);
|
|
104
|
+
const [step, setStep] = useState('form');
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (!publishableKey) {
|
|
107
|
+
setStripePromise(null);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
setStripePromise(loadStripe(publishableKey));
|
|
111
|
+
}, [publishableKey]);
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (isOpen) {
|
|
114
|
+
setStep('form');
|
|
115
|
+
}
|
|
116
|
+
}, [isOpen]);
|
|
117
|
+
const handleClose = useCallback(() => {
|
|
118
|
+
setStep('form');
|
|
119
|
+
onClose();
|
|
120
|
+
}, [onClose]);
|
|
121
|
+
const title = step === 'success'
|
|
122
|
+
? formatMessage(messages['manage.updatePayment.successTitle'])
|
|
123
|
+
: formatMessage(messages['manage.updatePayment.title']);
|
|
124
|
+
const canShowForm = Boolean(publishableKey && subscriptionBiId && stripePromise);
|
|
125
|
+
const elementsOptions = useMemo(() => ({
|
|
126
|
+
fonts: [{ cssSrc: 'https://fonts.googleapis.com/css?family=Open+Sans' }],
|
|
127
|
+
}), []);
|
|
128
|
+
return (_jsxs(ModalDialog, { title: title, isOpen: isOpen, onClose: handleClose, size: "lg", hasCloseButton: true, isOverflowVisible: false, isFullscreenOnMobile: true, className: "manage-update-payment-modal", children: [_jsx(ModalDialog.Header, { children: _jsx(ModalDialog.Title, { children: title }) }), _jsx(ModalDialog.Body, { children: step === 'success' ? (_jsxs("div", { className: "manage-update-payment manage-update-payment--success", children: [_jsx("p", { className: "manage-update-payment__intro text-primary-500 mb-0", children: nextBillingDate
|
|
129
|
+
? formatMessage(messages['manage.updatePayment.successBody'], {
|
|
130
|
+
date: nextBillingDate,
|
|
131
|
+
})
|
|
132
|
+
: formatMessage(messages['manage.updatePayment.successBodyNoDate']) }), _jsx(ActionRow, { className: "manage-update-payment__actions mt-4 w-100 justify-content-end flex-wrap", children: _jsx(Button, { variant: "primary", className: "manage-btn manage-btn--dark", onClick: handleClose, children: formatMessage(messages['manage.updatePayment.close']) }) })] })) : !canShowForm ? (_jsx(Alert, { variant: "warning", children: formatMessage(messages['manage.updatePayment.stripeMissing']) })) : (_jsx(Elements, { stripe: stripePromise, options: elementsOptions, children: _jsx(PaymentForm, { subscriptionBiId: subscriptionBiId, onClose: handleClose, onSuccess: () => setStep('success') }) })) })] }));
|
|
133
|
+
};
|
|
134
|
+
export default UpdatePaymentMethodModal;
|
|
135
|
+
//# sourceMappingURL=UpdatePaymentMethodModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdatePaymentMethodModal.js","sourceRoot":"","sources":["../../../src/components/UpdatePaymentMethodModal/UpdatePaymentMethodModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Alert,\n Form,\n ModalDialog,\n Button,\n ActionRow,\n Icon,\n} from '@openedx/paragon';\nimport { getAppConfig, useIntl } from '@openedx/frontend-base';\nimport { CreditCard } from '@openedx/paragon/icons';\nimport {\n Elements,\n CardNumberElement,\n CardCvcElement,\n CardExpiryElement,\n useElements,\n useStripe,\n} from '@stripe/react-stripe-js';\nimport { loadStripe, type Stripe } from '@stripe/stripe-js';\n\nimport { appId } from '../../constants';\nimport {\n useUpdatePaymentMethodMutation,\n useViaxClient,\n} from '../../data/hooks/useManageQueries';\nimport messages from '../messages';\n\nconst ELEMENT_STYLE = {\n base: {\n color: '#00262b',\n fontSize: '16px',\n lineHeight: '24px',\n fontFamily: '\"Open Sans\", \"Helvetica Neue\", Arial, sans-serif',\n fontSmoothing: 'antialiased',\n '::placeholder': {\n color: '#707070',\n },\n },\n invalid: {\n color: '#b91c1c',\n iconColor: '#b91c1c',\n },\n};\n\ninterface UpdatePaymentMethodModalProps {\n isOpen: boolean,\n onClose: () => void,\n subscriptionBiId: string | null | undefined,\n nextBillingDate: string | null,\n}\n\ninterface PaymentFormProps {\n subscriptionBiId: string,\n onClose: () => void,\n onSuccess: () => void,\n}\n\nconst PaymentForm: React.FC<PaymentFormProps> = ({\n subscriptionBiId,\n onClose,\n onSuccess,\n}) => {\n const { formatMessage } = useIntl();\n const stripe = useStripe();\n const elements = useElements();\n const client = useViaxClient();\n const updateMutation = useUpdatePaymentMethodMutation(client);\n\n const [postalCode, setPostalCode] = useState('');\n const [cardError, setCardError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n setCardError(null);\n\n if (!stripe || !elements) {\n return;\n }\n\n const cardNumber = elements.getElement(CardNumberElement);\n if (!cardNumber) {\n return;\n }\n\n const trimmedPostal = postalCode.trim();\n if (!trimmedPostal) {\n setCardError(formatMessage(messages['manage.updatePayment.postalRequired']));\n return;\n }\n\n setIsSubmitting(true);\n try {\n const { error, paymentMethod } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardNumber,\n billing_details: {\n address: {\n postal_code: trimmedPostal,\n },\n },\n });\n\n if (error || !paymentMethod?.id) {\n setCardError(error?.message || formatMessage(messages['manage.updatePayment.error']));\n return;\n }\n\n await updateMutation.mutateAsync({\n biId: subscriptionBiId,\n tStripePaymentMethodId: paymentMethod.id,\n });\n onSuccess();\n } catch (err) {\n const message = err instanceof Error && err.message\n ? err.message\n : formatMessage(messages['manage.updatePayment.error']);\n setCardError(message);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <form className=\"manage-update-payment\" onSubmit={handleSubmit}>\n <p className=\"manage-update-payment__intro text-primary-500 mb-4\">\n {formatMessage(messages['manage.updatePayment.intro'])}\n </p>\n\n <h3 className=\"manage-update-payment__section font-weight-bold text-primary-500 mb-3\">\n {formatMessage(messages['manage.updatePayment.sectionTitle'])}\n </h3>\n\n <div className=\"manage-update-payment__row manage-update-payment__row--card mb-0\">\n <Form.Group className=\"manage-update-payment__field manage-update-payment__field--card-number mb-3\">\n <Form.Label className=\"manage-update-payment__label d-block text-primary-500 mb-1\">\n {formatMessage(messages['manage.updatePayment.cardNumber'])}\n </Form.Label>\n <div className=\"manage-update-payment__element bg-white d-flex align-items-center\">\n <CardNumberElement\n options={{\n style: ELEMENT_STYLE,\n showIcon: true,\n placeholder: '1234 1234 1234 1234',\n }}\n />\n </div>\n </Form.Group>\n\n <Form.Group className=\"manage-update-payment__field manage-update-payment__field--cvc mb-3\">\n <Form.Label className=\"manage-update-payment__label d-block text-primary-500 mb-1\">\n {formatMessage(messages['manage.updatePayment.cvc'])}\n </Form.Label>\n <div className=\"manage-update-payment__element manage-update-payment__element--cvc bg-white d-flex align-items-center\">\n <CardCvcElement options={{ style: ELEMENT_STYLE, placeholder: 'CVC' }} />\n <Icon\n src={CreditCard}\n className=\"manage-update-payment__cvc-icon\"\n aria-hidden\n />\n </div>\n </Form.Group>\n\n <Form.Group className=\"manage-update-payment__field manage-update-payment__field--expiry mb-3\">\n <Form.Label className=\"manage-update-payment__label d-block text-primary-500 mb-1\">\n {formatMessage(messages['manage.updatePayment.expiry'])}\n </Form.Label>\n <div className=\"manage-update-payment__element bg-white d-flex align-items-center\">\n <CardExpiryElement options={{ style: ELEMENT_STYLE, placeholder: 'MM / YY' }} />\n </div>\n </Form.Group>\n </div>\n\n <div className=\"manage-update-payment__row manage-update-payment__row--postal mb-0\">\n <Form.Group className=\"manage-update-payment__field manage-update-payment__field--postal mb-3\">\n <Form.Label className=\"manage-update-payment__label d-block text-primary-500 mb-1\">\n {formatMessage(messages['manage.updatePayment.postal'])}\n </Form.Label>\n <div className=\"manage-update-payment__element bg-white d-flex align-items-center\">\n <input\n className=\"manage-update-payment__control w-100 m-0 p-0 bg-transparent border-0\"\n type=\"text\"\n name=\"postal-code\"\n value={postalCode}\n onChange={(e) => setPostalCode(e.target.value)}\n autoComplete=\"postal-code\"\n required\n />\n </div>\n </Form.Group>\n </div>\n\n {cardError && (\n <Alert variant=\"danger\" className=\"mt-3 mb-0\">\n {cardError}\n </Alert>\n )}\n\n <ActionRow className=\"manage-update-payment__actions mt-4 w-100 justify-content-end flex-wrap flex-column-reverse flex-sm-row align-items-stretch align-items-sm-center\">\n <Button\n type=\"button\"\n variant=\"tertiary\"\n className=\"w-100 w-sm-auto\"\n onClick={onClose}\n disabled={isSubmitting}\n >\n {formatMessage(messages['manage.updatePayment.close'])}\n </Button>\n <Button\n type=\"submit\"\n variant=\"primary\"\n className=\"manage-btn manage-btn--dark w-100 w-sm-auto\"\n disabled={!stripe || isSubmitting}\n >\n {isSubmitting\n ? formatMessage(messages['manage.updatePayment.submitting'])\n : formatMessage(messages['manage.updatePayment.submit'])}\n </Button>\n </ActionRow>\n </form>\n );\n};\n\nconst UpdatePaymentMethodModal: React.FC<UpdatePaymentMethodModalProps> = ({\n isOpen,\n onClose,\n subscriptionBiId,\n nextBillingDate,\n}) => {\n const { formatMessage } = useIntl();\n const config = getAppConfig(appId);\n const publishableKey = (config.STRIPE_PUBLIC_KEY as string | undefined) || '';\n const [stripePromise, setStripePromise] = useState<Promise<Stripe | null> | null>(null);\n const [step, setStep] = useState<'form' | 'success'>('form');\n\n useEffect(() => {\n if (!publishableKey) {\n setStripePromise(null);\n return;\n }\n setStripePromise(loadStripe(publishableKey));\n }, [publishableKey]);\n\n useEffect(() => {\n if (isOpen) {\n setStep('form');\n }\n }, [isOpen]);\n\n const handleClose = useCallback(() => {\n setStep('form');\n onClose();\n }, [onClose]);\n\n const title = step === 'success'\n ? formatMessage(messages['manage.updatePayment.successTitle'])\n : formatMessage(messages['manage.updatePayment.title']);\n\n const canShowForm = Boolean(publishableKey && subscriptionBiId && stripePromise);\n\n const elementsOptions = useMemo(() => ({\n fonts: [{ cssSrc: 'https://fonts.googleapis.com/css?family=Open+Sans' }],\n }), []);\n\n return (\n <ModalDialog\n title={title}\n isOpen={isOpen}\n onClose={handleClose}\n size=\"lg\"\n hasCloseButton\n isOverflowVisible={false}\n isFullscreenOnMobile\n className=\"manage-update-payment-modal\"\n >\n <ModalDialog.Header>\n <ModalDialog.Title>{title}</ModalDialog.Title>\n </ModalDialog.Header>\n\n <ModalDialog.Body>\n {step === 'success' ? (\n <div className=\"manage-update-payment manage-update-payment--success\">\n <p className=\"manage-update-payment__intro text-primary-500 mb-0\">\n {nextBillingDate\n ? formatMessage(messages['manage.updatePayment.successBody'], {\n date: nextBillingDate,\n })\n : formatMessage(messages['manage.updatePayment.successBodyNoDate'])}\n </p>\n <ActionRow className=\"manage-update-payment__actions mt-4 w-100 justify-content-end flex-wrap\">\n <Button\n variant=\"primary\"\n className=\"manage-btn manage-btn--dark\"\n onClick={handleClose}\n >\n {formatMessage(messages['manage.updatePayment.close'])}\n </Button>\n </ActionRow>\n </div>\n ) : !canShowForm ? (\n <Alert variant=\"warning\">\n {formatMessage(messages['manage.updatePayment.stripeMissing'])}\n </Alert>\n ) : (\n <Elements stripe={stripePromise} options={elementsOptions}>\n <PaymentForm\n subscriptionBiId={subscriptionBiId!}\n onClose={handleClose}\n onSuccess={() => setStep('success')}\n />\n </Elements>\n )}\n </ModalDialog.Body>\n </ModalDialog>\n );\n};\n\nexport default UpdatePaymentMethodModal;\n"]}
|