-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_subscription.js
219 lines (190 loc) · 10.3 KB
/
_subscription.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// IIFE to not muddy up the global context
(function () {
let customer = JSON.parse(`{{ customer | json }}`);
const { settings } = ReCharge.Novum;
const { createSpinner, getPaymentMethodDetailsDom, getAddressDom } = ReCharge.Novum.DomCreators;
const { renderPaymentMethodDetails, renderAddress } = ReCharge.Novum.Components;
const { addAccessibleClickListener } = ReCharge.Novum.Utils;
// State of all the subscription data we use. Basically caches data we don't need to keep fetching
const state = {
paymentMethods: undefined,
shippingAddresses: undefined
};
/** Fetches the passed in request and stores it into our state */
async function fetchState({ content, request, key }) {
const loadingEl = document.createElement('div');
loadingEl.classList.add('loading', 'd-flex', 'justify-center', 'mt-5');
// Setup the loading spinner while we are fetching
loadingEl.append(createSpinner({ size: 42 }));
content.prepend(loadingEl);
if (!state[key]) {
state[key] = await request();
}
loadingEl.classList.add('d-none');
return state[key];
}
/** Renders the current address and it's payment method and forces a refetch the next time addresses are requested */
function updateCurrentAddress(address) {
renderAddress(address, document.querySelector('[data-shipping-address]'));
// Force a reload of addresses
delete state.shippingAddresses;
const paymentMethod = address.include.payment_methods[0]; // Selected is always the first
renderPaymentMethodDetails(paymentMethod, document.querySelector('[data-payment-method]'));
}
async function onUpdatePaymentMethod() {
const currentPaymentMethodEl = document.querySelector('.subscription-payment-method [data-payment-method]');
ReCharge.Drawer.open({
header: 'Change payment method',
content: `
<h4 class="rc-subheading">Current Payment Method</h4>
<div class="text-body-2">
${currentPaymentMethodEl.innerHTML}
</div>
<div class="divider my-5"></div>
<h4 class="rc-subheading">Other Payment Methods</h4>
<div class="other-payment-methods"></div>
` });
const otherPaymentMethodsEl = document.querySelector('.other-payment-methods');
const rcPaymentMethods = await fetchState({ key: 'paymentMethods', content: otherPaymentMethodsEl, request: ReCharge.Api.getPaymentMethods });
// Get the current payment method and check if it's sci. Only allow valid payment methods
const currentPaymentMethodId = Number(currentPaymentMethodEl.firstElementChild.getAttribute('data-id'));
const currentPaymentMethod = rcPaymentMethods.find(pm => pm.id === currentPaymentMethodId);
const isCurrentPMShopify = currentPaymentMethod?.processor_name === 'shopify-payments';
const validPaymentMethods = rcPaymentMethods.filter(pm => {
const isSameAsCurrent = pm.id === currentPaymentMethodId; // Don't allow same pm to be selected
const isShopify = pm.processor_name === 'shopify-payments';
const isShopifyAllowed = isCurrentPMShopify ? isShopify : !isShopify; // Only allow sci when it's already and sci
return !isSameAsCurrent && isShopifyAllowed;
});
// Add all the valid payment methods to the dom
validPaymentMethods.forEach((paymentMethod) => {
const paymentMethodEl = document.createElement('div');
paymentMethodEl.innerHTML = `
${getPaymentMethodDetailsDom(paymentMethod)}
<button class="update-payment-method rc-btn rc-btn--primary mt-3" data-id="${paymentMethod.id}">Use this Payment Method</button>
`;
otherPaymentMethodsEl.append(paymentMethodEl)
});
if (!validPaymentMethods.length) {
const emptyEl = document.createElement('p');
emptyEl.innerHTML = 'No other payment methods to choose from. Please go through the checkout to create a new payment method.';
otherPaymentMethodsEl.append(emptyEl);
}
// Go through and add the update events to all the valid payment methods
document.getElementById('te-modal').querySelectorAll('button.update-payment-method').forEach((el) => {
el.addEventListener('click', async (e) => {
const { subscription } = ReCharge.Novum;
try {
const paymentMethodId = Number(e.target.getAttribute('data-id'));
const { subscription: updatedSubscription, address: updatedAddress } = await ReCharge.Api.submitRequest(() => ReCharge.Api.updateSubscriptionPaymentMethod(subscription.id, paymentMethodId), {
key: 'updatePaymentMethod',
submitButton: e.target,
successMessage: 'Payment updated'
});
// Updating current subscription and adding the new address to it (subscription response doesn't have it associated)
ReCharge.Novum.subscription = { ...subscription, ...updatedSubscription, address: updatedAddress };
updateCurrentAddress(updatedAddress);
ReCharge.Drawer.close();
} catch (err) { }
});
});
}
async function onUpdateShippingAddress() {
const currentAddressEl = document.querySelector('.subscription-shipping-address [data-shipping-address]');
ReCharge.Drawer.open({
header: 'Change shipping address',
content: `
<h4 class="rc-subheading">Current Shipping Address</h4>
<div class="text-body-2">
${currentAddressEl.innerHTML}
</div>
<div class="divider my-5"></div>
<h4 class="rc-subheading">Other Shipping Addresses</h4>
<div class="other-shipping-addresses"></div>
` });
const otherShippingAddressesEl = document.querySelector('.other-shipping-addresses');
const rcShippingAddresses = await fetchState({ key: 'shippingAddresses', content: otherShippingAddressesEl, request: ReCharge.Api.getShippingAddresses });
const currentShippingAddressId = Number(currentAddressEl.firstElementChild.getAttribute('data-id'));
const currentShippingAddress = rcShippingAddresses.find(addr => addr.id === currentShippingAddressId);
// Get the current address and check if it's sci. Only allow valid addresses
const isCurrentShopifyAddress = currentShippingAddress.include.payment_methods[0].processor_name === 'shopify-payments';
const validShippingAddresses = rcShippingAddresses.filter(addr => {
const paymentMethod = addr.include.payment_methods[0];
if (!paymentMethod) return false; // Don't allow addresses without a payment method
const isSameAsCurrent = addr.id === currentShippingAddressId; // Don't allow same address to be selected
const isShopify = paymentMethod.processor_name === 'shopify-payments';
const isShopifyAllowed = isCurrentShopifyAddress ? isShopify : !isShopify; // Only allow sci when it's already and sci
return !isSameAsCurrent && isShopifyAllowed;
});
// Add all the valid addresses to the dom
validShippingAddresses.forEach((address) => {
const addressEl = document.createElement('div');
addressEl.innerHTML = `
${getAddressDom(address)}
<button class="update-shipping-address rc-btn rc-btn--primary mt-3" data-id="${address.id}">Use this Address</button>
`;
otherShippingAddressesEl.append(addressEl)
});
if (!validShippingAddresses.length) {
const emptyEl = document.createElement('p');
emptyEl.innerHTML = 'No other addresses to choose from. Please go through the checkout to create a new payment method.';
otherShippingAddressesEl.append(emptyEl);
}
// Go through and add the update events to all the valid addresses
document.getElementById('te-modal').querySelectorAll('button.update-shipping-address').forEach((el) => {
el.addEventListener('click', async (e) => {
const { subscription } = ReCharge.Novum;
try {
const addressId = Number(e.target.getAttribute('data-id'));
// Mocked for now until endpoint exists
const { subscription: updatedSubscription, address: updatedAddress } = await ReCharge.Api.submitRequest(() => ReCharge.Api.updateSubscriptionAddress(subscription.id, addressId), {
key: 'updateShippingAddress',
submitButton: e.target,
successMessage: 'Shipping address updated'
});
// Updating current subscription and adding the new address to it (subscription response doesn't have it associated)
ReCharge.Novum.subscription = { ...subscription, ...updatedSubscription, address: updatedAddress };
updateCurrentAddress(updatedAddress);
ReCharge.Drawer.close();
} catch (err) { }
});
});
}
function onEditEmailClick() {
ReCharge.Drawer.open({
header: 'Edit email address',
content: `
<p class="rc-subtext text-center">Updating this email address will update your default email for all subscriptions</p>
<form id="RechargeEmailForm">
<div role="group" class="rc-form-control mt-2">
<label id="email-label" for="email" class="rc-form__label">{{ 'Email' | t }}</label>
<input type="text" id="email" class="rc-input" type="text" name="email" value="${customer.email}">
</div>
<button type="submit" class="update-email rc-btn rc-btn--primary">Update</button>
</form>
` });
document.forms.RechargeEmailForm.addEventListener('submit', async (e) => {
e.preventDefault();
try {
const email = document.getElementById('email').value;
const updatedCustomer = await ReCharge.Api.submitRequest(() => ReCharge.Api.updateCustomer({ email }), {
key: 'updateEmail',
submitButton: e.target.querySelector('button[type="submit"]'),
successMessage: 'Email address updated'
});
// Update the customers email
customer = updatedCustomer;
document.querySelector('.customer-email .email').innerHTML = customer.email;
ReCharge.Drawer.close();
} catch (err) { }
return false;
});
}
updateCurrentAddress(ReCharge.Novum.subscription.address);
addAccessibleClickListener(document.querySelector('.subscription-payment-method'), onUpdatePaymentMethod);
addAccessibleClickListener(document.querySelector('.customer-email'), onEditEmailClick);
// Don't allow user to edit address if it's turned off
if (settings.customer_portal.edit_shipping_address) {
addAccessibleClickListener(document.querySelector('.subscription-shipping-address'), onUpdateShippingAddress);
}
})()