@internetarchive/donation-form 1.0.1 → 1.0.3-alpha-webdev7960.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/LICENSE +661 -661
- package/README.md +115 -115
- package/dist/demo/braintree-endpoint-manager.js.map +1 -1
- package/dist/demo/demo-analytics-handler.js.map +1 -1
- package/dist/demo/submit-form-with.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/braintree-manager/braintree-interfaces.js.map +1 -1
- package/dist/src/braintree-manager/braintree-manager.js.map +1 -1
- package/dist/src/braintree-manager/payment-clients.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/google-pay-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/google-pay.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/paypal/paypal-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/paypal/paypal.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/venmo-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers/venmo.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers-interface.js.map +1 -1
- package/dist/src/braintree-manager/payment-providers.js.map +1 -1
- package/dist/src/donation-form-controller.js +123 -123
- package/dist/src/donation-form-controller.js.map +1 -1
- package/dist/src/donation-form-error.js.map +1 -1
- package/dist/src/donation-form.js +107 -107
- package/dist/src/donation-form.js.map +1 -1
- package/dist/src/form-elements/badged-input.js +47 -47
- package/dist/src/form-elements/badged-input.js.map +1 -1
- package/dist/src/form-elements/contact-form/autocomplete-field-options.js.map +1 -1
- package/dist/src/form-elements/contact-form/contact-form.js +157 -157
- package/dist/src/form-elements/contact-form/contact-form.js.map +1 -1
- package/dist/src/form-elements/contact-form/countries.js.map +1 -1
- package/dist/src/form-elements/header/donation-form-header.js +14 -14
- package/dist/src/form-elements/header/donation-form-header.js.map +1 -1
- package/dist/src/form-elements/header/donation-summary.js +15 -15
- package/dist/src/form-elements/header/donation-summary.js.map +1 -1
- package/dist/src/form-elements/payment-selector.js +164 -164
- package/dist/src/form-elements/payment-selector.js.map +1 -1
- package/dist/src/form-elements/total-amount.js +16 -16
- package/dist/src/form-elements/total-amount.js.map +1 -1
- package/dist/src/modals/confirm-donation-modal-content.js +51 -51
- package/dist/src/modals/confirm-donation-modal-content.js.map +1 -1
- package/dist/src/modals/error-modal-content.js +22 -22
- package/dist/src/modals/error-modal-content.js.map +1 -1
- package/dist/src/modals/upsell-modal-content.js +182 -182
- package/dist/src/modals/upsell-modal-content.js.map +1 -1
- package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js +20 -20
- package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/applepay-flow-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/creditcard-flow-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/googlepay-flow-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/paypal-flow-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/venmo-flow-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.js.map +1 -1
- package/dist/src/payment-flow-handlers/payment-flow-handlers.js.map +1 -1
- package/dist/src/recaptcha-manager/recaptcha-manager.js.map +1 -1
- package/dist/src/util/promisedSleep.js.map +1 -1
- package/dist/test/helpers/fillInContactForm.js.map +1 -1
- package/dist/test/mocks/flow-handlers/individual-handlers/mock-applepay-flow-handler.js.map +1 -1
- package/dist/test/mocks/flow-handlers/individual-handlers/mock-creditcard-flow-handler.js.map +1 -1
- package/dist/test/mocks/flow-handlers/individual-handlers/mock-googlepay-flow-handler.js.map +1 -1
- package/dist/test/mocks/flow-handlers/individual-handlers/mock-paypal-flow-handler.js.map +1 -1
- package/dist/test/mocks/flow-handlers/individual-handlers/mock-venmo-flow-handler.js.map +1 -1
- package/dist/test/mocks/flow-handlers/mock-payment-flow-handlers.js.map +1 -1
- package/dist/test/mocks/mock-braintree-manager.js.map +1 -1
- package/dist/test/mocks/mock-donation-info.js.map +1 -1
- package/dist/test/mocks/mock-endpoint-manager.js.map +1 -1
- package/dist/test/mocks/mock-hosted-fields-config.js.map +1 -1
- package/dist/test/mocks/mock-hosted-fields-container.js.map +1 -1
- package/dist/test/mocks/mock-lazy-loader.js.map +1 -1
- package/dist/test/mocks/mock-modal-manager.js.map +1 -1
- package/dist/test/mocks/mock-payment-clients.js.map +1 -1
- package/dist/test/mocks/mock-paypal-button-renderer.js.map +1 -1
- package/dist/test/mocks/mock-recaptcha-manager.js.map +1 -1
- package/dist/test/mocks/models/mock-billing-info.js.map +1 -1
- package/dist/test/mocks/models/mock-custom-fields.js.map +1 -1
- package/dist/test/mocks/models/mock-customer-info.js.map +1 -1
- package/dist/test/mocks/models/mock-donation-request.js.map +1 -1
- package/dist/test/mocks/models/mock-success-response.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-client.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-payment.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-paymentauthorizedevent.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-session.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-sessionmanager.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-applepay-validatemerchantevent.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-braintree-client.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-data-collector.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-googlepay-client.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-googlepay-library.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-grecaptcha.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-hostedfields-client.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-hostedfieldstateobject-generator.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-hostedfieldtokenizepayload.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-paypal-client.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-paypal-library.js.map +1 -1
- package/dist/test/mocks/payment-clients/mock-venmo-client.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-datasource-delegate.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-googlepay-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource-delegate.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/individual-providers/mock-venmo-handler.js.map +1 -1
- package/dist/test/mocks/payment-providers/mock-payment-providers.js.map +1 -1
- package/dist/test/tests/braintree-manager.test.js.map +1 -1
- package/dist/test/tests/donation-form-controller.test.js +39 -39
- package/dist/test/tests/donation-form-controller.test.js.map +1 -1
- package/dist/test/tests/donation-form.test.js +4 -4
- package/dist/test/tests/donation-form.test.js.map +1 -1
- package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js +14 -14
- package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js.map +1 -1
- package/dist/test/tests/form-elements/donation-summary.test.js.map +1 -1
- package/dist/test/tests/form-elements/payment-selector.test.js.map +1 -1
- package/dist/test/tests/modals/error-modal-content.test.js +2 -2
- package/dist/test/tests/modals/error-modal-content.test.js.map +1 -1
- package/dist/test/tests/modals/upsell-modal-content.test.js +31 -31
- package/dist/test/tests/modals/upsell-modal-content.test.js.map +1 -1
- package/dist/test/tests/models/donation-payment-info.test.js +5 -5
- package/dist/test/tests/models/donation-payment-info.test.js.map +1 -1
- package/dist/test/tests/payment-clients.test.js.map +1 -1
- package/dist/test/tests/payment-providers/applepay-sessiondatasource.test.js.map +1 -1
- package/dist/test/tests/payment-providers/applepay-sessionmanager.test.js.map +1 -1
- package/dist/test/tests/payment-providers/applepay.test.js.map +1 -1
- package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
- package/dist/test/tests/payment-providers/googlepay.test.js.map +1 -1
- package/dist/test/tests/payment-providers/payment-providers.test.js.map +1 -1
- package/dist/test/tests/payment-providers/paypal-button-datasource.test.js.map +1 -1
- package/dist/test/tests/payment-providers/paypal.test.js.map +1 -1
- package/dist/test/tests/payment-providers/venmo.test.js.map +1 -1
- package/dist/test/tests/recaptcha-manager.test.js.map +1 -1
- package/package.json +107 -107
- package/src/@types/analytics-handler/index.d.ts +8 -8
- package/src/@types/braintree-web/LICENSE +21 -21
- package/src/@types/braintree-web/index.d.ts +93 -93
- package/src/@types/braintree-web/modules/american-express.d.ts +50 -50
- package/src/@types/braintree-web/modules/apple-pay.d.ts +213 -213
- package/src/@types/braintree-web/modules/client.d.ts +103 -103
- package/src/@types/braintree-web/modules/core.d.ts +34 -34
- package/src/@types/braintree-web/modules/data-collector.d.ts +13 -13
- package/src/@types/braintree-web/modules/google-payment.d.ts +269 -269
- package/src/@types/braintree-web/modules/hosted-fields.d.ts +366 -366
- package/src/@types/braintree-web/modules/paypal-checkout.d.ts +262 -262
- package/src/@types/braintree-web/modules/paypal.d.ts +177 -177
- package/src/@types/braintree-web/modules/three-d-secure.d.ts +141 -141
- package/src/@types/braintree-web/modules/unionpay.d.ts +224 -224
- package/src/@types/braintree-web/modules/us-bank-account.d.ts +81 -81
- package/src/@types/braintree-web/modules/venmo.d.ts +110 -110
- package/src/@types/braintree-web/package.json +64 -64
- package/src/@types/paypal-checkout-components/LICENSE +21 -21
- package/src/@types/paypal-checkout-components/index.d.ts +67 -67
- package/src/@types/paypal-checkout-components/modules/button.d.ts +50 -50
- package/src/@types/paypal-checkout-components/modules/callback-data.d.ts +244 -244
- package/src/@types/paypal-checkout-components/modules/configuration.d.ts +114 -114
- package/src/@types/paypal-checkout-components/package.json +58 -58
- package/src/braintree-manager/braintree-interfaces.ts +172 -172
- package/src/braintree-manager/braintree-manager.ts +281 -281
- package/src/braintree-manager/payment-clients.ts +146 -146
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.ts +13 -13
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.ts +8 -8
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.ts +10 -10
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.ts +119 -119
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.ts +21 -21
- package/src/braintree-manager/payment-providers/apple-pay/apple-pay.ts +97 -97
- package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +21 -21
- package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +130 -130
- package/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.ts +19 -19
- package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +85 -85
- package/src/braintree-manager/payment-providers/google-pay-interface.ts +8 -8
- package/src/braintree-manager/payment-providers/google-pay.ts +59 -59
- package/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.ts +218 -218
- package/src/braintree-manager/payment-providers/paypal/paypal-interface.ts +13 -13
- package/src/braintree-manager/payment-providers/paypal/paypal.ts +78 -78
- package/src/braintree-manager/payment-providers/venmo-interface.ts +8 -8
- package/src/braintree-manager/payment-providers/venmo.ts +67 -67
- package/src/braintree-manager/payment-providers-interface.ts +25 -25
- package/src/braintree-manager/payment-providers.ts +147 -147
- package/src/donation-form-controller.ts +623 -623
- package/src/donation-form-error.ts +6 -6
- package/src/donation-form.ts +576 -576
- package/src/form-elements/badged-input.ts +109 -109
- package/src/form-elements/contact-form/autocomplete-field-options.ts +63 -63
- package/src/form-elements/contact-form/contact-form.ts +434 -434
- package/src/form-elements/contact-form/countries.ts +252 -252
- package/src/form-elements/header/donation-form-header.ts +98 -98
- package/src/form-elements/header/donation-summary.ts +61 -61
- package/src/form-elements/payment-selector.ts +365 -365
- package/src/form-elements/total-amount.ts +46 -46
- package/src/modals/confirm-donation-modal-content.ts +168 -168
- package/src/modals/error-modal-content.ts +48 -48
- package/src/modals/upsell-modal-content.ts +284 -284
- package/src/payment-flow-handlers/donation-flow-modal-manager.ts +439 -439
- package/src/payment-flow-handlers/handlers/applepay-flow-handler.ts +109 -109
- package/src/payment-flow-handlers/handlers/creditcard-flow-handler.ts +232 -232
- package/src/payment-flow-handlers/handlers/googlepay-flow-handler.ts +111 -111
- package/src/payment-flow-handlers/handlers/paypal-flow-handler.ts +331 -331
- package/src/payment-flow-handlers/handlers/venmo-flow-handler.ts +119 -119
- package/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.ts +127 -127
- package/src/payment-flow-handlers/payment-flow-handlers.ts +218 -218
- package/src/recaptcha-manager/recaptcha-manager.ts +123 -123
- package/src/util/promisedSleep.ts +3 -3
- package/dist/demo/app-root.d.ts +0 -0
- package/dist/demo/app-root.js +0 -2
- package/dist/demo/app-root.js.map +0 -1
|
@@ -1,439 +1,439 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
2
|
-
import { ModalConfig, ModalManagerInterface } from '@internetarchive/modal-manager';
|
|
3
|
-
import { UpsellModalCTAMode } from '../modals/upsell-modal-content';
|
|
4
|
-
import '../modals/confirm-donation-modal-content';
|
|
5
|
-
import { BraintreeManagerInterface } from '../braintree-manager/braintree-interfaces';
|
|
6
|
-
import {
|
|
7
|
-
SuccessResponse,
|
|
8
|
-
ErrorResponse,
|
|
9
|
-
DonationPaymentInfo,
|
|
10
|
-
DonationType,
|
|
11
|
-
PaymentProvider,
|
|
12
|
-
BillingInfo,
|
|
13
|
-
CustomerInfo,
|
|
14
|
-
DonationResponse,
|
|
15
|
-
} from '@internetarchive/donation-form-data-models';
|
|
16
|
-
import '../modals/error-modal-content';
|
|
17
|
-
import { DonationControllerEventLoggerInterface } from '../@types/analytics-handler';
|
|
18
|
-
|
|
19
|
-
enum ModalHeaderColor {
|
|
20
|
-
Blue = '#497fbf',
|
|
21
|
-
Green = '#55A183',
|
|
22
|
-
Red = '#691916',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The DonationFlowModalManager is responsible for most of the high-level modal flows.
|
|
27
|
-
*
|
|
28
|
-
* Each of the payment providers has slightly different interactions, ie the PayPal button,
|
|
29
|
-
* ApplePay popup, Venmo launching the app, etc. The modal flow is the same for all of them
|
|
30
|
-
* so this class gets called by the individual payment flow handlers to take the user
|
|
31
|
-
* through the modal flow.
|
|
32
|
-
*
|
|
33
|
-
* @export
|
|
34
|
-
* @interface DonationFlowModalManagerInterface
|
|
35
|
-
*/
|
|
36
|
-
export interface DonationFlowModalManagerInterface {
|
|
37
|
-
showConfirmationStepModal(options: {
|
|
38
|
-
amount: number;
|
|
39
|
-
donationType: DonationType;
|
|
40
|
-
currencyType: string;
|
|
41
|
-
confirmDonationCB: Function;
|
|
42
|
-
cancelDonationCB: Function;
|
|
43
|
-
}): Promise<void>;
|
|
44
|
-
/**
|
|
45
|
-
* Close the modal
|
|
46
|
-
*
|
|
47
|
-
* @memberof DonationFlowModalManagerInterface
|
|
48
|
-
*/
|
|
49
|
-
closeModal(): void;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Show the processing modal
|
|
53
|
-
*
|
|
54
|
-
* @memberof DonationFlowModalManagerInterface
|
|
55
|
-
*/
|
|
56
|
-
showProcessingModal(): void;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Show the Thank You modal
|
|
60
|
-
*
|
|
61
|
-
* @memberof DonationFlowModalManagerInterface
|
|
62
|
-
*/
|
|
63
|
-
showThankYouModal(options: {
|
|
64
|
-
successResponse: SuccessResponse;
|
|
65
|
-
upsellSuccessResponse?: SuccessResponse;
|
|
66
|
-
}): void;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Show the Error modal
|
|
70
|
-
*
|
|
71
|
-
* @param {{
|
|
72
|
-
* userClosedModalCallback?: () => void;
|
|
73
|
-
* }} [options]
|
|
74
|
-
* @memberof DonationFlowModalManagerInterface
|
|
75
|
-
*/
|
|
76
|
-
showErrorModal(options: { message: string; userClosedModalCallback?: () => void }): void;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Show the upsell modal
|
|
80
|
-
*
|
|
81
|
-
* @param {{
|
|
82
|
-
* ctaMode?: UpsellModalCTAMode;
|
|
83
|
-
* yesSelected?: (amount: number) => void;
|
|
84
|
-
* noSelected?: () => void;
|
|
85
|
-
* amountChanged?: (amount: number) => void;
|
|
86
|
-
* userClosedModalCallback?: () => void;
|
|
87
|
-
* }} [options]
|
|
88
|
-
* @returns {Promise<void>}
|
|
89
|
-
* @memberof DonationFlowModalManagerInterface
|
|
90
|
-
*/
|
|
91
|
-
showUpsellModal(options: {
|
|
92
|
-
oneTimeAmount: number;
|
|
93
|
-
ctaMode?: UpsellModalCTAMode;
|
|
94
|
-
yesSelected?: (amount: number) => void;
|
|
95
|
-
noSelected?: () => void;
|
|
96
|
-
amountChanged?: (amount: number) => void;
|
|
97
|
-
userClosedModalCallback?: () => void;
|
|
98
|
-
}): Promise<void>;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Start the donation submission flow. This kicks off the "main" modal flow once the
|
|
102
|
-
* user authorizes the donation through their payment provider, which provides
|
|
103
|
-
* us the with the nonce used to complete the donation.
|
|
104
|
-
*
|
|
105
|
-
* @param {{
|
|
106
|
-
* nonce: string;
|
|
107
|
-
* paymentProvider: PaymentProvider;
|
|
108
|
-
* donationInfo: DonationPaymentInfo;
|
|
109
|
-
* billingInfo: BillingInfo;
|
|
110
|
-
* customerInfo: CustomerInfo;
|
|
111
|
-
* upsellOnetimeTransactionId?: string;
|
|
112
|
-
* customerId?: string;
|
|
113
|
-
* recaptchaToken?: string;
|
|
114
|
-
* bin?: string; // first 6 digits of CC
|
|
115
|
-
* binName?: string; // credit card bank name
|
|
116
|
-
* }} options
|
|
117
|
-
* @returns {(Promise<DonationResponse | undefined>)}
|
|
118
|
-
* @memberof DonationFlowModalManagerInterface
|
|
119
|
-
*/
|
|
120
|
-
startDonationSubmissionFlow(options: {
|
|
121
|
-
nonce: string;
|
|
122
|
-
paymentProvider: PaymentProvider;
|
|
123
|
-
donationInfo: DonationPaymentInfo;
|
|
124
|
-
billingInfo: BillingInfo;
|
|
125
|
-
customerInfo: CustomerInfo;
|
|
126
|
-
upsellOnetimeTransactionId?: string;
|
|
127
|
-
customerId?: string;
|
|
128
|
-
recaptchaToken?: string;
|
|
129
|
-
bin?: string; // first 6 digits of CC
|
|
130
|
-
binName?: string; // credit card bank name
|
|
131
|
-
}): Promise<DonationResponse | undefined>;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Handle a successful donation response. This encapsulates the logic for the type of
|
|
135
|
-
* donation that was made.
|
|
136
|
-
* ie. If it was a one-time donation, show the upsell, if it was monthly do not.
|
|
137
|
-
*
|
|
138
|
-
* @param {DonationPaymentInfo} donationInfo
|
|
139
|
-
* @param {SuccessResponse} response
|
|
140
|
-
* @memberof DonationFlowModalManagerInterface
|
|
141
|
-
*/
|
|
142
|
-
handleSuccessfulDonationResponse(
|
|
143
|
-
donationInfo: DonationPaymentInfo,
|
|
144
|
-
response: SuccessResponse,
|
|
145
|
-
): void;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export class DonationFlowModalManager implements DonationFlowModalManagerInterface {
|
|
149
|
-
private braintreeManager: BraintreeManagerInterface;
|
|
150
|
-
|
|
151
|
-
private modalManager: ModalManagerInterface;
|
|
152
|
-
|
|
153
|
-
private analytics: DonationControllerEventLoggerInterface;
|
|
154
|
-
|
|
155
|
-
constructor(options: {
|
|
156
|
-
braintreeManager: BraintreeManagerInterface;
|
|
157
|
-
modalManager: ModalManagerInterface;
|
|
158
|
-
analytics: DonationControllerEventLoggerInterface;
|
|
159
|
-
}) {
|
|
160
|
-
this.modalManager = options.modalManager;
|
|
161
|
-
this.braintreeManager = options.braintreeManager;
|
|
162
|
-
this.analytics = options.analytics;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** @inheritdoc */
|
|
166
|
-
closeModal(): void {
|
|
167
|
-
this.modalManager.closeModal();
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/** @inheritdoc */
|
|
171
|
-
showProcessingModal(): void {
|
|
172
|
-
const modalConfig = new ModalConfig({
|
|
173
|
-
headerColor: ModalHeaderColor.Blue,
|
|
174
|
-
showProcessingIndicator: true,
|
|
175
|
-
closeOnBackdropClick: false,
|
|
176
|
-
showCloseButton: false,
|
|
177
|
-
processingImageMode: 'processing',
|
|
178
|
-
title: html` Processing... `,
|
|
179
|
-
});
|
|
180
|
-
this.modalManager.showModal({ config: modalConfig });
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** @inheritdoc */
|
|
184
|
-
showThankYouModal(options: {
|
|
185
|
-
successResponse: SuccessResponse;
|
|
186
|
-
upsellSuccessResponse?: SuccessResponse;
|
|
187
|
-
}): void {
|
|
188
|
-
const modalConfig = new ModalConfig({
|
|
189
|
-
showProcessingIndicator: true,
|
|
190
|
-
processingImageMode: 'complete',
|
|
191
|
-
headerColor: ModalHeaderColor.Green,
|
|
192
|
-
title: html` Thank You! `,
|
|
193
|
-
});
|
|
194
|
-
this.modalManager.showModal({
|
|
195
|
-
config: modalConfig,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
// post analytic
|
|
199
|
-
const selectedPayment = options.successResponse.paymentProvider.replace(/\s+/g, '');
|
|
200
|
-
let action = `Donated-${selectedPayment}`;
|
|
201
|
-
if (options.upsellSuccessResponse) {
|
|
202
|
-
action += `-upsell`;
|
|
203
|
-
}
|
|
204
|
-
const label = options.successResponse.donationType;
|
|
205
|
-
this.analytics.logDonationFlowEvent(action, label);
|
|
206
|
-
|
|
207
|
-
// post donation
|
|
208
|
-
this.braintreeManager.donationSuccessful(options);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** @inheritdoc */
|
|
212
|
-
showErrorModal(options: { message: string; userClosedModalCallback?: () => void }): void {
|
|
213
|
-
const modalConfig = new ModalConfig({
|
|
214
|
-
headerColor: ModalHeaderColor.Red,
|
|
215
|
-
title: html` Processing error `,
|
|
216
|
-
headline: html` There's been a problem completing your donation. `,
|
|
217
|
-
message: html` ${options?.message} `,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
this.modalManager.showModal({
|
|
221
|
-
config: modalConfig,
|
|
222
|
-
userClosedModalCallback: options?.userClosedModalCallback,
|
|
223
|
-
customModalContent: html`
|
|
224
|
-
<donation-form-error-modal-content></donation-form-error-modal-content>
|
|
225
|
-
`,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
showConfirmationStepModal(options: {
|
|
230
|
-
amount: number;
|
|
231
|
-
donationType: DonationType;
|
|
232
|
-
currencyType: string;
|
|
233
|
-
confirmDonationCB: Function;
|
|
234
|
-
cancelDonationCB: Function;
|
|
235
|
-
}): Promise<void> {
|
|
236
|
-
const confirmDonation = (): void => {
|
|
237
|
-
options?.confirmDonationCB();
|
|
238
|
-
};
|
|
239
|
-
const cancelDonation = (): void => {
|
|
240
|
-
options?.cancelDonationCB();
|
|
241
|
-
};
|
|
242
|
-
const modalTitle =
|
|
243
|
-
options.donationType === DonationType.Upsell
|
|
244
|
-
? 'Confirm monthly donation'
|
|
245
|
-
: 'Complete donation';
|
|
246
|
-
|
|
247
|
-
const modalConfig = new ModalConfig({
|
|
248
|
-
closeOnBackdropClick: false,
|
|
249
|
-
headerColor: ModalHeaderColor.Green,
|
|
250
|
-
title: html`${modalTitle}`,
|
|
251
|
-
message: html`
|
|
252
|
-
<confirm-donation-modal
|
|
253
|
-
.amount="${options.amount}"
|
|
254
|
-
.currencyType="${options.currencyType}"
|
|
255
|
-
.donationType="${options.donationType}"
|
|
256
|
-
.confirmDonation=${confirmDonation}
|
|
257
|
-
.cancelDonation=${cancelDonation}
|
|
258
|
-
></confirm-donation-modal>
|
|
259
|
-
`,
|
|
260
|
-
});
|
|
261
|
-
return this.modalManager.showModal({
|
|
262
|
-
config: modalConfig,
|
|
263
|
-
userClosedModalCallback: cancelDonation,
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/** @inheritdoc */
|
|
268
|
-
showUpsellModal(options: {
|
|
269
|
-
oneTimeAmount: number;
|
|
270
|
-
yesSelected?: (amount: number) => void;
|
|
271
|
-
noSelected?: () => void;
|
|
272
|
-
amountChanged?: (amount: number) => void;
|
|
273
|
-
userClosedModalCallback?: () => void;
|
|
274
|
-
ctaMode?: UpsellModalCTAMode;
|
|
275
|
-
}): Promise<void> {
|
|
276
|
-
const modalConfig = new ModalConfig({
|
|
277
|
-
headerColor: ModalHeaderColor.Green,
|
|
278
|
-
title: html` Donation received `,
|
|
279
|
-
processingImageMode: 'complete',
|
|
280
|
-
showProcessingIndicator: true,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
const upsellAmount = DonationFlowModalManager.getDefaultUpsellAmount(options.oneTimeAmount);
|
|
284
|
-
if (options.amountChanged) {
|
|
285
|
-
options.amountChanged(upsellAmount);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const modalContent = html`
|
|
289
|
-
<upsell-modal-content
|
|
290
|
-
.amount=${upsellAmount}
|
|
291
|
-
.yesButtonMode=${options?.ctaMode ?? UpsellModalCTAMode.YesButton}
|
|
292
|
-
@yesSelected=${(e: CustomEvent): void =>
|
|
293
|
-
options?.yesSelected ? options.yesSelected(e.detail.amount) : undefined}
|
|
294
|
-
@noThanksSelected=${options?.noSelected}
|
|
295
|
-
@amountChanged=${(e: CustomEvent): void =>
|
|
296
|
-
options?.amountChanged ? options.amountChanged(e.detail.amount) : undefined}
|
|
297
|
-
>
|
|
298
|
-
<slot name="paypal-upsell-button"></slot>
|
|
299
|
-
</upsell-modal-content>
|
|
300
|
-
`;
|
|
301
|
-
return this.modalManager.showModal({
|
|
302
|
-
config: modalConfig,
|
|
303
|
-
customModalContent: modalContent,
|
|
304
|
-
userClosedModalCallback: options?.userClosedModalCallback,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** @inheritdoc */
|
|
309
|
-
async startDonationSubmissionFlow(options: {
|
|
310
|
-
nonce: string;
|
|
311
|
-
paymentProvider: PaymentProvider;
|
|
312
|
-
donationInfo: DonationPaymentInfo;
|
|
313
|
-
billingInfo: BillingInfo;
|
|
314
|
-
customerInfo: CustomerInfo;
|
|
315
|
-
upsellOnetimeTransactionId?: string;
|
|
316
|
-
customerId?: string;
|
|
317
|
-
recaptchaToken?: string;
|
|
318
|
-
bin?: string; // first 6 digits of CC
|
|
319
|
-
binName?: string; // credit card bank name
|
|
320
|
-
}): Promise<DonationResponse | undefined> {
|
|
321
|
-
this.showProcessingModal();
|
|
322
|
-
|
|
323
|
-
try {
|
|
324
|
-
const response = await this.braintreeManager.submitDonation(options);
|
|
325
|
-
|
|
326
|
-
if (response.success) {
|
|
327
|
-
this.handleSuccessfulDonationResponse(
|
|
328
|
-
options.donationInfo,
|
|
329
|
-
response.value as SuccessResponse,
|
|
330
|
-
);
|
|
331
|
-
return response;
|
|
332
|
-
} else {
|
|
333
|
-
const error = response.value as ErrorResponse;
|
|
334
|
-
this.showErrorModal({
|
|
335
|
-
message: error.message,
|
|
336
|
-
});
|
|
337
|
-
return response;
|
|
338
|
-
}
|
|
339
|
-
} catch (error) {
|
|
340
|
-
this.showErrorModal({
|
|
341
|
-
message: `${error}`,
|
|
342
|
-
});
|
|
343
|
-
console.error('error getting a response', error);
|
|
344
|
-
return undefined;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
private async upsellModalYesSelected(
|
|
349
|
-
oneTimeDonationResponse: SuccessResponse,
|
|
350
|
-
amount: number,
|
|
351
|
-
): Promise<DonationResponse | undefined> {
|
|
352
|
-
this.showProcessingModal();
|
|
353
|
-
|
|
354
|
-
try {
|
|
355
|
-
const response = await this.braintreeManager.submitUpsellDonation({
|
|
356
|
-
oneTimeDonationResponse: oneTimeDonationResponse,
|
|
357
|
-
amount: amount,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
if (response.success) {
|
|
361
|
-
this.completeUpsell({
|
|
362
|
-
successResponse: oneTimeDonationResponse,
|
|
363
|
-
upsellSuccessResponse: response.value as SuccessResponse,
|
|
364
|
-
});
|
|
365
|
-
} else {
|
|
366
|
-
const error = response.value as ErrorResponse;
|
|
367
|
-
this.showErrorModal({
|
|
368
|
-
message: error.message,
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return response;
|
|
373
|
-
} catch (error) {
|
|
374
|
-
this.showErrorModal({
|
|
375
|
-
message: `${error}`,
|
|
376
|
-
});
|
|
377
|
-
console.error('error getting a response', error);
|
|
378
|
-
return undefined;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
private completeUpsell(options: {
|
|
383
|
-
successResponse: SuccessResponse;
|
|
384
|
-
upsellSuccessResponse?: SuccessResponse;
|
|
385
|
-
}): void {
|
|
386
|
-
this.showThankYouModal(options);
|
|
387
|
-
|
|
388
|
-
// post analytic
|
|
389
|
-
const selectedPayment = options.successResponse.paymentProvider.replace(/\s+/g, '');
|
|
390
|
-
const action = `Donated-${selectedPayment}-upsell`;
|
|
391
|
-
const label = options.successResponse.donationType;
|
|
392
|
-
this.analytics.logDonationFlowEvent(action, label);
|
|
393
|
-
|
|
394
|
-
this.braintreeManager.donationSuccessful(options);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
static getDefaultUpsellAmount(oneTimeAmount: number): number {
|
|
398
|
-
let amount = 5;
|
|
399
|
-
|
|
400
|
-
if (oneTimeAmount <= 10) amount = 8;
|
|
401
|
-
else if (oneTimeAmount > 10 && oneTimeAmount <= 25) amount = 10;
|
|
402
|
-
else if (oneTimeAmount > 25 && oneTimeAmount <= 100) amount = 25;
|
|
403
|
-
else if (oneTimeAmount > 100) amount = 50;
|
|
404
|
-
|
|
405
|
-
return amount;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/** @inheritdoc */
|
|
409
|
-
handleSuccessfulDonationResponse(
|
|
410
|
-
donationInfo: DonationPaymentInfo,
|
|
411
|
-
response: SuccessResponse,
|
|
412
|
-
): void {
|
|
413
|
-
switch (donationInfo.donationType) {
|
|
414
|
-
case DonationType.OneTime:
|
|
415
|
-
this.showUpsellModal({
|
|
416
|
-
oneTimeAmount: response.amount,
|
|
417
|
-
yesSelected: (amount: number) => {
|
|
418
|
-
this.upsellModalYesSelected(response, amount);
|
|
419
|
-
},
|
|
420
|
-
noSelected: () => {
|
|
421
|
-
this.showThankYouModal({ successResponse: response });
|
|
422
|
-
},
|
|
423
|
-
userClosedModalCallback: () => {
|
|
424
|
-
this.showThankYouModal({ successResponse: response });
|
|
425
|
-
},
|
|
426
|
-
});
|
|
427
|
-
break;
|
|
428
|
-
case DonationType.Monthly:
|
|
429
|
-
this.showThankYouModal({ successResponse: response });
|
|
430
|
-
break;
|
|
431
|
-
// This case will never be reached, it is only here for completeness.
|
|
432
|
-
// The upsell case gets handled in `modalYesSelected()` below
|
|
433
|
-
case DonationType.Upsell:
|
|
434
|
-
break;
|
|
435
|
-
default:
|
|
436
|
-
break;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { ModalConfig, ModalManagerInterface } from '@internetarchive/modal-manager';
|
|
3
|
+
import { UpsellModalCTAMode } from '../modals/upsell-modal-content';
|
|
4
|
+
import '../modals/confirm-donation-modal-content';
|
|
5
|
+
import { BraintreeManagerInterface } from '../braintree-manager/braintree-interfaces';
|
|
6
|
+
import {
|
|
7
|
+
SuccessResponse,
|
|
8
|
+
ErrorResponse,
|
|
9
|
+
DonationPaymentInfo,
|
|
10
|
+
DonationType,
|
|
11
|
+
PaymentProvider,
|
|
12
|
+
BillingInfo,
|
|
13
|
+
CustomerInfo,
|
|
14
|
+
DonationResponse,
|
|
15
|
+
} from '@internetarchive/donation-form-data-models';
|
|
16
|
+
import '../modals/error-modal-content';
|
|
17
|
+
import { DonationControllerEventLoggerInterface } from '../@types/analytics-handler';
|
|
18
|
+
|
|
19
|
+
enum ModalHeaderColor {
|
|
20
|
+
Blue = '#497fbf',
|
|
21
|
+
Green = '#55A183',
|
|
22
|
+
Red = '#691916',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The DonationFlowModalManager is responsible for most of the high-level modal flows.
|
|
27
|
+
*
|
|
28
|
+
* Each of the payment providers has slightly different interactions, ie the PayPal button,
|
|
29
|
+
* ApplePay popup, Venmo launching the app, etc. The modal flow is the same for all of them
|
|
30
|
+
* so this class gets called by the individual payment flow handlers to take the user
|
|
31
|
+
* through the modal flow.
|
|
32
|
+
*
|
|
33
|
+
* @export
|
|
34
|
+
* @interface DonationFlowModalManagerInterface
|
|
35
|
+
*/
|
|
36
|
+
export interface DonationFlowModalManagerInterface {
|
|
37
|
+
showConfirmationStepModal(options: {
|
|
38
|
+
amount: number;
|
|
39
|
+
donationType: DonationType;
|
|
40
|
+
currencyType: string;
|
|
41
|
+
confirmDonationCB: Function;
|
|
42
|
+
cancelDonationCB: Function;
|
|
43
|
+
}): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Close the modal
|
|
46
|
+
*
|
|
47
|
+
* @memberof DonationFlowModalManagerInterface
|
|
48
|
+
*/
|
|
49
|
+
closeModal(): void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Show the processing modal
|
|
53
|
+
*
|
|
54
|
+
* @memberof DonationFlowModalManagerInterface
|
|
55
|
+
*/
|
|
56
|
+
showProcessingModal(): void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Show the Thank You modal
|
|
60
|
+
*
|
|
61
|
+
* @memberof DonationFlowModalManagerInterface
|
|
62
|
+
*/
|
|
63
|
+
showThankYouModal(options: {
|
|
64
|
+
successResponse: SuccessResponse;
|
|
65
|
+
upsellSuccessResponse?: SuccessResponse;
|
|
66
|
+
}): void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Show the Error modal
|
|
70
|
+
*
|
|
71
|
+
* @param {{
|
|
72
|
+
* userClosedModalCallback?: () => void;
|
|
73
|
+
* }} [options]
|
|
74
|
+
* @memberof DonationFlowModalManagerInterface
|
|
75
|
+
*/
|
|
76
|
+
showErrorModal(options: { message: string; userClosedModalCallback?: () => void }): void;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Show the upsell modal
|
|
80
|
+
*
|
|
81
|
+
* @param {{
|
|
82
|
+
* ctaMode?: UpsellModalCTAMode;
|
|
83
|
+
* yesSelected?: (amount: number) => void;
|
|
84
|
+
* noSelected?: () => void;
|
|
85
|
+
* amountChanged?: (amount: number) => void;
|
|
86
|
+
* userClosedModalCallback?: () => void;
|
|
87
|
+
* }} [options]
|
|
88
|
+
* @returns {Promise<void>}
|
|
89
|
+
* @memberof DonationFlowModalManagerInterface
|
|
90
|
+
*/
|
|
91
|
+
showUpsellModal(options: {
|
|
92
|
+
oneTimeAmount: number;
|
|
93
|
+
ctaMode?: UpsellModalCTAMode;
|
|
94
|
+
yesSelected?: (amount: number) => void;
|
|
95
|
+
noSelected?: () => void;
|
|
96
|
+
amountChanged?: (amount: number) => void;
|
|
97
|
+
userClosedModalCallback?: () => void;
|
|
98
|
+
}): Promise<void>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Start the donation submission flow. This kicks off the "main" modal flow once the
|
|
102
|
+
* user authorizes the donation through their payment provider, which provides
|
|
103
|
+
* us the with the nonce used to complete the donation.
|
|
104
|
+
*
|
|
105
|
+
* @param {{
|
|
106
|
+
* nonce: string;
|
|
107
|
+
* paymentProvider: PaymentProvider;
|
|
108
|
+
* donationInfo: DonationPaymentInfo;
|
|
109
|
+
* billingInfo: BillingInfo;
|
|
110
|
+
* customerInfo: CustomerInfo;
|
|
111
|
+
* upsellOnetimeTransactionId?: string;
|
|
112
|
+
* customerId?: string;
|
|
113
|
+
* recaptchaToken?: string;
|
|
114
|
+
* bin?: string; // first 6 digits of CC
|
|
115
|
+
* binName?: string; // credit card bank name
|
|
116
|
+
* }} options
|
|
117
|
+
* @returns {(Promise<DonationResponse | undefined>)}
|
|
118
|
+
* @memberof DonationFlowModalManagerInterface
|
|
119
|
+
*/
|
|
120
|
+
startDonationSubmissionFlow(options: {
|
|
121
|
+
nonce: string;
|
|
122
|
+
paymentProvider: PaymentProvider;
|
|
123
|
+
donationInfo: DonationPaymentInfo;
|
|
124
|
+
billingInfo: BillingInfo;
|
|
125
|
+
customerInfo: CustomerInfo;
|
|
126
|
+
upsellOnetimeTransactionId?: string;
|
|
127
|
+
customerId?: string;
|
|
128
|
+
recaptchaToken?: string;
|
|
129
|
+
bin?: string; // first 6 digits of CC
|
|
130
|
+
binName?: string; // credit card bank name
|
|
131
|
+
}): Promise<DonationResponse | undefined>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Handle a successful donation response. This encapsulates the logic for the type of
|
|
135
|
+
* donation that was made.
|
|
136
|
+
* ie. If it was a one-time donation, show the upsell, if it was monthly do not.
|
|
137
|
+
*
|
|
138
|
+
* @param {DonationPaymentInfo} donationInfo
|
|
139
|
+
* @param {SuccessResponse} response
|
|
140
|
+
* @memberof DonationFlowModalManagerInterface
|
|
141
|
+
*/
|
|
142
|
+
handleSuccessfulDonationResponse(
|
|
143
|
+
donationInfo: DonationPaymentInfo,
|
|
144
|
+
response: SuccessResponse,
|
|
145
|
+
): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class DonationFlowModalManager implements DonationFlowModalManagerInterface {
|
|
149
|
+
private braintreeManager: BraintreeManagerInterface;
|
|
150
|
+
|
|
151
|
+
private modalManager: ModalManagerInterface;
|
|
152
|
+
|
|
153
|
+
private analytics: DonationControllerEventLoggerInterface;
|
|
154
|
+
|
|
155
|
+
constructor(options: {
|
|
156
|
+
braintreeManager: BraintreeManagerInterface;
|
|
157
|
+
modalManager: ModalManagerInterface;
|
|
158
|
+
analytics: DonationControllerEventLoggerInterface;
|
|
159
|
+
}) {
|
|
160
|
+
this.modalManager = options.modalManager;
|
|
161
|
+
this.braintreeManager = options.braintreeManager;
|
|
162
|
+
this.analytics = options.analytics;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** @inheritdoc */
|
|
166
|
+
closeModal(): void {
|
|
167
|
+
this.modalManager.closeModal();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** @inheritdoc */
|
|
171
|
+
showProcessingModal(): void {
|
|
172
|
+
const modalConfig = new ModalConfig({
|
|
173
|
+
headerColor: ModalHeaderColor.Blue,
|
|
174
|
+
showProcessingIndicator: true,
|
|
175
|
+
closeOnBackdropClick: false,
|
|
176
|
+
showCloseButton: false,
|
|
177
|
+
processingImageMode: 'processing',
|
|
178
|
+
title: html` Processing... `,
|
|
179
|
+
});
|
|
180
|
+
this.modalManager.showModal({ config: modalConfig });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** @inheritdoc */
|
|
184
|
+
showThankYouModal(options: {
|
|
185
|
+
successResponse: SuccessResponse;
|
|
186
|
+
upsellSuccessResponse?: SuccessResponse;
|
|
187
|
+
}): void {
|
|
188
|
+
const modalConfig = new ModalConfig({
|
|
189
|
+
showProcessingIndicator: true,
|
|
190
|
+
processingImageMode: 'complete',
|
|
191
|
+
headerColor: ModalHeaderColor.Green,
|
|
192
|
+
title: html` Thank You! `,
|
|
193
|
+
});
|
|
194
|
+
this.modalManager.showModal({
|
|
195
|
+
config: modalConfig,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// post analytic
|
|
199
|
+
const selectedPayment = options.successResponse.paymentProvider.replace(/\s+/g, '');
|
|
200
|
+
let action = `Donated-${selectedPayment}`;
|
|
201
|
+
if (options.upsellSuccessResponse) {
|
|
202
|
+
action += `-upsell`;
|
|
203
|
+
}
|
|
204
|
+
const label = options.successResponse.donationType;
|
|
205
|
+
this.analytics.logDonationFlowEvent(action, label);
|
|
206
|
+
|
|
207
|
+
// post donation
|
|
208
|
+
this.braintreeManager.donationSuccessful(options);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** @inheritdoc */
|
|
212
|
+
showErrorModal(options: { message: string; userClosedModalCallback?: () => void }): void {
|
|
213
|
+
const modalConfig = new ModalConfig({
|
|
214
|
+
headerColor: ModalHeaderColor.Red,
|
|
215
|
+
title: html` Processing error `,
|
|
216
|
+
headline: html` There's been a problem completing your donation. `,
|
|
217
|
+
message: html` ${options?.message} `,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
this.modalManager.showModal({
|
|
221
|
+
config: modalConfig,
|
|
222
|
+
userClosedModalCallback: options?.userClosedModalCallback,
|
|
223
|
+
customModalContent: html`
|
|
224
|
+
<donation-form-error-modal-content></donation-form-error-modal-content>
|
|
225
|
+
`,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
showConfirmationStepModal(options: {
|
|
230
|
+
amount: number;
|
|
231
|
+
donationType: DonationType;
|
|
232
|
+
currencyType: string;
|
|
233
|
+
confirmDonationCB: Function;
|
|
234
|
+
cancelDonationCB: Function;
|
|
235
|
+
}): Promise<void> {
|
|
236
|
+
const confirmDonation = (): void => {
|
|
237
|
+
options?.confirmDonationCB();
|
|
238
|
+
};
|
|
239
|
+
const cancelDonation = (): void => {
|
|
240
|
+
options?.cancelDonationCB();
|
|
241
|
+
};
|
|
242
|
+
const modalTitle =
|
|
243
|
+
options.donationType === DonationType.Upsell
|
|
244
|
+
? 'Confirm monthly donation'
|
|
245
|
+
: 'Complete donation';
|
|
246
|
+
|
|
247
|
+
const modalConfig = new ModalConfig({
|
|
248
|
+
closeOnBackdropClick: false,
|
|
249
|
+
headerColor: ModalHeaderColor.Green,
|
|
250
|
+
title: html`${modalTitle}`,
|
|
251
|
+
message: html`
|
|
252
|
+
<confirm-donation-modal
|
|
253
|
+
.amount="${options.amount}"
|
|
254
|
+
.currencyType="${options.currencyType}"
|
|
255
|
+
.donationType="${options.donationType}"
|
|
256
|
+
.confirmDonation=${confirmDonation}
|
|
257
|
+
.cancelDonation=${cancelDonation}
|
|
258
|
+
></confirm-donation-modal>
|
|
259
|
+
`,
|
|
260
|
+
});
|
|
261
|
+
return this.modalManager.showModal({
|
|
262
|
+
config: modalConfig,
|
|
263
|
+
userClosedModalCallback: cancelDonation,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** @inheritdoc */
|
|
268
|
+
showUpsellModal(options: {
|
|
269
|
+
oneTimeAmount: number;
|
|
270
|
+
yesSelected?: (amount: number) => void;
|
|
271
|
+
noSelected?: () => void;
|
|
272
|
+
amountChanged?: (amount: number) => void;
|
|
273
|
+
userClosedModalCallback?: () => void;
|
|
274
|
+
ctaMode?: UpsellModalCTAMode;
|
|
275
|
+
}): Promise<void> {
|
|
276
|
+
const modalConfig = new ModalConfig({
|
|
277
|
+
headerColor: ModalHeaderColor.Green,
|
|
278
|
+
title: html` Donation received `,
|
|
279
|
+
processingImageMode: 'complete',
|
|
280
|
+
showProcessingIndicator: true,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const upsellAmount = DonationFlowModalManager.getDefaultUpsellAmount(options.oneTimeAmount);
|
|
284
|
+
if (options.amountChanged) {
|
|
285
|
+
options.amountChanged(upsellAmount);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const modalContent = html`
|
|
289
|
+
<upsell-modal-content
|
|
290
|
+
.amount=${upsellAmount}
|
|
291
|
+
.yesButtonMode=${options?.ctaMode ?? UpsellModalCTAMode.YesButton}
|
|
292
|
+
@yesSelected=${(e: CustomEvent): void =>
|
|
293
|
+
options?.yesSelected ? options.yesSelected(e.detail.amount) : undefined}
|
|
294
|
+
@noThanksSelected=${options?.noSelected}
|
|
295
|
+
@amountChanged=${(e: CustomEvent): void =>
|
|
296
|
+
options?.amountChanged ? options.amountChanged(e.detail.amount) : undefined}
|
|
297
|
+
>
|
|
298
|
+
<slot name="paypal-upsell-button"></slot>
|
|
299
|
+
</upsell-modal-content>
|
|
300
|
+
`;
|
|
301
|
+
return this.modalManager.showModal({
|
|
302
|
+
config: modalConfig,
|
|
303
|
+
customModalContent: modalContent,
|
|
304
|
+
userClosedModalCallback: options?.userClosedModalCallback,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** @inheritdoc */
|
|
309
|
+
async startDonationSubmissionFlow(options: {
|
|
310
|
+
nonce: string;
|
|
311
|
+
paymentProvider: PaymentProvider;
|
|
312
|
+
donationInfo: DonationPaymentInfo;
|
|
313
|
+
billingInfo: BillingInfo;
|
|
314
|
+
customerInfo: CustomerInfo;
|
|
315
|
+
upsellOnetimeTransactionId?: string;
|
|
316
|
+
customerId?: string;
|
|
317
|
+
recaptchaToken?: string;
|
|
318
|
+
bin?: string; // first 6 digits of CC
|
|
319
|
+
binName?: string; // credit card bank name
|
|
320
|
+
}): Promise<DonationResponse | undefined> {
|
|
321
|
+
this.showProcessingModal();
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
const response = await this.braintreeManager.submitDonation(options);
|
|
325
|
+
|
|
326
|
+
if (response.success) {
|
|
327
|
+
this.handleSuccessfulDonationResponse(
|
|
328
|
+
options.donationInfo,
|
|
329
|
+
response.value as SuccessResponse,
|
|
330
|
+
);
|
|
331
|
+
return response;
|
|
332
|
+
} else {
|
|
333
|
+
const error = response.value as ErrorResponse;
|
|
334
|
+
this.showErrorModal({
|
|
335
|
+
message: error.message,
|
|
336
|
+
});
|
|
337
|
+
return response;
|
|
338
|
+
}
|
|
339
|
+
} catch (error) {
|
|
340
|
+
this.showErrorModal({
|
|
341
|
+
message: `${error}`,
|
|
342
|
+
});
|
|
343
|
+
console.error('error getting a response', error);
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private async upsellModalYesSelected(
|
|
349
|
+
oneTimeDonationResponse: SuccessResponse,
|
|
350
|
+
amount: number,
|
|
351
|
+
): Promise<DonationResponse | undefined> {
|
|
352
|
+
this.showProcessingModal();
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
const response = await this.braintreeManager.submitUpsellDonation({
|
|
356
|
+
oneTimeDonationResponse: oneTimeDonationResponse,
|
|
357
|
+
amount: amount,
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
if (response.success) {
|
|
361
|
+
this.completeUpsell({
|
|
362
|
+
successResponse: oneTimeDonationResponse,
|
|
363
|
+
upsellSuccessResponse: response.value as SuccessResponse,
|
|
364
|
+
});
|
|
365
|
+
} else {
|
|
366
|
+
const error = response.value as ErrorResponse;
|
|
367
|
+
this.showErrorModal({
|
|
368
|
+
message: error.message,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return response;
|
|
373
|
+
} catch (error) {
|
|
374
|
+
this.showErrorModal({
|
|
375
|
+
message: `${error}`,
|
|
376
|
+
});
|
|
377
|
+
console.error('error getting a response', error);
|
|
378
|
+
return undefined;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private completeUpsell(options: {
|
|
383
|
+
successResponse: SuccessResponse;
|
|
384
|
+
upsellSuccessResponse?: SuccessResponse;
|
|
385
|
+
}): void {
|
|
386
|
+
this.showThankYouModal(options);
|
|
387
|
+
|
|
388
|
+
// post analytic
|
|
389
|
+
const selectedPayment = options.successResponse.paymentProvider.replace(/\s+/g, '');
|
|
390
|
+
const action = `Donated-${selectedPayment}-upsell`;
|
|
391
|
+
const label = options.successResponse.donationType;
|
|
392
|
+
this.analytics.logDonationFlowEvent(action, label);
|
|
393
|
+
|
|
394
|
+
this.braintreeManager.donationSuccessful(options);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
static getDefaultUpsellAmount(oneTimeAmount: number): number {
|
|
398
|
+
let amount = 5;
|
|
399
|
+
|
|
400
|
+
if (oneTimeAmount <= 10) amount = 8;
|
|
401
|
+
else if (oneTimeAmount > 10 && oneTimeAmount <= 25) amount = 10;
|
|
402
|
+
else if (oneTimeAmount > 25 && oneTimeAmount <= 100) amount = 25;
|
|
403
|
+
else if (oneTimeAmount > 100) amount = 50;
|
|
404
|
+
|
|
405
|
+
return amount;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** @inheritdoc */
|
|
409
|
+
handleSuccessfulDonationResponse(
|
|
410
|
+
donationInfo: DonationPaymentInfo,
|
|
411
|
+
response: SuccessResponse,
|
|
412
|
+
): void {
|
|
413
|
+
switch (donationInfo.donationType) {
|
|
414
|
+
case DonationType.OneTime:
|
|
415
|
+
this.showUpsellModal({
|
|
416
|
+
oneTimeAmount: response.amount,
|
|
417
|
+
yesSelected: (amount: number) => {
|
|
418
|
+
this.upsellModalYesSelected(response, amount);
|
|
419
|
+
},
|
|
420
|
+
noSelected: () => {
|
|
421
|
+
this.showThankYouModal({ successResponse: response });
|
|
422
|
+
},
|
|
423
|
+
userClosedModalCallback: () => {
|
|
424
|
+
this.showThankYouModal({ successResponse: response });
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
break;
|
|
428
|
+
case DonationType.Monthly:
|
|
429
|
+
this.showThankYouModal({ successResponse: response });
|
|
430
|
+
break;
|
|
431
|
+
// This case will never be reached, it is only here for completeness.
|
|
432
|
+
// The upsell case gets handled in `modalYesSelected()` below
|
|
433
|
+
case DonationType.Upsell:
|
|
434
|
+
break;
|
|
435
|
+
default:
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|