@occluze/tether 0.6.4 → 0.6.6
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/README.md +3 -3
- package/dist/esm/chunks/account-QUBHQG3C.js +1 -0
- package/dist/esm/chunks/account-pages-VWDHF6WA.js +1 -0
- package/dist/esm/chunks/chunk-VPVJPNB4.js +1 -0
- package/dist/esm/chunks/{diagnose-4JHU6RTC.js → diagnose-VXQBSD3A.js} +6 -3
- package/dist/esm/index.js +1 -1
- package/dist/tether.account-pages.js +579 -0
- package/dist/tether.account-pages.min.js +1 -0
- package/dist/tether.account.js +64 -15
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.diagnose.js +9 -2
- package/dist/tether.diagnose.min.js +6 -3
- package/dist/tether.js +3 -5
- package/dist/tether.min.js +2 -2
- package/dist/tether.min.js.map +3 -3
- package/package.json +1 -1
- package/src/account-pages.js +305 -0
- package/src/account.js +56 -12
- package/src/diagnose.js +5 -1
- package/src/index.js +2 -5
- package/src/lazy-iife.js +3 -0
- package/src/lazy.js +1 -0
- package/src/parts/account-pages.js +3 -0
- package/types/index.d.ts +27 -1
- package/dist/esm/chunks/account-NVHPA7AX.js +0 -1
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/account-pages.js
|
|
9
|
+
var account_pages_exports = {};
|
|
10
|
+
__export(account_pages_exports, {
|
|
11
|
+
addresses: () => addresses,
|
|
12
|
+
deleteAddress: () => deleteAddress,
|
|
13
|
+
order: () => order,
|
|
14
|
+
renderPages: () => renderPages,
|
|
15
|
+
requestReturn: () => requestReturn,
|
|
16
|
+
saveAddress: () => saveAddress,
|
|
17
|
+
setup: () => setup,
|
|
18
|
+
subscriptionAction: () => subscriptionAction,
|
|
19
|
+
subscriptions: () => subscriptions,
|
|
20
|
+
updateProfile: () => updateProfile
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// tether-core:config.js
|
|
24
|
+
var m = window.Tether.__core["config.js"];
|
|
25
|
+
var { DEFAULTS, cfg, configure, isConfigured, log, reportError, warn } = m;
|
|
26
|
+
|
|
27
|
+
// tether-core:client.js
|
|
28
|
+
var m2 = window.Tether.__core["client.js"];
|
|
29
|
+
var { TetherError, endpoint, gql, request, unwrap, withContext } = m2;
|
|
30
|
+
|
|
31
|
+
// tether-core:dom.js
|
|
32
|
+
var m3 = window.Tether.__core["dom.js"];
|
|
33
|
+
var { attr, busy, cdnUrl, dataKey, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, readText, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setText, setTextTracked, show, toAttributes, watchImages } = m3;
|
|
34
|
+
|
|
35
|
+
// server/src/account-ops.js
|
|
36
|
+
var MONEY = "amount currencyCode";
|
|
37
|
+
var ADDRESS = "id firstName lastName company address1 address2 city province zoneCode zip country countryCode phoneNumber formatted";
|
|
38
|
+
var Q = {
|
|
39
|
+
order: `query TetherOrder($id:ID!){order(id:$id){id name number processedAt cancelledAt financialStatus fulfillmentStatus statusPageUrl requiresShipping totalPrice{${MONEY}}subtotal{${MONEY}}totalShipping{${MONEY}}totalTax{${MONEY}}shippingAddress{${ADDRESS}}billingAddress{${ADDRESS}}lineItems(first:50){nodes{id name title variantTitle quantity sku image{url altText}price{${MONEY}}totalPrice{${MONEY}}suggestedReturnReasonDefinitions(first:10){nodes{id name handle}}}}fulfillments(first:10){nodes{id status createdAt estimatedDeliveryAt latestShipmentStatus trackingInformation{company number url}}}returnInformation{returnableLineItems(first:50){nodes{quantity lineItem{id}}}}returns(first:10){nodes{id status}}}}`,
|
|
40
|
+
addresses: `query TetherAddresses{customer{defaultAddress{id}addresses(first:20){nodes{${ADDRESS}}}}}`,
|
|
41
|
+
subscriptions: `query TetherSubscriptions{customer{subscriptionContracts(first:20,reverse:true){nodes{id status nextBillingDate currencyCode deliveryPrice{${MONEY}}deliveryPolicy{interval intervalCount{count}}lines(first:20){nodes{id name title variantTitle quantity sku currentPrice{${MONEY}}lineDiscountedPrice{${MONEY}}image{url altText}}}upcomingBillingCycles(first:3){nodes{cycleIndex skipped billingAttemptExpectedDate}}}}}}`,
|
|
42
|
+
contract: `query TetherContract($id:ID!){customer{subscriptionContract(id:$id){id status upcomingBillingCycles(first:3){nodes{cycleIndex skipped}}}}}`
|
|
43
|
+
};
|
|
44
|
+
var M = {
|
|
45
|
+
profile: "mutation TetherProfile($input: CustomerUpdateInput!) { customerUpdate(input: $input) { customer { firstName lastName } userErrors { field message } } }",
|
|
46
|
+
addressCreate: `mutation TetherAddressCreate($address:CustomerAddressInput!,$default:Boolean){customerAddressCreate(address:$address,defaultAddress:$default){customerAddress{${ADDRESS}}userErrors{field message}}}`,
|
|
47
|
+
addressUpdate: `mutation TetherAddressUpdate($id:ID!,$address:CustomerAddressInput,$default:Boolean){customerAddressUpdate(addressId:$id,address:$address,defaultAddress:$default){customerAddress{${ADDRESS}}userErrors{field message}}}`,
|
|
48
|
+
addressDelete: "mutation TetherAddressDelete($id: ID!) { customerAddressDelete(addressId: $id) { deletedAddressId userErrors { field message } } }",
|
|
49
|
+
pause: "mutation TetherPause($id: ID!) { subscriptionContractPause(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",
|
|
50
|
+
resume: "mutation TetherResume($id: ID!) { subscriptionContractActivate(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",
|
|
51
|
+
cancel: "mutation TetherCancel($id: ID!) { subscriptionContractCancel(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",
|
|
52
|
+
skip: "mutation TetherSkip($input: SubscriptionBillingCycleInput!) { subscriptionBillingCycleSkip(billingCycleInput: $input) { billingCycle { cycleIndex skipped } userErrors { field message } } }",
|
|
53
|
+
unskip: "mutation TetherUnskip($input: SubscriptionBillingCycleInput!) { subscriptionBillingCycleUnskip(billingCycleInput: $input) { billingCycle { cycleIndex skipped } userErrors { field message } } }",
|
|
54
|
+
returnRequest: "mutation TetherReturn($orderId: ID!, $lines: [RequestedLineItemInput!]!) { orderRequestReturn(orderId: $orderId, requestedLineItems: $lines) { return { id status } userErrors { field message } } }"
|
|
55
|
+
};
|
|
56
|
+
var InputError = class extends Error {
|
|
57
|
+
};
|
|
58
|
+
var gid = (type) => new RegExp(`^gid://shopify/${type}/\\d+(\\?[\\w=&.-]{1,80})?$`);
|
|
59
|
+
var IDS = {
|
|
60
|
+
Order: gid("Order"),
|
|
61
|
+
CustomerAddress: gid("CustomerAddress"),
|
|
62
|
+
SubscriptionContract: gid("SubscriptionContract"),
|
|
63
|
+
LineItem: gid("LineItem"),
|
|
64
|
+
ReturnReasonDefinition: gid("ReturnReasonDefinition")
|
|
65
|
+
};
|
|
66
|
+
function idOf(type, value) {
|
|
67
|
+
const v = /^\d{1,20}$/.test(String(value ?? "")) ? `gid://shopify/${type}/${value}` : String(value ?? "");
|
|
68
|
+
if (!IDS[type].test(v)) throw new InputError(`${type} id`);
|
|
69
|
+
return v;
|
|
70
|
+
}
|
|
71
|
+
var text = (v, max = 255) => {
|
|
72
|
+
if (v == null || v === "") return void 0;
|
|
73
|
+
if (typeof v !== "string" && typeof v !== "number") throw new InputError("text");
|
|
74
|
+
const s = String(v).replace(/[\u0000-\u001f\u007f]/g, "").trim();
|
|
75
|
+
if (s.length > max) throw new InputError("too long");
|
|
76
|
+
return s;
|
|
77
|
+
};
|
|
78
|
+
var ADDRESS_FIELDS = ["firstName", "lastName", "company", "address1", "address2", "city", "zip", "zoneCode", "phoneNumber"];
|
|
79
|
+
function addressInput(a = {}) {
|
|
80
|
+
if (!a || typeof a !== "object" || Array.isArray(a)) throw new InputError("address");
|
|
81
|
+
const out = {};
|
|
82
|
+
ADDRESS_FIELDS.forEach((k) => {
|
|
83
|
+
const v = text(a[k]);
|
|
84
|
+
if (v !== void 0) out[k] = v;
|
|
85
|
+
});
|
|
86
|
+
if (a.countryCode != null && a.countryCode !== "") {
|
|
87
|
+
const c = String(a.countryCode).toUpperCase();
|
|
88
|
+
if (!/^[A-Z]{2}$/.test(c)) throw new InputError("countryCode");
|
|
89
|
+
out.countryCode = c;
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
var userErrors = (payload) => {
|
|
94
|
+
const errs = payload?.userErrors || [];
|
|
95
|
+
if (errs.length) {
|
|
96
|
+
const e = new InputError(errs.map((x) => x.message).join(" | "));
|
|
97
|
+
e.userErrors = errs;
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
return payload;
|
|
101
|
+
};
|
|
102
|
+
var ops = {
|
|
103
|
+
async order(ask, { id }) {
|
|
104
|
+
const data = await ask(Q.order, { id: idOf("Order", id) });
|
|
105
|
+
return { order: data?.order || null };
|
|
106
|
+
},
|
|
107
|
+
async profile(ask, { firstName, lastName }) {
|
|
108
|
+
const input = {};
|
|
109
|
+
if (firstName !== void 0) input.firstName = text(firstName, 100) ?? "";
|
|
110
|
+
if (lastName !== void 0) input.lastName = text(lastName, 100) ?? "";
|
|
111
|
+
if (!Object.keys(input).length) throw new InputError("nothing to change");
|
|
112
|
+
const p = userErrors((await ask(M.profile, { input }))?.customerUpdate);
|
|
113
|
+
return { customer: p.customer };
|
|
114
|
+
},
|
|
115
|
+
async addresses(ask) {
|
|
116
|
+
const c = (await ask(Q.addresses, {}))?.customer;
|
|
117
|
+
const def = c?.defaultAddress?.id || null;
|
|
118
|
+
return { addresses: (c?.addresses?.nodes || []).map((a) => ({ ...a, isDefault: a.id === def })) };
|
|
119
|
+
},
|
|
120
|
+
async saveAddress(ask, { id, address, isDefault }) {
|
|
121
|
+
const a = addressInput(address || {});
|
|
122
|
+
const def = isDefault === true ? true : void 0;
|
|
123
|
+
const p = id ? userErrors((await ask(M.addressUpdate, { id: idOf("CustomerAddress", id), address: Object.keys(a).length ? a : null, default: def ?? null }))?.customerAddressUpdate) : userErrors((await ask(M.addressCreate, { address: a, default: def ?? false }))?.customerAddressCreate);
|
|
124
|
+
return { address: p.customerAddress };
|
|
125
|
+
},
|
|
126
|
+
async deleteAddress(ask, { id }) {
|
|
127
|
+
const p = userErrors((await ask(M.addressDelete, { id: idOf("CustomerAddress", id) }))?.customerAddressDelete);
|
|
128
|
+
return { deleted: p.deletedAddressId };
|
|
129
|
+
},
|
|
130
|
+
async subscriptions(ask) {
|
|
131
|
+
return { subscriptions: (await ask(Q.subscriptions, {}))?.customer?.subscriptionContracts?.nodes || [] };
|
|
132
|
+
},
|
|
133
|
+
async subscription(ask, { id, action }) {
|
|
134
|
+
if (!["pause", "resume", "skip", "unskip", "cancel"].includes(action)) throw new InputError("action");
|
|
135
|
+
const contractId = idOf("SubscriptionContract", id);
|
|
136
|
+
const contract = (await ask(Q.contract, { id: contractId }))?.customer?.subscriptionContract;
|
|
137
|
+
if (!contract) {
|
|
138
|
+
const e = new InputError("not found");
|
|
139
|
+
e.status = 404;
|
|
140
|
+
throw e;
|
|
141
|
+
}
|
|
142
|
+
if (action === "skip" || action === "unskip") {
|
|
143
|
+
const cycles = contract.upcomingBillingCycles?.nodes || [];
|
|
144
|
+
const cycle = action === "skip" ? cycles.find((c) => !c.skipped) : cycles.find((c) => c.skipped);
|
|
145
|
+
if (!cycle) throw new InputError(action === "skip" ? "no upcoming delivery to skip" : "nothing skipped");
|
|
146
|
+
const p2 = userErrors((await ask(M[action], { input: { contractId, selector: { index: cycle.cycleIndex } } }))?.[action === "skip" ? "subscriptionBillingCycleSkip" : "subscriptionBillingCycleUnskip"]);
|
|
147
|
+
return { billingCycle: p2.billingCycle };
|
|
148
|
+
}
|
|
149
|
+
const name = { pause: "subscriptionContractPause", resume: "subscriptionContractActivate", cancel: "subscriptionContractCancel" }[action];
|
|
150
|
+
const p = userErrors((await ask(M[action], { id: contractId }))?.[name]);
|
|
151
|
+
return { contract: p.contract };
|
|
152
|
+
},
|
|
153
|
+
async requestReturn(ask, { orderId, lines: lines2 }) {
|
|
154
|
+
const oid = idOf("Order", orderId);
|
|
155
|
+
if (!Array.isArray(lines2) || !lines2.length || lines2.length > 50) throw new InputError("lines");
|
|
156
|
+
const requested = lines2.map((l) => {
|
|
157
|
+
const q = Number(l?.quantity);
|
|
158
|
+
if (!Number.isInteger(q) || q < 1 || q > 1e3) throw new InputError("quantity");
|
|
159
|
+
const out = { lineItemId: idOf("LineItem", l.lineItemId), quantity: q };
|
|
160
|
+
if (l.reasonId) out.returnReasonDefinitionId = idOf("ReturnReasonDefinition", l.reasonId);
|
|
161
|
+
const note = text(l.note, 300);
|
|
162
|
+
if (note) out.customerNote = note;
|
|
163
|
+
return out;
|
|
164
|
+
});
|
|
165
|
+
const p = userErrors((await ask(M.returnRequest, { orderId: oid, lines: requested }))?.orderRequestReturn);
|
|
166
|
+
return { return: p.return };
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/account-pages.js
|
|
171
|
+
var ctx = null;
|
|
172
|
+
var bound = false;
|
|
173
|
+
function setup(c) {
|
|
174
|
+
ctx = c;
|
|
175
|
+
}
|
|
176
|
+
var https = (u) => {
|
|
177
|
+
try {
|
|
178
|
+
return new URL(u).protocol === "https:";
|
|
179
|
+
} catch {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
var date = (s) => {
|
|
184
|
+
try {
|
|
185
|
+
return new Date(s).toLocaleDateString(cfg.locale || void 0);
|
|
186
|
+
} catch {
|
|
187
|
+
return s;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
var ROUTE = {
|
|
191
|
+
order: (i) => ["GET", `/order?id=${encodeURIComponent(i.id)}`],
|
|
192
|
+
addresses: () => ["GET", "/addresses"],
|
|
193
|
+
subscriptions: () => ["GET", "/subscriptions"],
|
|
194
|
+
profile: () => ["POST", "/profile"],
|
|
195
|
+
saveAddress: () => ["POST", "/address"],
|
|
196
|
+
deleteAddress: () => ["POST", "/address/delete"],
|
|
197
|
+
subscription: () => ["POST", "/subscription"],
|
|
198
|
+
requestReturn: () => ["POST", "/return"]
|
|
199
|
+
};
|
|
200
|
+
async function run(name, input = {}) {
|
|
201
|
+
const { server, serverFetch, query } = ctx;
|
|
202
|
+
if (server()) {
|
|
203
|
+
const [method, path] = ROUTE[name](input);
|
|
204
|
+
const data = await serverFetch(path, method === "POST" ? { method, body: input } : {});
|
|
205
|
+
if (data.loggedIn === false) throw new TetherError("Not logged in", { code: "NOT_LOGGED_IN", status: 401 });
|
|
206
|
+
return data;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
return await ops[name]((q, v) => query(q, v), input);
|
|
210
|
+
} catch (err) {
|
|
211
|
+
if (err instanceof InputError) throw new TetherError(err.message, { code: "INVALID", userErrors: err.userErrors });
|
|
212
|
+
throw err;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
var changed = (what) => {
|
|
216
|
+
ctx.reset();
|
|
217
|
+
emit("account-updated", { what });
|
|
218
|
+
};
|
|
219
|
+
var order = (id) => run("order", { id }).then((r) => r.order);
|
|
220
|
+
var updateProfile = ({ firstName, lastName } = {}) => run("profile", { firstName, lastName }).then((r) => {
|
|
221
|
+
changed("profile");
|
|
222
|
+
return r.customer;
|
|
223
|
+
});
|
|
224
|
+
var addresses = () => run("addresses").then((r) => r.addresses);
|
|
225
|
+
var saveAddress = (address, { id, isDefault } = {}) => run("saveAddress", { id, address, isDefault }).then((r) => {
|
|
226
|
+
changed("addresses");
|
|
227
|
+
return r.address;
|
|
228
|
+
});
|
|
229
|
+
var deleteAddress = (id) => run("deleteAddress", { id }).then((r) => {
|
|
230
|
+
changed("addresses");
|
|
231
|
+
return r.deleted;
|
|
232
|
+
});
|
|
233
|
+
var subscriptions = () => run("subscriptions").then((r) => r.subscriptions);
|
|
234
|
+
var subscriptionAction = (id, action) => run("subscription", { id, action }).then((r) => {
|
|
235
|
+
changed("subscriptions");
|
|
236
|
+
return r;
|
|
237
|
+
});
|
|
238
|
+
var requestReturn = (orderId, lines2) => run("requestReturn", { orderId, lines: lines2 }).then((r) => {
|
|
239
|
+
changed("orders");
|
|
240
|
+
return r.return;
|
|
241
|
+
});
|
|
242
|
+
var lower = (v) => v ? String(v).toLowerCase().replace(/_/g, " ") : "";
|
|
243
|
+
var lines = (a) => (a?.formatted || []).join(", ");
|
|
244
|
+
var showIn = (root, name, conds) => qsa(root, sel(name)).forEach((el) => {
|
|
245
|
+
const k = get(el, name);
|
|
246
|
+
if (k in conds) show(el, Boolean(conds[k]));
|
|
247
|
+
});
|
|
248
|
+
var showGlobal = (root, conds) => showIn(root, "show", conds);
|
|
249
|
+
function fillLines(box, items, returnable = null) {
|
|
250
|
+
repeat(box, items, (row, l) => {
|
|
251
|
+
const can = returnable ? returnable.get(l.id) || 0 : 0;
|
|
252
|
+
row.dataset.tetherLine = l.id;
|
|
253
|
+
qsa(row, sel("order-line")).concat(row.matches(sel("order-line")) ? [row] : []).forEach((el) => {
|
|
254
|
+
const k = get(el, "order-line");
|
|
255
|
+
if (k === "image") {
|
|
256
|
+
if (l.image) setImage(el, l.image.url, l.image.altText || l.title);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const v = { title: l.title || l.name, "variant-title": l.variantTitle || "", quantity: String(l.quantity), price: l.price ? formatMoney(l.price) : "", total: l.totalPrice ? formatMoney(l.totalPrice) : "", sku: l.sku || "", returnable: String(can) }[k];
|
|
260
|
+
if (v != null) setText(el, v);
|
|
261
|
+
});
|
|
262
|
+
showIn(row, "order-line-show", { returnable: can > 0 });
|
|
263
|
+
qsa(row, sel("return-quantity")).forEach((input) => {
|
|
264
|
+
input.max = String(can);
|
|
265
|
+
input.min = "0";
|
|
266
|
+
if (!input.value) input.value = "0";
|
|
267
|
+
input.disabled = can < 1;
|
|
268
|
+
});
|
|
269
|
+
qsa(row, `select${sel("return-reason")}`).forEach((select) => {
|
|
270
|
+
const reasons = l.suggestedReturnReasonDefinitions?.nodes || [];
|
|
271
|
+
if (select.dataset.tetherFilled !== l.id) {
|
|
272
|
+
select.dataset.tetherFilled = l.id;
|
|
273
|
+
reasons.forEach((r) => select.appendChild(new Option(r.name, r.id)));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
var SCOPE = { order: sel("order") };
|
|
279
|
+
async function renderOrder(el) {
|
|
280
|
+
const raw = get(el, "order") || "";
|
|
281
|
+
const key = raw.startsWith("url:") ? new URL(window.location.href).searchParams.get(raw.slice(4) || "id") : raw;
|
|
282
|
+
const state = (s) => el.setAttribute(attr("order-state"), s);
|
|
283
|
+
if (!key) {
|
|
284
|
+
state("not-found");
|
|
285
|
+
showIn(el, "order-show", { "not-found": true });
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
state("loading");
|
|
289
|
+
showIn(el, "order-show", { loading: true, ready: false, "not-found": false, error: false });
|
|
290
|
+
let o;
|
|
291
|
+
try {
|
|
292
|
+
o = await order(key);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
reportError(err, "order");
|
|
295
|
+
state("error");
|
|
296
|
+
showIn(el, "order-show", { loading: false, error: true });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (!o) {
|
|
300
|
+
state("not-found");
|
|
301
|
+
showIn(el, "order-show", { loading: false, "not-found": true });
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
el.dataset.tetherOrderId = o.id;
|
|
305
|
+
const returnable = new Map((o.returnInformation?.returnableLineItems?.nodes || []).map((r) => [r.lineItem?.id, r.quantity]));
|
|
306
|
+
const ships = o.fulfillments?.nodes || [];
|
|
307
|
+
qsa(el, sel("order-bind")).forEach((b) => {
|
|
308
|
+
const k = get(b, "order-bind");
|
|
309
|
+
if (k === "url") {
|
|
310
|
+
if (https(o.statusPageUrl)) b.setAttribute("href", o.statusPageUrl);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const v = {
|
|
314
|
+
name: o.name,
|
|
315
|
+
date: date(o.processedAt),
|
|
316
|
+
total: formatMoney(o.totalPrice),
|
|
317
|
+
subtotal: o.subtotal ? formatMoney(o.subtotal) : "",
|
|
318
|
+
shipping: o.totalShipping ? formatMoney(o.totalShipping) : "",
|
|
319
|
+
tax: o.totalTax ? formatMoney(o.totalTax) : "",
|
|
320
|
+
status: lower(o.financialStatus),
|
|
321
|
+
fulfillment: lower(o.fulfillmentStatus),
|
|
322
|
+
"shipping-address": lines(o.shippingAddress),
|
|
323
|
+
"billing-address": lines(o.billingAddress),
|
|
324
|
+
items: (o.lineItems?.nodes || []).map((l) => `${l.quantity}\xD7 ${l.title || l.name}`).join(", "),
|
|
325
|
+
cancelled: o.cancelledAt ? date(o.cancelledAt) : ""
|
|
326
|
+
}[k];
|
|
327
|
+
if (v != null) setText(b, v);
|
|
328
|
+
});
|
|
329
|
+
qsa(el, sel("order-lines")).forEach((box) => fillLines(box, o.lineItems?.nodes || [], returnable));
|
|
330
|
+
qsa(el, sel("order-fulfillments")).forEach((box) => repeat(box, ships, (row, f) => {
|
|
331
|
+
const t = f.trackingInformation?.[0] || {};
|
|
332
|
+
qsa(row, sel("fulfillment-bind")).concat(row.matches(sel("fulfillment-bind")) ? [row] : []).forEach((b) => {
|
|
333
|
+
const k = get(b, "fulfillment-bind");
|
|
334
|
+
if (k === "url") {
|
|
335
|
+
if (https(t.url)) b.setAttribute("href", t.url);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const v = { status: lower(f.latestShipmentStatus || f.status), date: date(f.createdAt), eta: f.estimatedDeliveryAt ? date(f.estimatedDeliveryAt) : "", company: t.company || "", number: t.number || "" }[k];
|
|
339
|
+
if (v != null) setText(b, v);
|
|
340
|
+
});
|
|
341
|
+
}));
|
|
342
|
+
showIn(el, "order-show", {
|
|
343
|
+
loading: false,
|
|
344
|
+
ready: true,
|
|
345
|
+
error: false,
|
|
346
|
+
"not-found": false,
|
|
347
|
+
cancelled: Boolean(o.cancelledAt),
|
|
348
|
+
shipped: ships.length > 0,
|
|
349
|
+
returnable: [...returnable.values()].some((q) => q > 0),
|
|
350
|
+
"has-returns": (o.returns?.nodes || []).length > 0,
|
|
351
|
+
"return-requested": el.dataset.tetherReturned === "1"
|
|
352
|
+
});
|
|
353
|
+
state("ready");
|
|
354
|
+
}
|
|
355
|
+
async function renderProfile(form) {
|
|
356
|
+
const c = await ctx.customer().catch(() => null);
|
|
357
|
+
if (!c) return;
|
|
358
|
+
["firstName", "lastName"].forEach((n) => {
|
|
359
|
+
const i = form.elements?.[n];
|
|
360
|
+
if (i && !i.dataset.tetherTouched) i.value = c[n] || "";
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
var addressCache = null;
|
|
364
|
+
async function renderAddresses(root) {
|
|
365
|
+
const boxes = qsa(root, sel("addresses"));
|
|
366
|
+
if (!boxes.length) return;
|
|
367
|
+
showGlobal(root, { "addresses-loading": true, "addresses-empty": false });
|
|
368
|
+
let list = [];
|
|
369
|
+
try {
|
|
370
|
+
list = addressCache = await addresses();
|
|
371
|
+
} catch (err) {
|
|
372
|
+
reportError(err, "addresses");
|
|
373
|
+
}
|
|
374
|
+
showGlobal(root, { "addresses-loading": false, "addresses-empty": list.length === 0 });
|
|
375
|
+
boxes.forEach((box) => repeat(box, list, (row, a) => {
|
|
376
|
+
row.dataset.tetherAddress = a.id;
|
|
377
|
+
qsa(row, sel("address-bind")).concat(row.matches(sel("address-bind")) ? [row] : []).forEach((b) => {
|
|
378
|
+
const v = { formatted: lines(a), name: [a.firstName, a.lastName].filter(Boolean).join(" "), company: a.company || "", address1: a.address1 || "", address2: a.address2 || "", city: a.city || "", zip: a.zip || "", province: a.province || "", country: a.country || "", phone: a.phoneNumber || "" }[get(b, "address-bind")];
|
|
379
|
+
if (v != null) setText(b, v);
|
|
380
|
+
});
|
|
381
|
+
showIn(row, "address-show", { default: a.isDefault, "not-default": !a.isDefault });
|
|
382
|
+
}));
|
|
383
|
+
}
|
|
384
|
+
var SUB_ACTIONS = ["pause", "resume", "skip", "unskip", "cancel"];
|
|
385
|
+
function subConds(c) {
|
|
386
|
+
const next = c.upcomingBillingCycles?.nodes?.[0];
|
|
387
|
+
const st = c.status;
|
|
388
|
+
return {
|
|
389
|
+
active: st === "ACTIVE",
|
|
390
|
+
paused: st === "PAUSED",
|
|
391
|
+
cancelled: st === "CANCELLED",
|
|
392
|
+
expired: st === "EXPIRED",
|
|
393
|
+
failed: st === "FAILED",
|
|
394
|
+
skipped: Boolean(next?.skipped),
|
|
395
|
+
"can-pause": st === "ACTIVE",
|
|
396
|
+
"can-resume": st === "PAUSED" || st === "FAILED",
|
|
397
|
+
"can-skip": st === "ACTIVE" && Boolean(next) && !next.skipped,
|
|
398
|
+
"can-unskip": st === "ACTIVE" && Boolean(next?.skipped),
|
|
399
|
+
"can-cancel": st === "ACTIVE" || st === "PAUSED" || st === "FAILED"
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
async function renderSubscriptions(root) {
|
|
403
|
+
const boxes = qsa(root, sel("subscriptions"));
|
|
404
|
+
if (!boxes.length) return;
|
|
405
|
+
showGlobal(root, { "subscriptions-loading": true, "subscriptions-empty": false });
|
|
406
|
+
let list = [];
|
|
407
|
+
try {
|
|
408
|
+
list = await subscriptions();
|
|
409
|
+
} catch (err) {
|
|
410
|
+
reportError(err, "subscriptions");
|
|
411
|
+
}
|
|
412
|
+
showGlobal(root, { "subscriptions-loading": false, "subscriptions-empty": list.length === 0 });
|
|
413
|
+
boxes.forEach((box) => repeat(box, list, (row, c) => {
|
|
414
|
+
row.dataset.tetherSubscription = c.id;
|
|
415
|
+
row.setAttribute(attr("subscription-status"), lower(c.status));
|
|
416
|
+
const ls = c.lines?.nodes || [];
|
|
417
|
+
const n = c.deliveryPolicy?.intervalCount?.count || 1;
|
|
418
|
+
const unit = lower(c.deliveryPolicy?.interval);
|
|
419
|
+
const total = ls.reduce((sum, l) => sum + parseFloat(l.lineDiscountedPrice?.amount || 0), 0);
|
|
420
|
+
qsa(row, sel("subscription-bind")).forEach((b) => {
|
|
421
|
+
const k = get(b, "subscription-bind");
|
|
422
|
+
const v = {
|
|
423
|
+
status: lower(c.status),
|
|
424
|
+
next: c.nextBillingDate ? date(c.nextBillingDate) : "",
|
|
425
|
+
interval: unit ? n === 1 ? unit : `${n} ${unit}s` : "",
|
|
426
|
+
products: ls.map((l) => `${l.quantity}\xD7 ${l.title}`).join(", "),
|
|
427
|
+
total: ls.length ? formatMoney({ amount: String(total), currencyCode: c.currencyCode }) : "",
|
|
428
|
+
delivery: c.deliveryPrice ? formatMoney(c.deliveryPrice) : ""
|
|
429
|
+
}[k];
|
|
430
|
+
if (v != null) setText(b, v);
|
|
431
|
+
});
|
|
432
|
+
qsa(row, sel("subscription-lines")).forEach((lb) => repeat(lb, ls, (lr, l) => {
|
|
433
|
+
qsa(lr, sel("subscription-line")).concat(lr.matches(sel("subscription-line")) ? [lr] : []).forEach((b) => {
|
|
434
|
+
const k = get(b, "subscription-line");
|
|
435
|
+
if (k === "image") {
|
|
436
|
+
if (l.image) setImage(b, l.image.url, l.image.altText || l.title);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const v = { title: l.title, "variant-title": l.variantTitle || "", quantity: String(l.quantity), price: formatMoney(l.currentPrice) }[k];
|
|
440
|
+
if (v != null) setText(b, v);
|
|
441
|
+
});
|
|
442
|
+
}));
|
|
443
|
+
const conds = subConds(c);
|
|
444
|
+
showIn(row, "subscription-show", conds);
|
|
445
|
+
qsa(row, sel("subscription-action")).forEach((btn) => {
|
|
446
|
+
const a = get(btn, "subscription-action");
|
|
447
|
+
const ok = conds[`can-${a}`];
|
|
448
|
+
btn.disabled = !ok;
|
|
449
|
+
btn.classList.toggle("is-disabled", !ok);
|
|
450
|
+
});
|
|
451
|
+
}));
|
|
452
|
+
}
|
|
453
|
+
async function renderPages(root = document) {
|
|
454
|
+
if (!bound) {
|
|
455
|
+
bound = true;
|
|
456
|
+
bindPages();
|
|
457
|
+
}
|
|
458
|
+
await Promise.all([
|
|
459
|
+
...qsa(root, sel("order")).map((el) => renderOrder(el)),
|
|
460
|
+
...qsa(root, sel("profile-form")).map((f) => renderProfile(f)),
|
|
461
|
+
renderAddresses(root),
|
|
462
|
+
renderSubscriptions(root)
|
|
463
|
+
]);
|
|
464
|
+
}
|
|
465
|
+
var fieldsOf = (form) => Object.fromEntries([...form.elements].filter((i) => i.name && i.type !== "submit" && i.type !== "button" && i.type !== "checkbox").map((i) => [i.name, i.value]));
|
|
466
|
+
async function act(el, fn, { error } = {}) {
|
|
467
|
+
el.classList.add("is-busy");
|
|
468
|
+
el.setAttribute("aria-busy", "true");
|
|
469
|
+
el.setAttribute(attr("form-state"), "pending");
|
|
470
|
+
qsa(el, sel("form-error")).forEach((e) => setText(e, ""));
|
|
471
|
+
try {
|
|
472
|
+
const out = await fn();
|
|
473
|
+
el.setAttribute(attr("form-state"), "saved");
|
|
474
|
+
return out;
|
|
475
|
+
} catch (err) {
|
|
476
|
+
el.setAttribute(attr("form-state"), "error");
|
|
477
|
+
const msg = err?.userErrors?.map((u) => u.message).join(" ") || err?.message || "Something went wrong";
|
|
478
|
+
qsa(el, sel("form-error")).forEach((e) => setText(e, msg.replace(/^Customer accounts: /, "")));
|
|
479
|
+
if (error) reportError(err, error);
|
|
480
|
+
return void 0;
|
|
481
|
+
} finally {
|
|
482
|
+
el.classList.remove("is-busy");
|
|
483
|
+
el.removeAttribute("aria-busy");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function bindPages() {
|
|
487
|
+
document.addEventListener("submit", (e) => {
|
|
488
|
+
const f = e.target;
|
|
489
|
+
if (f.matches?.(sel("profile-form"))) {
|
|
490
|
+
e.preventDefault();
|
|
491
|
+
act(f, () => updateProfile(fieldsOf(f)));
|
|
492
|
+
} else if (f.matches?.(sel("address-form"))) {
|
|
493
|
+
e.preventDefault();
|
|
494
|
+
const id = f.dataset.tetherAddressId || void 0;
|
|
495
|
+
const isDefault = Boolean(f.elements?.isDefault?.checked);
|
|
496
|
+
act(f, async () => {
|
|
497
|
+
await saveAddress(fieldsOf(f), { id, isDefault });
|
|
498
|
+
f.reset();
|
|
499
|
+
delete f.dataset.tetherAddressId;
|
|
500
|
+
await renderAddresses(document);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
document.addEventListener("input", (e) => {
|
|
505
|
+
if (e.target.closest?.(sel("profile-form"))) e.target.dataset.tetherTouched = "1";
|
|
506
|
+
});
|
|
507
|
+
document.addEventListener("click", (e) => {
|
|
508
|
+
const t = e.target;
|
|
509
|
+
const row = t.closest?.("[data-tether-address]");
|
|
510
|
+
const confirmOk = (btn2) => {
|
|
511
|
+
const q = get(btn2, "confirm");
|
|
512
|
+
return !q || window.confirm(q);
|
|
513
|
+
};
|
|
514
|
+
let btn;
|
|
515
|
+
if ((btn = t.closest?.(sel("address-delete"))) && row) {
|
|
516
|
+
e.preventDefault();
|
|
517
|
+
if (confirmOk(btn)) act(row, async () => {
|
|
518
|
+
await deleteAddress(row.dataset.tetherAddress);
|
|
519
|
+
await renderAddresses(document);
|
|
520
|
+
});
|
|
521
|
+
} else if ((btn = t.closest?.(sel("address-default"))) && row) {
|
|
522
|
+
e.preventDefault();
|
|
523
|
+
act(row, async () => {
|
|
524
|
+
await saveAddress(null, { id: row.dataset.tetherAddress, isDefault: true });
|
|
525
|
+
await renderAddresses(document);
|
|
526
|
+
});
|
|
527
|
+
} else if ((btn = t.closest?.(sel("address-edit"))) && row) {
|
|
528
|
+
e.preventDefault();
|
|
529
|
+
const a = (addressCache || []).find((x) => x.id === row.dataset.tetherAddress);
|
|
530
|
+
const f = document.querySelector(sel("address-form"));
|
|
531
|
+
if (a && f) {
|
|
532
|
+
f.dataset.tetherAddressId = a.id;
|
|
533
|
+
[...f.elements].forEach((i) => {
|
|
534
|
+
if (i.name && i.name in a) i.value = a[i.name] ?? "";
|
|
535
|
+
if (i.name === "isDefault") i.checked = a.isDefault;
|
|
536
|
+
});
|
|
537
|
+
f.scrollIntoView?.({ block: "nearest" });
|
|
538
|
+
}
|
|
539
|
+
} else if (btn = t.closest?.(sel("address-new"))) {
|
|
540
|
+
const f = document.querySelector(sel("address-form"));
|
|
541
|
+
if (f) {
|
|
542
|
+
f.reset();
|
|
543
|
+
delete f.dataset.tetherAddressId;
|
|
544
|
+
}
|
|
545
|
+
} else if (btn = t.closest?.(sel("subscription-action"))) {
|
|
546
|
+
e.preventDefault();
|
|
547
|
+
const sub = btn.closest("[data-tether-subscription]");
|
|
548
|
+
const a = get(btn, "subscription-action");
|
|
549
|
+
if (!sub || !SUB_ACTIONS.includes(a) || btn.disabled || !confirmOk(btn)) return;
|
|
550
|
+
sub.setAttribute(attr("subscription-state"), "pending");
|
|
551
|
+
act(sub, async () => {
|
|
552
|
+
await subscriptionAction(sub.dataset.tetherSubscription, a);
|
|
553
|
+
await renderSubscriptions(document);
|
|
554
|
+
}).then(() => {
|
|
555
|
+
sub.setAttribute(attr("subscription-state"), sub.getAttribute(attr("form-state")) === "error" ? "error" : "done");
|
|
556
|
+
});
|
|
557
|
+
} else if (btn = t.closest?.(sel("order-return"))) {
|
|
558
|
+
e.preventDefault();
|
|
559
|
+
const scope = btn.closest(SCOPE.order);
|
|
560
|
+
if (!scope?.dataset.tetherOrderId) return;
|
|
561
|
+
const req = qsa(scope, "[data-tether-line]").map((r) => ({
|
|
562
|
+
lineItemId: r.dataset.tetherLine,
|
|
563
|
+
quantity: parseInt(r.querySelector(sel("return-quantity"))?.value || "0", 10),
|
|
564
|
+
reasonId: r.querySelector(sel("return-reason"))?.value || void 0,
|
|
565
|
+
note: r.querySelector(sel("return-note"))?.value || void 0
|
|
566
|
+
})).filter((l) => l.quantity > 0);
|
|
567
|
+
if (!req.length || !confirmOk(btn)) return;
|
|
568
|
+
act(scope, async () => {
|
|
569
|
+
await requestReturn(scope.dataset.tetherOrderId, req);
|
|
570
|
+
scope.dataset.tetherReturned = "1";
|
|
571
|
+
await renderOrder(scope);
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// src/parts/account-pages.js
|
|
578
|
+
window.Tether.__parts["account-pages"] = account_pages_exports;
|
|
579
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{var le=Object.defineProperty;var pe=(e,t)=>{for(var s in t)le(e,s,{get:t[s],enumerable:!0})};var M={};pe(M,{addresses:()=>re,deleteAddress:()=>ne,order:()=>te,renderPages:()=>De,requestReturn:()=>ae,saveAddress:()=>V,setup:()=>Ae,subscriptionAction:()=>oe,subscriptions:()=>ie,updateProfile:()=>se});var fe=window.Tether.__core["config.js"],{DEFAULTS:xe,cfg:Q,configure:ke,isConfigured:qe,log:Pe,reportError:q,warn:Re}=fe;var me=window.Tether.__core["client.js"],{TetherError:F,endpoint:Ue,gql:Le,request:Ne,unwrap:Be,withContext:je}=me;var he=window.Tether.__core["dom.js"],{attr:A,busy:Fe,cdnUrl:Ge,dataKey:Ve,emit:W,formatDate:ze,formatMoney:b,formatPercent:Me,get:y,has:Ke,hasTemplate:Je,imageUrl:Qe,notifyLayoutChanged:We,parseJSONAttr:Xe,productUrl:Ye,qsa:u,readText:Ze,repeat:v,repeatKeyed:He,sameImage:et,scoped:tt,sel:d,setImage:G,setSelected:st,setText:I,setTextTracked:rt,show:X,toAttributes:nt,watchImages:it}=he;var w="amount currencyCode",R="id firstName lastName company address1 address2 city province zoneCode zip country countryCode phoneNumber formatted",L={order:`query TetherOrder($id:ID!){order(id:$id){id name number processedAt cancelledAt financialStatus fulfillmentStatus statusPageUrl requiresShipping totalPrice{${w}}subtotal{${w}}totalShipping{${w}}totalTax{${w}}shippingAddress{${R}}billingAddress{${R}}lineItems(first:50){nodes{id name title variantTitle quantity sku image{url altText}price{${w}}totalPrice{${w}}suggestedReturnReasonDefinitions(first:10){nodes{id name handle}}}}fulfillments(first:10){nodes{id status createdAt estimatedDeliveryAt latestShipmentStatus trackingInformation{company number url}}}returnInformation{returnableLineItems(first:50){nodes{quantity lineItem{id}}}}returns(first:10){nodes{id status}}}}`,addresses:`query TetherAddresses{customer{defaultAddress{id}addresses(first:20){nodes{${R}}}}}`,subscriptions:`query TetherSubscriptions{customer{subscriptionContracts(first:20,reverse:true){nodes{id status nextBillingDate currencyCode deliveryPrice{${w}}deliveryPolicy{interval intervalCount{count}}lines(first:20){nodes{id name title variantTitle quantity sku currentPrice{${w}}lineDiscountedPrice{${w}}image{url altText}}}upcomingBillingCycles(first:3){nodes{cycleIndex skipped billingAttemptExpectedDate}}}}}}`,contract:"query TetherContract($id:ID!){customer{subscriptionContract(id:$id){id status upcomingBillingCycles(first:3){nodes{cycleIndex skipped}}}}}"},S={profile:"mutation TetherProfile($input: CustomerUpdateInput!) { customerUpdate(input: $input) { customer { firstName lastName } userErrors { field message } } }",addressCreate:`mutation TetherAddressCreate($address:CustomerAddressInput!,$default:Boolean){customerAddressCreate(address:$address,defaultAddress:$default){customerAddress{${R}}userErrors{field message}}}`,addressUpdate:`mutation TetherAddressUpdate($id:ID!,$address:CustomerAddressInput,$default:Boolean){customerAddressUpdate(addressId:$id,address:$address,defaultAddress:$default){customerAddress{${R}}userErrors{field message}}}`,addressDelete:"mutation TetherAddressDelete($id: ID!) { customerAddressDelete(addressId: $id) { deletedAddressId userErrors { field message } } }",pause:"mutation TetherPause($id: ID!) { subscriptionContractPause(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",resume:"mutation TetherResume($id: ID!) { subscriptionContractActivate(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",cancel:"mutation TetherCancel($id: ID!) { subscriptionContractCancel(subscriptionContractId: $id) { contract { id status } userErrors { field message } } }",skip:"mutation TetherSkip($input: SubscriptionBillingCycleInput!) { subscriptionBillingCycleSkip(billingCycleInput: $input) { billingCycle { cycleIndex skipped } userErrors { field message } } }",unskip:"mutation TetherUnskip($input: SubscriptionBillingCycleInput!) { subscriptionBillingCycleUnskip(billingCycleInput: $input) { billingCycle { cycleIndex skipped } userErrors { field message } } }",returnRequest:"mutation TetherReturn($orderId: ID!, $lines: [RequestedLineItemInput!]!) { orderRequestReturn(orderId: $orderId, requestedLineItems: $lines) { return { id status } userErrors { field message } } }"},p=class extends Error{},P=e=>new RegExp(`^gid://shopify/${e}/\\d+(\\?[\\w=&.-]{1,80})?$`),ge={Order:P("Order"),CustomerAddress:P("CustomerAddress"),SubscriptionContract:P("SubscriptionContract"),LineItem:P("LineItem"),ReturnReasonDefinition:P("ReturnReasonDefinition")};function T(e,t){let s=/^\d{1,20}$/.test(String(t??""))?`gid://shopify/${e}/${t}`:String(t??"");if(!ge[e].test(s))throw new p(`${e} id`);return s}var N=(e,t=255)=>{if(e==null||e==="")return;if(typeof e!="string"&&typeof e!="number")throw new p("text");let s=String(e).replace(/[\u0000-\u001f\u007f]/g,"").trim();if(s.length>t)throw new p("too long");return s},ye=["firstName","lastName","company","address1","address2","city","zip","zoneCode","phoneNumber"];function be(e={}){if(!e||typeof e!="object"||Array.isArray(e))throw new p("address");let t={};if(ye.forEach(s=>{let i=N(e[s]);i!==void 0&&(t[s]=i)}),e.countryCode!=null&&e.countryCode!==""){let s=String(e.countryCode).toUpperCase();if(!/^[A-Z]{2}$/.test(s))throw new p("countryCode");t.countryCode=s}return t}var D=e=>{let t=e?.userErrors||[];if(t.length){let s=new p(t.map(i=>i.message).join(" | "));throw s.userErrors=t,s}return e},Y={async order(e,{id:t}){return{order:(await e(L.order,{id:T("Order",t)}))?.order||null}},async profile(e,{firstName:t,lastName:s}){let i={};if(t!==void 0&&(i.firstName=N(t,100)??""),s!==void 0&&(i.lastName=N(s,100)??""),!Object.keys(i).length)throw new p("nothing to change");return{customer:D((await e(S.profile,{input:i}))?.customerUpdate).customer}},async addresses(e){let t=(await e(L.addresses,{}))?.customer,s=t?.defaultAddress?.id||null;return{addresses:(t?.addresses?.nodes||[]).map(i=>({...i,isDefault:i.id===s}))}},async saveAddress(e,{id:t,address:s,isDefault:i}){let r=be(s||{}),n=i===!0?!0:void 0;return{address:D(t?(await e(S.addressUpdate,{id:T("CustomerAddress",t),address:Object.keys(r).length?r:null,default:n??null}))?.customerAddressUpdate:(await e(S.addressCreate,{address:r,default:n??!1}))?.customerAddressCreate).customerAddress}},async deleteAddress(e,{id:t}){return{deleted:D((await e(S.addressDelete,{id:T("CustomerAddress",t)}))?.customerAddressDelete).deletedAddressId}},async subscriptions(e){return{subscriptions:(await e(L.subscriptions,{}))?.customer?.subscriptionContracts?.nodes||[]}},async subscription(e,{id:t,action:s}){if(!["pause","resume","skip","unskip","cancel"].includes(s))throw new p("action");let i=T("SubscriptionContract",t),r=(await e(L.contract,{id:i}))?.customer?.subscriptionContract;if(!r){let o=new p("not found");throw o.status=404,o}if(s==="skip"||s==="unskip"){let o=r.upcomingBillingCycles?.nodes||[],c=s==="skip"?o.find(m=>!m.skipped):o.find(m=>m.skipped);if(!c)throw new p(s==="skip"?"no upcoming delivery to skip":"nothing skipped");return{billingCycle:D((await e(S[s],{input:{contractId:i,selector:{index:c.cycleIndex}}}))?.[s==="skip"?"subscriptionBillingCycleSkip":"subscriptionBillingCycleUnskip"]).billingCycle}}let n={pause:"subscriptionContractPause",resume:"subscriptionContractActivate",cancel:"subscriptionContractCancel"}[s];return{contract:D((await e(S[s],{id:i}))?.[n]).contract}},async requestReturn(e,{orderId:t,lines:s}){let i=T("Order",t);if(!Array.isArray(s)||!s.length||s.length>50)throw new p("lines");let r=s.map(a=>{let o=Number(a?.quantity);if(!Number.isInteger(o)||o<1||o>1e3)throw new p("quantity");let c={lineItemId:T("LineItem",a.lineItemId),quantity:o};a.reasonId&&(c.returnReasonDefinitionId=T("ReturnReasonDefinition",a.reasonId));let f=N(a.note,300);return f&&(c.customerNote=f),c});return{return:D((await e(S.returnRequest,{orderId:i,lines:r}))?.orderRequestReturn).return}}};var _=null,Z=!1;function Ae(e){_=e}var H=e=>{try{return new URL(e).protocol==="https:"}catch{return!1}},O=e=>{try{return new Date(e).toLocaleDateString(Q.locale||void 0)}catch{return e}},Ie={order:e=>["GET",`/order?id=${encodeURIComponent(e.id)}`],addresses:()=>["GET","/addresses"],subscriptions:()=>["GET","/subscriptions"],profile:()=>["POST","/profile"],saveAddress:()=>["POST","/address"],deleteAddress:()=>["POST","/address/delete"],subscription:()=>["POST","/subscription"],requestReturn:()=>["POST","/return"]};async function E(e,t={}){let{server:s,serverFetch:i,query:r}=_;if(s()){let[n,a]=Ie[e](t),o=await i(a,n==="POST"?{method:n,body:t}:{});if(o.loggedIn===!1)throw new F("Not logged in",{code:"NOT_LOGGED_IN",status:401});return o}try{return await Y[e]((n,a)=>r(n,a),t)}catch(n){throw n instanceof p?new F(n.message,{code:"INVALID",userErrors:n.userErrors}):n}}var U=e=>{_.reset(),W("account-updated",{what:e})},te=e=>E("order",{id:e}).then(t=>t.order),se=({firstName:e,lastName:t}={})=>E("profile",{firstName:e,lastName:t}).then(s=>(U("profile"),s.customer)),re=()=>E("addresses").then(e=>e.addresses),V=(e,{id:t,isDefault:s}={})=>E("saveAddress",{id:t,address:e,isDefault:s}).then(i=>(U("addresses"),i.address)),ne=e=>E("deleteAddress",{id:e}).then(t=>(U("addresses"),t.deleted)),ie=()=>E("subscriptions").then(e=>e.subscriptions),oe=(e,t)=>E("subscription",{id:e,action:t}).then(s=>(U("subscriptions"),s)),ae=(e,t)=>E("requestReturn",{orderId:e,lines:t}).then(s=>(U("orders"),s.return));var k=e=>e?String(e).toLowerCase().replace(/_/g," "):"",z=e=>(e?.formatted||[]).join(", "),C=(e,t,s)=>u(e,d(t)).forEach(i=>{let r=y(i,t);r in s&&X(i,!!s[r])}),j=(e,t)=>C(e,"show",t);function we(e,t,s=null){v(e,t,(i,r)=>{let n=s&&s.get(r.id)||0;i.dataset.tetherLine=r.id,u(i,d("order-line")).concat(i.matches(d("order-line"))?[i]:[]).forEach(a=>{let o=y(a,"order-line");if(o==="image"){r.image&&G(a,r.image.url,r.image.altText||r.title);return}let c={title:r.title||r.name,"variant-title":r.variantTitle||"",quantity:String(r.quantity),price:r.price?b(r.price):"",total:r.totalPrice?b(r.totalPrice):"",sku:r.sku||"",returnable:String(n)}[o];c!=null&&I(a,c)}),C(i,"order-line-show",{returnable:n>0}),u(i,d("return-quantity")).forEach(a=>{a.max=String(n),a.min="0",a.value||(a.value="0"),a.disabled=n<1}),u(i,`select${d("return-reason")}`).forEach(a=>{let o=r.suggestedReturnReasonDefinitions?.nodes||[];a.dataset.tetherFilled!==r.id&&(a.dataset.tetherFilled=r.id,o.forEach(c=>a.appendChild(new Option(c.name,c.id))))})})}var Ce={order:d("order")};async function de(e){let t=y(e,"order")||"",s=t.startsWith("url:")?new URL(window.location.href).searchParams.get(t.slice(4)||"id"):t,i=o=>e.setAttribute(A("order-state"),o);if(!s){i("not-found"),C(e,"order-show",{"not-found":!0});return}i("loading"),C(e,"order-show",{loading:!0,ready:!1,"not-found":!1,error:!1});let r;try{r=await te(s)}catch(o){q(o,"order"),i("error"),C(e,"order-show",{loading:!1,error:!0});return}if(!r){i("not-found"),C(e,"order-show",{loading:!1,"not-found":!0});return}e.dataset.tetherOrderId=r.id;let n=new Map((r.returnInformation?.returnableLineItems?.nodes||[]).map(o=>[o.lineItem?.id,o.quantity])),a=r.fulfillments?.nodes||[];u(e,d("order-bind")).forEach(o=>{let c=y(o,"order-bind");if(c==="url"){H(r.statusPageUrl)&&o.setAttribute("href",r.statusPageUrl);return}let f={name:r.name,date:O(r.processedAt),total:b(r.totalPrice),subtotal:r.subtotal?b(r.subtotal):"",shipping:r.totalShipping?b(r.totalShipping):"",tax:r.totalTax?b(r.totalTax):"",status:k(r.financialStatus),fulfillment:k(r.fulfillmentStatus),"shipping-address":z(r.shippingAddress),"billing-address":z(r.billingAddress),items:(r.lineItems?.nodes||[]).map(m=>`${m.quantity}\xD7 ${m.title||m.name}`).join(", "),cancelled:r.cancelledAt?O(r.cancelledAt):""}[c];f!=null&&I(o,f)}),u(e,d("order-lines")).forEach(o=>we(o,r.lineItems?.nodes||[],n)),u(e,d("order-fulfillments")).forEach(o=>v(o,a,(c,f)=>{let m=f.trackingInformation?.[0]||{};u(c,d("fulfillment-bind")).concat(c.matches(d("fulfillment-bind"))?[c]:[]).forEach(h=>{let g=y(h,"fulfillment-bind");if(g==="url"){H(m.url)&&h.setAttribute("href",m.url);return}let l={status:k(f.latestShipmentStatus||f.status),date:O(f.createdAt),eta:f.estimatedDeliveryAt?O(f.estimatedDeliveryAt):"",company:m.company||"",number:m.number||""}[g];l!=null&&I(h,l)})})),C(e,"order-show",{loading:!1,ready:!0,error:!1,"not-found":!1,cancelled:!!r.cancelledAt,shipped:a.length>0,returnable:[...n.values()].some(o=>o>0),"has-returns":(r.returns?.nodes||[]).length>0,"return-requested":e.dataset.tetherReturned==="1"}),i("ready")}async function Ee(e){let t=await _.customer().catch(()=>null);t&&["firstName","lastName"].forEach(s=>{let i=e.elements?.[s];i&&!i.dataset.tetherTouched&&(i.value=t[s]||"")})}var ce=null;async function B(e){let t=u(e,d("addresses"));if(!t.length)return;j(e,{"addresses-loading":!0,"addresses-empty":!1});let s=[];try{s=ce=await re()}catch(i){q(i,"addresses")}j(e,{"addresses-loading":!1,"addresses-empty":s.length===0}),t.forEach(i=>v(i,s,(r,n)=>{r.dataset.tetherAddress=n.id,u(r,d("address-bind")).concat(r.matches(d("address-bind"))?[r]:[]).forEach(a=>{let o={formatted:z(n),name:[n.firstName,n.lastName].filter(Boolean).join(" "),company:n.company||"",address1:n.address1||"",address2:n.address2||"",city:n.city||"",zip:n.zip||"",province:n.province||"",country:n.country||"",phone:n.phoneNumber||""}[y(a,"address-bind")];o!=null&&I(a,o)}),C(r,"address-show",{default:n.isDefault,"not-default":!n.isDefault})}))}var Se=["pause","resume","skip","unskip","cancel"];function Te(e){let t=e.upcomingBillingCycles?.nodes?.[0],s=e.status;return{active:s==="ACTIVE",paused:s==="PAUSED",cancelled:s==="CANCELLED",expired:s==="EXPIRED",failed:s==="FAILED",skipped:!!t?.skipped,"can-pause":s==="ACTIVE","can-resume":s==="PAUSED"||s==="FAILED","can-skip":s==="ACTIVE"&&!!t&&!t.skipped,"can-unskip":s==="ACTIVE"&&!!t?.skipped,"can-cancel":s==="ACTIVE"||s==="PAUSED"||s==="FAILED"}}async function ue(e){let t=u(e,d("subscriptions"));if(!t.length)return;j(e,{"subscriptions-loading":!0,"subscriptions-empty":!1});let s=[];try{s=await ie()}catch(i){q(i,"subscriptions")}j(e,{"subscriptions-loading":!1,"subscriptions-empty":s.length===0}),t.forEach(i=>v(i,s,(r,n)=>{r.dataset.tetherSubscription=n.id,r.setAttribute(A("subscription-status"),k(n.status));let a=n.lines?.nodes||[],o=n.deliveryPolicy?.intervalCount?.count||1,c=k(n.deliveryPolicy?.interval),f=a.reduce((h,g)=>h+parseFloat(g.lineDiscountedPrice?.amount||0),0);u(r,d("subscription-bind")).forEach(h=>{let g=y(h,"subscription-bind"),l={status:k(n.status),next:n.nextBillingDate?O(n.nextBillingDate):"",interval:c?o===1?c:`${o} ${c}s`:"",products:a.map($=>`${$.quantity}\xD7 ${$.title}`).join(", "),total:a.length?b({amount:String(f),currencyCode:n.currencyCode}):"",delivery:n.deliveryPrice?b(n.deliveryPrice):""}[g];l!=null&&I(h,l)}),u(r,d("subscription-lines")).forEach(h=>v(h,a,(g,l)=>{u(g,d("subscription-line")).concat(g.matches(d("subscription-line"))?[g]:[]).forEach($=>{let K=y($,"subscription-line");if(K==="image"){l.image&&G($,l.image.url,l.image.altText||l.title);return}let J={title:l.title,"variant-title":l.variantTitle||"",quantity:String(l.quantity),price:b(l.currentPrice)}[K];J!=null&&I($,J)})}));let m=Te(n);C(r,"subscription-show",m),u(r,d("subscription-action")).forEach(h=>{let g=y(h,"subscription-action"),l=m[`can-${g}`];h.disabled=!l,h.classList.toggle("is-disabled",!l)})}))}async function De(e=document){Z||(Z=!0,$e()),await Promise.all([...u(e,d("order")).map(t=>de(t)),...u(e,d("profile-form")).map(t=>Ee(t)),B(e),ue(e)])}var ee=e=>Object.fromEntries([...e.elements].filter(t=>t.name&&t.type!=="submit"&&t.type!=="button"&&t.type!=="checkbox").map(t=>[t.name,t.value]));async function x(e,t,{error:s}={}){e.classList.add("is-busy"),e.setAttribute("aria-busy","true"),e.setAttribute(A("form-state"),"pending"),u(e,d("form-error")).forEach(i=>I(i,""));try{let i=await t();return e.setAttribute(A("form-state"),"saved"),i}catch(i){e.setAttribute(A("form-state"),"error");let r=i?.userErrors?.map(n=>n.message).join(" ")||i?.message||"Something went wrong";u(e,d("form-error")).forEach(n=>I(n,r.replace(/^Customer accounts: /,""))),s&&q(i,s);return}finally{e.classList.remove("is-busy"),e.removeAttribute("aria-busy")}}function $e(){document.addEventListener("submit",e=>{let t=e.target;if(t.matches?.(d("profile-form")))e.preventDefault(),x(t,()=>se(ee(t)));else if(t.matches?.(d("address-form"))){e.preventDefault();let s=t.dataset.tetherAddressId||void 0,i=!!t.elements?.isDefault?.checked;x(t,async()=>{await V(ee(t),{id:s,isDefault:i}),t.reset(),delete t.dataset.tetherAddressId,await B(document)})}}),document.addEventListener("input",e=>{e.target.closest?.(d("profile-form"))&&(e.target.dataset.tetherTouched="1")}),document.addEventListener("click",e=>{let t=e.target,s=t.closest?.("[data-tether-address]"),i=n=>{let a=y(n,"confirm");return!a||window.confirm(a)},r;if((r=t.closest?.(d("address-delete")))&&s)e.preventDefault(),i(r)&&x(s,async()=>{await ne(s.dataset.tetherAddress),await B(document)});else if((r=t.closest?.(d("address-default")))&&s)e.preventDefault(),x(s,async()=>{await V(null,{id:s.dataset.tetherAddress,isDefault:!0}),await B(document)});else if((r=t.closest?.(d("address-edit")))&&s){e.preventDefault();let n=(ce||[]).find(o=>o.id===s.dataset.tetherAddress),a=document.querySelector(d("address-form"));n&&a&&(a.dataset.tetherAddressId=n.id,[...a.elements].forEach(o=>{o.name&&o.name in n&&(o.value=n[o.name]??""),o.name==="isDefault"&&(o.checked=n.isDefault)}),a.scrollIntoView?.({block:"nearest"}))}else if(r=t.closest?.(d("address-new"))){let n=document.querySelector(d("address-form"));n&&(n.reset(),delete n.dataset.tetherAddressId)}else if(r=t.closest?.(d("subscription-action"))){e.preventDefault();let n=r.closest("[data-tether-subscription]"),a=y(r,"subscription-action");if(!n||!Se.includes(a)||r.disabled||!i(r))return;n.setAttribute(A("subscription-state"),"pending"),x(n,async()=>{await oe(n.dataset.tetherSubscription,a),await ue(document)}).then(()=>{n.setAttribute(A("subscription-state"),n.getAttribute(A("form-state"))==="error"?"error":"done")})}else if(r=t.closest?.(d("order-return"))){e.preventDefault();let n=r.closest(Ce.order);if(!n?.dataset.tetherOrderId)return;let a=u(n,"[data-tether-line]").map(o=>({lineItemId:o.dataset.tetherLine,quantity:parseInt(o.querySelector(d("return-quantity"))?.value||"0",10),reasonId:o.querySelector(d("return-reason"))?.value||void 0,note:o.querySelector(d("return-note"))?.value||void 0})).filter(o=>o.quantity>0);if(!a.length||!i(r))return;x(n,async()=>{await ae(n.dataset.tetherOrderId,a),n.dataset.tetherReturned="1",await de(n)})}})}window.Tether.__parts["account-pages"]=M;})();
|