@kasuvia/sdk 0.0.8 → 0.0.9
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 +42 -15
- package/dist/AddressAutocomplete-CjcqPElD.d.mts +46 -0
- package/dist/AddressAutocomplete-CvJHuRkf.d.ts +46 -0
- package/dist/components/index.d.mts +497 -0
- package/dist/components/index.d.ts +497 -0
- package/dist/components/index.js +4217 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +4194 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/server.d.mts +26 -0
- package/dist/config/server.d.ts +26 -0
- package/dist/config/server.js +38 -0
- package/dist/config/server.js.map +1 -0
- package/dist/config/server.mjs +13 -0
- package/dist/config/server.mjs.map +1 -0
- package/dist/hooks/index.d.mts +393 -160
- package/dist/hooks/index.d.ts +393 -160
- package/dist/hooks/index.js +2792 -2137
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +2734 -2121
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index-CNW_LINy.d.mts +578 -0
- package/dist/index-CNW_LINy.d.ts +578 -0
- package/dist/{index-C1chUA3P.d.mts → index-F7N6UItS.d.mts} +1 -1
- package/dist/{index-C1chUA3P.d.ts → index-F7N6UItS.d.ts} +1 -1
- package/dist/index-NkI10J_E.d.mts +40 -0
- package/dist/index-NkI10J_E.d.ts +40 -0
- package/dist/index.d.mts +20437 -103
- package/dist/index.d.ts +20437 -103
- package/dist/index.js +2111 -1802
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2006 -1786
- package/dist/index.mjs.map +1 -1
- package/dist/media.service-Cx7dQjzX.d.mts +1393 -0
- package/dist/media.service-mrBFJ2UQ.d.ts +1393 -0
- package/dist/services/index.d.mts +908 -2
- package/dist/services/index.d.ts +908 -2
- package/dist/services/index.js +1492 -1686
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +1431 -1670
- package/dist/services/index.mjs.map +1 -1
- package/package.json +46 -6
- package/src/components/bespoke/BespokeAvailabilityBadge.tsx +32 -0
- package/src/components/bespoke/BespokeProgressTracker.tsx +58 -0
- package/src/components/bespoke/index.ts +3 -0
- package/src/components/booking/SlotPicker.tsx +97 -0
- package/src/components/booking/index.ts +1 -0
- package/src/components/cart/CartItem.tsx +81 -0
- package/src/components/cart/CartSidebar.tsx +115 -0
- package/src/components/cart/CartTypeMismatchBanner.tsx +55 -0
- package/src/components/cart/index.ts +3 -0
- package/src/components/index.ts +8 -0
- package/src/components/orders/DeliverableReviewer.tsx +139 -0
- package/src/components/orders/index.ts +1 -0
- package/src/components/product/ProductCard.tsx +350 -0
- package/src/components/product/ProductGrid.tsx +84 -0
- package/src/components/product/index.ts +2 -0
- package/src/components/shared/AddressAutocomplete.tsx +212 -0
- package/src/components/shared/AnalyticsScripts.tsx +56 -0
- package/src/components/shared/CookieConsentBanner.tsx +98 -0
- package/src/components/shared/ImageEditorModal.tsx +1066 -0
- package/src/components/shared/ImageViewerModal.tsx +598 -0
- package/src/components/shared/LucideReactIcon.tsx +52 -0
- package/src/components/shared/MapPinDrop.tsx +101 -0
- package/src/components/shared/MultiSelectPicker.tsx +193 -0
- package/src/components/shared/OfflineBanner.tsx +46 -0
- package/src/components/shared/SearchableInput.tsx +153 -0
- package/src/components/shared/SearchablePopover.tsx +166 -0
- package/src/components/shared/SmartImage.tsx +311 -0
- package/src/components/shared/TruncatedValue.tsx +27 -0
- package/src/components/shared/UnsavedChangesGuard.tsx +138 -0
- package/src/components/shared/index.ts +15 -0
- package/src/components/skeletons/CardSkeleton.tsx +26 -0
- package/src/components/skeletons/CartItemSkeleton.tsx +26 -0
- package/src/components/skeletons/OrderItemSkeleton.tsx +26 -0
- package/src/components/skeletons/ProductCardSkeleton.tsx +26 -0
- package/src/components/skeletons/TableSkeleton.tsx +42 -0
- package/src/components/skeletons/index.ts +5 -0
- package/src/config/index.ts +22 -4
- package/src/config/server.ts +45 -0
- package/src/context/sdk-context.tsx +5 -2
- package/src/generated/auth-openapi.ts +2935 -0
- package/src/generated/cart-openapi.ts +652 -0
- package/src/generated/cms-openapi.ts +1668 -0
- package/src/generated/crm-openapi.ts +986 -0
- package/src/generated/graphql.ts +126 -0
- package/src/generated/index.ts +11 -0
- package/src/generated/media-openapi.ts +613 -0
- package/src/generated/notification-openapi.ts +862 -0
- package/src/generated/payment-openapi.ts +2713 -0
- package/src/generated/store-openapi.ts +9510 -0
- package/src/graphql/operations/collections.graphql +32 -0
- package/src/graphql/operations/products.graphql +197 -0
- package/src/graphql/operations/wishlist.graphql +25 -0
- package/src/hooks/index.ts +9 -2
- package/src/hooks/use-auth.ts +163 -69
- package/src/hooks/use-bespoke-availability.ts +39 -22
- package/src/hooks/use-business-config.ts +51 -0
- package/src/hooks/use-cart.ts +310 -238
- package/src/hooks/use-cms.ts +107 -127
- package/src/hooks/use-collections.ts +35 -55
- package/src/hooks/use-consultations.ts +9 -136
- package/src/hooks/use-countries.ts +19 -28
- package/src/hooks/use-currencies.ts +8 -20
- package/src/hooks/use-customer-address.ts +64 -0
- package/src/hooks/use-feedback.ts +34 -0
- package/src/hooks/use-languages.ts +26 -39
- package/src/hooks/use-media-upload.ts +23 -0
- package/src/hooks/use-notification-stream.ts +88 -0
- package/src/hooks/use-notifications.ts +163 -0
- package/src/hooks/use-order-stream.ts +29 -29
- package/src/hooks/use-orders.ts +91 -73
- package/src/hooks/use-payment.ts +116 -84
- package/src/hooks/use-products.ts +65 -269
- package/src/hooks/use-push-notifications.ts +122 -0
- package/src/hooks/use-reviews.ts +175 -0
- package/src/hooks/use-service-booking.ts +109 -132
- package/src/hooks/use-states.ts +16 -30
- package/src/hooks/use-wishlist.ts +44 -69
- package/src/index.ts +15 -11
- package/src/services/auth.service.ts +422 -132
- package/src/services/bespoke.service.ts +69 -10
- package/src/services/cart.service.ts +155 -186
- package/src/services/cms.service.ts +41 -50
- package/src/services/collection.service.ts +25 -63
- package/src/services/config.service.ts +10 -21
- package/src/services/consultation.service.ts +36 -93
- package/src/services/feedback.service.ts +76 -0
- package/src/services/index.ts +7 -1
- package/src/services/legal.service.ts +62 -0
- package/src/services/logistics.service.ts +235 -53
- package/src/services/media.service.ts +115 -0
- package/src/services/notifications.service.ts +204 -20
- package/src/services/order.service.ts +498 -127
- package/src/services/payment.service.ts +149 -100
- package/src/services/product.service.ts +157 -814
- package/src/services/review.service.ts +211 -0
- package/src/services/service-booking.service.ts +198 -99
- package/src/services/wishlist.service.ts +27 -74
- package/src/types/auth/index.ts +161 -18
- package/src/types/business/index.ts +9 -1
- package/src/types/cms/index.ts +91 -6
- package/src/types/cms/legal.ts +18 -0
- package/src/types/consultations/index.ts +60 -68
- package/src/types/index.ts +5 -3
- package/src/types/media/index.ts +35 -3
- package/src/types/payments/index.ts +80 -16
- package/src/types/reviews/index.ts +116 -0
- package/src/types/services/index.ts +113 -38
- package/src/types/store/checkout.ts +53 -0
- package/src/types/store/index.ts +273 -52
- package/src/types/store/invoice.ts +31 -0
- package/src/types/store/shipping.ts +84 -3
- package/src/types/ui/index.ts +1 -1
- package/src/utils/checkout.ts +19 -3
- package/src/utils/cookieConsent.ts +34 -0
- package/src/utils/format.ts +408 -0
- package/src/utils/geolocation.ts +134 -0
- package/src/utils/graphql-url.ts +47 -0
- package/src/utils/guest-session.ts +59 -0
- package/src/utils/http-client.ts +147 -0
- package/src/utils/index.ts +11 -4
- package/src/utils/status-colors.ts +79 -0
- package/src/utils/token-refresh.ts +115 -0
- package/src/utils/validators.ts +13 -0
- package/src/utils/youtube.ts +18 -0
- package/dist/index-C5YO9gTl.d.mts +0 -507
- package/dist/index-C5YO9gTl.d.ts +0 -507
- package/dist/index-CefG7_xq.d.mts +0 -793
- package/dist/index-DeHCf3zI.d.ts +0 -793
- package/src/graphql/collections.graphql.ts +0 -48
- package/src/graphql/index.ts +0 -7
- package/src/graphql/products.graphql.ts +0 -860
- package/src/graphql/wishlist.graphql.ts +0 -34
- package/src/hooks/use-consultation-stream.ts +0 -142
- package/src/types/bespoke/index.ts +0 -39
package/dist/services/index.mjs
CHANGED
|
@@ -1,3 +1,100 @@
|
|
|
1
|
+
// src/utils/token-refresh.ts
|
|
2
|
+
var GLOBAL_KEY = "__kasuviaSdkTokenRefreshRegistry__";
|
|
3
|
+
function getRegistry() {
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
if (!g[GLOBAL_KEY]) {
|
|
6
|
+
g[GLOBAL_KEY] = { handler: null, inFlight: null };
|
|
7
|
+
}
|
|
8
|
+
return g[GLOBAL_KEY];
|
|
9
|
+
}
|
|
10
|
+
async function refreshAccessToken() {
|
|
11
|
+
const registry = getRegistry();
|
|
12
|
+
if (!registry.handler) return null;
|
|
13
|
+
if (registry.inFlight) return registry.inFlight;
|
|
14
|
+
registry.inFlight = registry.handler().finally(() => {
|
|
15
|
+
registry.inFlight = null;
|
|
16
|
+
});
|
|
17
|
+
return registry.inFlight;
|
|
18
|
+
}
|
|
19
|
+
function hasRefreshHandler() {
|
|
20
|
+
return getRegistry().handler !== null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/utils/http-client.ts
|
|
24
|
+
var ApiError = class extends Error {
|
|
25
|
+
constructor(message, status, body) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "ApiError";
|
|
28
|
+
this.status = status;
|
|
29
|
+
this.body = body;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function extractApiErrorMessage(body, fallback) {
|
|
33
|
+
if (typeof body !== "object" || body === null) return fallback;
|
|
34
|
+
const record = body;
|
|
35
|
+
if (typeof record.detail === "string") return record.detail;
|
|
36
|
+
if (Array.isArray(record.detail) && record.detail.length > 0) {
|
|
37
|
+
const first = record.detail[0];
|
|
38
|
+
if (first && typeof first.msg === "string") {
|
|
39
|
+
const loc = first.loc;
|
|
40
|
+
const field = Array.isArray(loc) ? loc[loc.length - 1] : void 0;
|
|
41
|
+
return typeof field === "string" || typeof field === "number" ? `${field}: ${first.msg}` : first.msg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const firstStringOrArrayItem = (value) => {
|
|
45
|
+
if (typeof value === "string") return value;
|
|
46
|
+
if (Array.isArray(value) && typeof value[0] === "string") return value[0];
|
|
47
|
+
return void 0;
|
|
48
|
+
};
|
|
49
|
+
const nonFieldMessage = firstStringOrArrayItem(record.non_field_errors);
|
|
50
|
+
if (nonFieldMessage) return nonFieldMessage;
|
|
51
|
+
for (const [key, value] of Object.entries(record)) {
|
|
52
|
+
if (key === "detail" || key === "non_field_errors") continue;
|
|
53
|
+
const message = firstStringOrArrayItem(value);
|
|
54
|
+
if (message) return message;
|
|
55
|
+
}
|
|
56
|
+
return fallback;
|
|
57
|
+
}
|
|
58
|
+
function storefrontHeaders(config) {
|
|
59
|
+
return {
|
|
60
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
61
|
+
"X-Business-ID": config.businessId
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function authHeaders(config, accessToken) {
|
|
65
|
+
return {
|
|
66
|
+
...storefrontHeaders(config),
|
|
67
|
+
Authorization: `Bearer ${accessToken}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
71
|
+
async function apiRequest(url, options = {}) {
|
|
72
|
+
const { fallbackErrorMessage = "Request failed", ...init } = options;
|
|
73
|
+
const headers = new Headers(init.headers);
|
|
74
|
+
const hadBearerToken = headers.get("Authorization")?.startsWith("Bearer ") ?? false;
|
|
75
|
+
const response = await fetch(url, { ...init, headers });
|
|
76
|
+
if (response.status === 401 && hadBearerToken && hasRefreshHandler()) {
|
|
77
|
+
const freshToken = await refreshAccessToken();
|
|
78
|
+
if (freshToken) {
|
|
79
|
+
const retryHeaders = new Headers(headers);
|
|
80
|
+
retryHeaders.set("Authorization", `Bearer ${freshToken}`);
|
|
81
|
+
const retryResponse = await fetch(url, { ...init, headers: retryHeaders });
|
|
82
|
+
if (retryResponse.ok) {
|
|
83
|
+
const retryText = await retryResponse.text();
|
|
84
|
+
return retryText ? JSON.parse(retryText) : void 0;
|
|
85
|
+
}
|
|
86
|
+
const retryBody = await retryResponse.json().catch(() => ({}));
|
|
87
|
+
throw new ApiError(extractApiErrorMessage(retryBody, fallbackErrorMessage), retryResponse.status, retryBody);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const body = await response.json().catch(() => ({}));
|
|
92
|
+
throw new ApiError(extractApiErrorMessage(body, fallbackErrorMessage), response.status, body);
|
|
93
|
+
}
|
|
94
|
+
const text = await response.text();
|
|
95
|
+
return text ? JSON.parse(text) : void 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
1
98
|
// src/services/cart.service.ts
|
|
2
99
|
function parseItems(items) {
|
|
3
100
|
return items.map((item) => ({
|
|
@@ -5,218 +102,148 @@ function parseItems(items) {
|
|
|
5
102
|
variant_attributes: item.variant_attributes && typeof item.variant_attributes === "string" ? JSON.parse(item.variant_attributes) : item.variant_attributes
|
|
6
103
|
}));
|
|
7
104
|
}
|
|
105
|
+
function guestHeaders(config, guestSessionId, extra) {
|
|
106
|
+
return { ...extra, ...storefrontHeaders(config), "X-Guest-Session": guestSessionId };
|
|
107
|
+
}
|
|
8
108
|
async function getGuestCart(config, guestSessionId) {
|
|
9
|
-
if (!guestSessionId)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"X-Guest-Session": guestSessionId
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
if (!response.ok) return [];
|
|
19
|
-
const data = await response.json();
|
|
20
|
-
return parseItems(data.items || []);
|
|
21
|
-
} catch {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
109
|
+
if (!guestSessionId) throw new Error("Guest session ID is required to fetch guest cart");
|
|
110
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/`, {
|
|
111
|
+
headers: guestHeaders(config, guestSessionId),
|
|
112
|
+
fallbackErrorMessage: "Failed to fetch guest cart"
|
|
113
|
+
});
|
|
114
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
24
115
|
}
|
|
25
116
|
async function addToGuestCart(config, guestSessionId, item) {
|
|
26
|
-
if (!guestSessionId)
|
|
117
|
+
if (!guestSessionId) throw new Error("Guest session ID is required to add to guest cart");
|
|
27
118
|
const payload = {
|
|
28
119
|
product_id: item.product_id,
|
|
29
|
-
|
|
30
|
-
product_name: item.product_name,
|
|
31
|
-
image: item.image,
|
|
32
|
-
variant_id: item.variant_id,
|
|
33
|
-
variant_attributes: typeof item.variant_attributes === "string" ? item.variant_attributes : JSON.stringify(item.variant_attributes),
|
|
34
|
-
unit_price: item.unit_price,
|
|
120
|
+
variant_id: item.variant_id ?? void 0,
|
|
35
121
|
quantity: item.quantity,
|
|
36
|
-
custom_measurements: item.custom_measurements
|
|
37
|
-
is_bespoke: item.is_bespoke
|
|
122
|
+
custom_measurements: item.custom_measurements ?? void 0
|
|
38
123
|
};
|
|
39
|
-
const
|
|
124
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/`, {
|
|
40
125
|
method: "POST",
|
|
41
|
-
headers:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
body: JSON.stringify(payload)
|
|
48
|
-
});
|
|
49
|
-
if (!response.ok) return [];
|
|
50
|
-
const data = await response.json();
|
|
51
|
-
return parseItems(data.items || []);
|
|
126
|
+
headers: guestHeaders(config, guestSessionId, JSON_HEADERS),
|
|
127
|
+
body: JSON.stringify(payload),
|
|
128
|
+
fallbackErrorMessage: "Failed to add to guest cart"
|
|
129
|
+
});
|
|
130
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
52
131
|
}
|
|
53
132
|
async function updateGuestCartItemQuantity(config, guestSessionId, itemId, quantity) {
|
|
54
|
-
if (!guestSessionId)
|
|
55
|
-
const
|
|
133
|
+
if (!guestSessionId) throw new Error("Guest session ID is required to update guest cart item");
|
|
134
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/${itemId}`, {
|
|
56
135
|
method: "PATCH",
|
|
57
|
-
headers:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
body: JSON.stringify({ quantity })
|
|
64
|
-
});
|
|
65
|
-
if (!response.ok) return [];
|
|
66
|
-
const data = await response.json();
|
|
67
|
-
return parseItems(data.items || []);
|
|
136
|
+
headers: guestHeaders(config, guestSessionId, JSON_HEADERS),
|
|
137
|
+
body: JSON.stringify({ quantity }),
|
|
138
|
+
fallbackErrorMessage: "Failed to update guest cart item"
|
|
139
|
+
});
|
|
140
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
68
141
|
}
|
|
69
142
|
async function removeFromGuestCart(config, guestSessionId, itemId) {
|
|
70
|
-
if (!guestSessionId)
|
|
71
|
-
await
|
|
143
|
+
if (!guestSessionId) throw new Error("Guest session ID is required to remove from guest cart");
|
|
144
|
+
await apiRequest(`${config.backendUrls.cart}/cart/${itemId}`, {
|
|
72
145
|
method: "DELETE",
|
|
73
|
-
headers:
|
|
74
|
-
|
|
75
|
-
"X-Business-ID": config.businessId,
|
|
76
|
-
"X-Guest-Session": guestSessionId
|
|
77
|
-
}
|
|
146
|
+
headers: guestHeaders(config, guestSessionId),
|
|
147
|
+
fallbackErrorMessage: "Failed to remove item from guest cart"
|
|
78
148
|
});
|
|
79
|
-
return getGuestCart(config, guestSessionId);
|
|
80
149
|
}
|
|
81
150
|
async function clearGuestCart(config, guestSessionId) {
|
|
82
|
-
if (!guestSessionId)
|
|
83
|
-
await
|
|
151
|
+
if (!guestSessionId) throw new Error("Guest session ID is required to clear guest cart");
|
|
152
|
+
await apiRequest(`${config.backendUrls.cart}/cart/clear`, {
|
|
84
153
|
method: "DELETE",
|
|
85
|
-
headers:
|
|
86
|
-
|
|
87
|
-
"X-Business-ID": config.businessId,
|
|
88
|
-
"X-Guest-Session": guestSessionId
|
|
89
|
-
}
|
|
154
|
+
headers: guestHeaders(config, guestSessionId),
|
|
155
|
+
fallbackErrorMessage: "Failed to clear guest cart"
|
|
90
156
|
});
|
|
91
157
|
}
|
|
92
158
|
async function getCart(config, accessToken) {
|
|
93
159
|
if (!accessToken) {
|
|
94
|
-
|
|
160
|
+
throw new Error("Access token is required to fetch authenticated cart");
|
|
95
161
|
}
|
|
96
|
-
const
|
|
97
|
-
headers:
|
|
98
|
-
|
|
99
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
100
|
-
"X-Business-ID": config.businessId
|
|
101
|
-
}
|
|
162
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/`, {
|
|
163
|
+
headers: authHeaders(config, accessToken),
|
|
164
|
+
fallbackErrorMessage: "Failed to fetch cart"
|
|
102
165
|
});
|
|
103
|
-
|
|
104
|
-
const data = await response.json();
|
|
105
|
-
const parsedItems = parseItems(data.items || []);
|
|
106
|
-
return { ...data, items: parsedItems };
|
|
166
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
107
167
|
}
|
|
108
168
|
async function addToCart(config, accessToken, item) {
|
|
109
|
-
const
|
|
169
|
+
const payload = {
|
|
170
|
+
product_id: item.product_id,
|
|
171
|
+
variant_id: item.variant_id ?? void 0,
|
|
172
|
+
quantity: item.quantity,
|
|
173
|
+
custom_measurements: item.custom_measurements ?? void 0
|
|
174
|
+
};
|
|
175
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/`, {
|
|
110
176
|
method: "POST",
|
|
111
|
-
headers: {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
},
|
|
117
|
-
body: JSON.stringify(item)
|
|
118
|
-
});
|
|
119
|
-
if (!response.ok) throw new Error("Failed to add to cart");
|
|
120
|
-
const data = await response.json();
|
|
121
|
-
const parsedItems = parseItems(data.items || []);
|
|
122
|
-
return { ...data, items: parsedItems };
|
|
177
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
178
|
+
body: JSON.stringify(payload),
|
|
179
|
+
fallbackErrorMessage: "Failed to add to cart"
|
|
180
|
+
});
|
|
181
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
123
182
|
}
|
|
124
183
|
async function updateCartItem(config, accessToken, itemId, quantity) {
|
|
125
|
-
const
|
|
184
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/${itemId}`, {
|
|
126
185
|
method: "PATCH",
|
|
127
|
-
headers: {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
},
|
|
133
|
-
body: JSON.stringify({ quantity })
|
|
134
|
-
});
|
|
135
|
-
if (!response.ok) throw new Error("Failed to update cart item");
|
|
136
|
-
const data = await response.json();
|
|
137
|
-
const parsedItems = parseItems(data.items || []);
|
|
138
|
-
return { ...data, items: parsedItems };
|
|
186
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
187
|
+
body: JSON.stringify({ quantity }),
|
|
188
|
+
fallbackErrorMessage: "Failed to update cart item"
|
|
189
|
+
});
|
|
190
|
+
return { ...data, items: parseItems(data.items || []) };
|
|
139
191
|
}
|
|
140
192
|
async function removeFromCart(config, accessToken, itemId) {
|
|
141
|
-
await
|
|
193
|
+
await apiRequest(`${config.backendUrls.cart}/cart/${itemId}`, {
|
|
142
194
|
method: "DELETE",
|
|
143
|
-
headers:
|
|
144
|
-
|
|
145
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
146
|
-
"X-Business-ID": config.businessId
|
|
147
|
-
}
|
|
195
|
+
headers: authHeaders(config, accessToken),
|
|
196
|
+
fallbackErrorMessage: "Failed to remove cart item"
|
|
148
197
|
});
|
|
149
|
-
return getCart(config, accessToken);
|
|
150
198
|
}
|
|
151
199
|
async function clearCart(config, accessToken) {
|
|
152
|
-
await
|
|
200
|
+
await apiRequest(`${config.backendUrls.cart}/cart/clear`, {
|
|
153
201
|
method: "DELETE",
|
|
154
|
-
headers:
|
|
155
|
-
|
|
156
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
157
|
-
"X-Business-ID": config.businessId
|
|
158
|
-
}
|
|
202
|
+
headers: authHeaders(config, accessToken),
|
|
203
|
+
fallbackErrorMessage: "Failed to clear cart"
|
|
159
204
|
});
|
|
160
205
|
}
|
|
161
|
-
async function mergeGuestCart(config, accessToken, guestSessionId) {
|
|
162
|
-
const guestItems = guestSessionId ? await getGuestCart(config, guestSessionId) : [];
|
|
163
|
-
if (guestItems.length === 0) {
|
|
164
|
-
return getCart(config, accessToken);
|
|
165
|
-
}
|
|
206
|
+
async function mergeGuestCart(config, accessToken, guestSessionId, guestItems) {
|
|
166
207
|
const payloadItems = guestItems.map((item) => ({
|
|
167
208
|
product_id: item.product_id,
|
|
168
|
-
|
|
169
|
-
product_name: item.product_name,
|
|
170
|
-
image: item.image,
|
|
171
|
-
variant_id: item.variant_id,
|
|
172
|
-
variant_attributes: typeof item.variant_attributes === "string" ? item.variant_attributes : JSON.stringify(item.variant_attributes ?? {}),
|
|
173
|
-
unit_price: item.unit_price,
|
|
209
|
+
variant_id: item.variant_id ?? void 0,
|
|
174
210
|
quantity: item.quantity,
|
|
175
|
-
custom_measurements:
|
|
176
|
-
is_bespoke: item.is_bespoke
|
|
211
|
+
custom_measurements: item.custom_measurements ?? void 0
|
|
177
212
|
}));
|
|
178
|
-
const headers = {
|
|
179
|
-
"Content-Type": "application/json",
|
|
180
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
181
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
182
|
-
"X-Business-ID": config.businessId
|
|
183
|
-
};
|
|
213
|
+
const headers = { ...JSON_HEADERS, ...authHeaders(config, accessToken) };
|
|
184
214
|
if (guestSessionId) {
|
|
185
215
|
headers["X-Guest-Session"] = guestSessionId;
|
|
186
216
|
}
|
|
187
|
-
const
|
|
217
|
+
const data = await apiRequest(`${config.backendUrls.cart}/cart/merge`, {
|
|
188
218
|
method: "POST",
|
|
189
219
|
headers,
|
|
190
|
-
body: JSON.stringify({ items: payloadItems })
|
|
220
|
+
body: JSON.stringify({ items: payloadItems }),
|
|
221
|
+
fallbackErrorMessage: "Failed to merge guest cart"
|
|
191
222
|
});
|
|
192
|
-
if (!response.ok) throw new Error("Failed to merge guest cart");
|
|
193
|
-
const data = await response.json();
|
|
194
223
|
return { ...data, items: parseItems(data.items || []) };
|
|
195
224
|
}
|
|
196
225
|
async function mergeGuestCartIfPresent(config, accessToken, guestSessionId) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
await mergeGuestCart(config, accessToken, guestSessionId);
|
|
201
|
-
} catch (error) {
|
|
202
|
-
console.warn("[Cart] Failed to merge guest cart:", error);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
function getGuestCartCount() {
|
|
206
|
-
return 0;
|
|
226
|
+
const guestCart = await getGuestCart(config, guestSessionId);
|
|
227
|
+
if (!guestCart.items.length) return;
|
|
228
|
+
await mergeGuestCart(config, accessToken, guestSessionId, guestCart.items);
|
|
207
229
|
}
|
|
208
|
-
function
|
|
209
|
-
return
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return
|
|
230
|
+
function getGuestCartProductType(items) {
|
|
231
|
+
if (!items || !items.length) return null;
|
|
232
|
+
const types = new Set(items.map((i) => i.product_type).filter(Boolean));
|
|
233
|
+
if (types.size === 0) return null;
|
|
234
|
+
if (types.size === 1) return [...types][0] ?? null;
|
|
235
|
+
return "physical" /* PHYSICAL */;
|
|
213
236
|
}
|
|
214
237
|
|
|
215
238
|
// src/services/order.service.ts
|
|
239
|
+
function extractShippingAddress(raw) {
|
|
240
|
+
const val = raw.physical_fulfillment?.shipping_address;
|
|
241
|
+
return typeof val === "object" && val !== null ? val : null;
|
|
242
|
+
}
|
|
216
243
|
function deriveCustomerName(raw) {
|
|
217
244
|
if (raw.customer_name) return raw.customer_name;
|
|
218
245
|
if (raw.guest_name) return raw.guest_name;
|
|
219
|
-
const addr =
|
|
246
|
+
const addr = extractShippingAddress(raw);
|
|
220
247
|
if (addr) {
|
|
221
248
|
const full = `${addr.first_name ?? ""} ${addr.last_name ?? ""}`.trim();
|
|
222
249
|
if (full) return full;
|
|
@@ -228,25 +255,123 @@ function deriveCustomerName(raw) {
|
|
|
228
255
|
function normaliseStorefrontOrder(raw) {
|
|
229
256
|
const items = (raw.items ?? []).map((item) => ({
|
|
230
257
|
id: item.id,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
258
|
+
order_id: item.order_id,
|
|
259
|
+
product_id: item.product_id ?? void 0,
|
|
260
|
+
variant_id: item.variant_id ?? void 0,
|
|
261
|
+
product_name: item.product_name ?? "",
|
|
262
|
+
quantity: item.quantity,
|
|
263
|
+
unit_price: item.unit_price,
|
|
264
|
+
variant_details: item.variant_details,
|
|
265
|
+
custom_measurements: item.custom_measurements,
|
|
266
|
+
image_url: item.image_url ?? void 0
|
|
235
267
|
}));
|
|
236
|
-
const addr =
|
|
268
|
+
const addr = extractShippingAddress(raw);
|
|
269
|
+
const customerName = deriveCustomerName(raw);
|
|
270
|
+
const customerEmail = raw.guest_email ?? raw.customer_email ?? "";
|
|
271
|
+
const physical = raw.physical_fulfillment;
|
|
272
|
+
if (!raw.currency) {
|
|
273
|
+
throw new Error(`Order ${raw.id} response is missing a currency field.`);
|
|
274
|
+
}
|
|
275
|
+
if (!raw.created_at) {
|
|
276
|
+
throw new Error(`Order ${raw.id} response is missing a created_at field.`);
|
|
277
|
+
}
|
|
278
|
+
if (!raw.updated_at) {
|
|
279
|
+
throw new Error(`Order ${raw.id} response is missing an updated_at field.`);
|
|
280
|
+
}
|
|
281
|
+
if (!raw.business_id) {
|
|
282
|
+
throw new Error(`Order ${raw.id} response is missing a business_id field.`);
|
|
283
|
+
}
|
|
237
284
|
return {
|
|
238
285
|
id: raw.id,
|
|
239
|
-
display_id: raw.display_id,
|
|
286
|
+
display_id: raw.display_id || raw.id,
|
|
287
|
+
business_id: raw.business_id,
|
|
288
|
+
customer_id: raw.customer_id ?? void 0,
|
|
240
289
|
items,
|
|
241
|
-
total: raw.total_amount ?? raw.total ?? 0,
|
|
242
290
|
status: raw.status,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
291
|
+
payment_status: raw.payment_status || "pending",
|
|
292
|
+
product_type: raw.product_type ?? void 0,
|
|
293
|
+
// Canonical backend fields
|
|
294
|
+
total_amount: raw.total_amount,
|
|
295
|
+
currency: raw.currency,
|
|
296
|
+
subtotal_amount: raw.subtotal_amount ?? void 0,
|
|
297
|
+
shipping_amount: raw.shipping_amount ?? void 0,
|
|
298
|
+
discount_amount: raw.discount_amount ?? void 0,
|
|
299
|
+
tax_amount: raw.tax_amount ?? void 0,
|
|
300
|
+
customer_name: customerName,
|
|
301
|
+
customer_email: customerEmail,
|
|
302
|
+
// REAL BUG FIXED (2026-09-23) via the REST codegen initiative: every
|
|
303
|
+
// field below this point used to read a flat `raw.<field>` that does
|
|
304
|
+
// NOT exist anywhere on the real OrderResponse - confirmed by reading
|
|
305
|
+
// the actual Pydantic classes, not just the generated types. They
|
|
306
|
+
// genuinely live nested under `physical_fulfillment` (shipping/
|
|
307
|
+
// tracking/carrier/pickup/surcharge/weight) or `digital_fulfillment`
|
|
308
|
+
// (buyer_country) - "One nested block per product type, instead of
|
|
309
|
+
// ~35 flat fields on OrderBase" per that schema file's own Order
|
|
310
|
+
// Schema Refactor comment. Every one of these was silently `undefined`
|
|
311
|
+
// on every real order: a customer's tracking number, carrier, delivery
|
|
312
|
+
// status, and shipping address never actually rendered anywhere on the
|
|
313
|
+
// storefront's order tracking page.
|
|
314
|
+
tracking_number: physical?.tracking_number ?? void 0,
|
|
315
|
+
delivery_status: physical?.delivery_status ?? void 0,
|
|
316
|
+
carrier_name: physical?.carrier_name ?? void 0,
|
|
317
|
+
carrier_slug: physical?.carrier_slug ?? void 0,
|
|
318
|
+
terminal_rate_id: physical?.terminal_rate_id ?? void 0,
|
|
319
|
+
guest_token: raw.guest_token ?? void 0,
|
|
320
|
+
guest_email: raw.guest_email ?? void 0,
|
|
321
|
+
guest_phone: raw.guest_phone ?? void 0,
|
|
322
|
+
guest_name: raw.guest_name ?? void 0,
|
|
323
|
+
buyer_country: raw.digital_fulfillment?.buyer_country ?? void 0,
|
|
324
|
+
created_at: raw.created_at,
|
|
325
|
+
updated_at: raw.updated_at,
|
|
326
|
+
// Weight discrepancy & surcharge fields (Task 2) — physical_fulfillment
|
|
327
|
+
shipping_surcharge_amount: physical?.shipping_surcharge_amount ?? void 0,
|
|
328
|
+
shipping_surcharge_reason: physical?.shipping_surcharge_reason ?? void 0,
|
|
329
|
+
shipping_surcharge_description: physical?.shipping_surcharge_description ?? void 0,
|
|
330
|
+
shipping_surcharge_applied_at: physical?.shipping_surcharge_applied_at ?? void 0,
|
|
331
|
+
declared_weight_kg: physical?.declared_weight_kg ?? void 0,
|
|
332
|
+
actual_weight_kg: physical?.actual_weight_kg ?? void 0,
|
|
333
|
+
// Self-pickup verification fields (Task 3) — physical_fulfillment
|
|
334
|
+
pickup_verification_code: physical?.pickup_verification_code ?? void 0,
|
|
335
|
+
pickup_verification_code_generated_at: physical?.pickup_verification_code_generated_at ?? void 0,
|
|
336
|
+
pickup_verification_code_used_at: physical?.pickup_verification_code_used_at ?? void 0,
|
|
337
|
+
pickup_verification_failed_attempts: physical?.pickup_verification_failed_attempts,
|
|
338
|
+
pickup_verification_locked_until: physical?.pickup_verification_locked_until ?? void 0,
|
|
339
|
+
pickup_qr_payload: physical?.pickup_qr_payload ?? void 0,
|
|
340
|
+
// Bespoke fields — real backend nests these under `bespoke_fulfillment`.
|
|
341
|
+
bespoke_brief: raw.bespoke_fulfillment?.brief ?? void 0,
|
|
342
|
+
bespoke_reference_images: raw.bespoke_fulfillment?.reference_images ?? void 0,
|
|
343
|
+
bespoke_measurements: raw.bespoke_fulfillment?.measurements ?? void 0,
|
|
344
|
+
bespoke_preferred_timeline: raw.bespoke_fulfillment?.preferred_timeline ?? void 0,
|
|
345
|
+
bespoke_special_instructions: raw.bespoke_fulfillment?.special_instructions ?? void 0,
|
|
346
|
+
bespoke_deposit_ratio: raw.bespoke_fulfillment?.deposit_ratio ?? void 0,
|
|
347
|
+
bespoke_deposit_amount: raw.bespoke_fulfillment?.deposit_amount ?? void 0,
|
|
348
|
+
bespoke_balance_amount: raw.bespoke_fulfillment?.balance_amount ?? void 0,
|
|
349
|
+
bespoke_status: raw.bespoke_fulfillment?.status ?? void 0,
|
|
350
|
+
bespoke_deliverable_submitted_at: raw.bespoke_fulfillment?.deliverable_submitted_at ?? void 0,
|
|
351
|
+
bespoke_deliverable_url: raw.bespoke_fulfillment?.deliverable_url ?? void 0,
|
|
352
|
+
bespoke_deliverable_notes: raw.bespoke_fulfillment?.deliverable_notes ?? void 0,
|
|
353
|
+
bespoke_buyer_approved_at: raw.bespoke_fulfillment?.buyer_approved_at ?? void 0,
|
|
354
|
+
bespoke_revision_count: raw.bespoke_fulfillment?.revision_count ?? 0,
|
|
355
|
+
bespoke_revision_notes: raw.bespoke_fulfillment?.revision_notes ?? void 0,
|
|
356
|
+
// SDK camelCase convenience aliases
|
|
357
|
+
total: raw.total_amount ?? void 0,
|
|
358
|
+
shippingAmount: raw.shipping_amount ?? void 0,
|
|
359
|
+
discountAmount: raw.discount_amount ?? void 0,
|
|
360
|
+
customerEmail,
|
|
361
|
+
customerName,
|
|
362
|
+
createdAt: new Date(raw.created_at).getTime(),
|
|
363
|
+
updatedAt: new Date(raw.updated_at).getTime(),
|
|
364
|
+
// REAL BUG FIXED (2026-09-23), found alongside the nesting bug above:
|
|
365
|
+
// `deliveryMethod` reads physical_fulfillment.shipping_method now
|
|
366
|
+
// (was reading a flat `delivery_method` field that never existed at
|
|
367
|
+
// all, anywhere - not even nested). The real value is "carrier" or
|
|
368
|
+
// "self_pickup" (PhysicalFulfillmentCreate.shipping_method's own
|
|
369
|
+
// docstring) - see the matching fix in kasuvia-storefront's
|
|
370
|
+
// OrderDeliveryInfo.tsx, which used to compare against the wrong
|
|
371
|
+
// string "pickup".
|
|
372
|
+
deliveryMethod: physical?.shipping_method ?? void 0,
|
|
373
|
+
trackingNumber: physical?.tracking_number ?? void 0,
|
|
374
|
+
deliveryAddress: addr ? `${addr.street}, ${addr.city}, ${addr.state}, ${addr.country}` : void 0,
|
|
250
375
|
shippingAddress: addr ? {
|
|
251
376
|
first_name: addr.first_name ?? "",
|
|
252
377
|
last_name: addr.last_name ?? "",
|
|
@@ -254,62 +379,85 @@ function normaliseStorefrontOrder(raw) {
|
|
|
254
379
|
street: addr.street ?? "",
|
|
255
380
|
city: addr.city ?? "",
|
|
256
381
|
state: addr.state ?? "",
|
|
257
|
-
lga: addr.lga
|
|
382
|
+
lga: addr.lga,
|
|
258
383
|
country: addr.country ?? "",
|
|
259
|
-
postal: addr.postal
|
|
384
|
+
postal: addr.postal
|
|
260
385
|
} : void 0,
|
|
261
|
-
|
|
386
|
+
// REAL GAP (2026-09-23), NOT fixed here: confirmed cancellation_reason
|
|
387
|
+
// does not exist anywhere in OrderResponse or any of its fulfillment
|
|
388
|
+
// sub-schemas (kasuvia-store-management's app/schemas/order.py) - the
|
|
389
|
+
// cancel-order endpoint accepts a `reason` in its request body but the
|
|
390
|
+
// backend never persists/returns it back on the order. Permanently
|
|
391
|
+
// undefined until the backend adds real storage for it; kept as a
|
|
392
|
+
// field on the public Order type rather than silently removed, since
|
|
393
|
+
// deleting a public SDK field is a breaking change this fix's scope
|
|
394
|
+
// doesn't cover.
|
|
395
|
+
cancellationReason: void 0,
|
|
262
396
|
hasBespoke: raw.product_type === "bespoke",
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
397
|
+
// REAL GAP (2026-09-23), NOT fixed here: same as cancellationReason -
|
|
398
|
+
// confirmed no `bespoke_stage` field exists anywhere; the real,
|
|
399
|
+
// equivalent concept is bespoke_fulfillment.status (already exposed
|
|
400
|
+
// above as `bespoke_status`). Reads that here rather than staying
|
|
401
|
+
// permanently undefined, since it's genuinely the same real data the
|
|
402
|
+
// consuming components (BespokeProgress) want to key off of.
|
|
403
|
+
bespokeStage: raw.bespoke_fulfillment?.status ?? void 0,
|
|
404
|
+
bespokeBrief: raw.bespoke_fulfillment?.brief ?? void 0,
|
|
405
|
+
deliveryStatus: physical?.delivery_status ?? void 0,
|
|
406
|
+
carrierName: physical?.carrier_name ?? void 0,
|
|
407
|
+
terminalShipmentId: physical?.terminal_shipment_id ?? void 0,
|
|
408
|
+
guestToken: raw.guest_token ?? void 0,
|
|
409
|
+
guestEmail: raw.guest_email ?? void 0,
|
|
410
|
+
guestPhone: raw.guest_phone ?? void 0,
|
|
411
|
+
guestName: raw.guest_name ?? void 0
|
|
272
412
|
};
|
|
273
413
|
}
|
|
274
|
-
async function createOrder(config, accessToken, payload) {
|
|
275
|
-
const
|
|
414
|
+
async function createOrder(config, accessToken, payload, guestSessionId) {
|
|
415
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
416
|
+
if (accessToken) {
|
|
417
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
418
|
+
} else if (guestSessionId) {
|
|
419
|
+
headers["X-Guest-Session"] = guestSessionId;
|
|
420
|
+
}
|
|
421
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/storefront`, {
|
|
276
422
|
method: "POST",
|
|
277
|
-
headers
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
"X-Business-ID": config.businessId
|
|
282
|
-
},
|
|
283
|
-
body: JSON.stringify(payload)
|
|
284
|
-
});
|
|
285
|
-
if (!response.ok) throw new Error("Failed to create order");
|
|
286
|
-
const data = await response.json();
|
|
423
|
+
headers,
|
|
424
|
+
body: JSON.stringify(payload),
|
|
425
|
+
fallbackErrorMessage: "Failed to create order"
|
|
426
|
+
});
|
|
287
427
|
return normaliseStorefrontOrder(data);
|
|
288
428
|
}
|
|
289
|
-
async function
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
"X-Business-ID": config.businessId
|
|
298
|
-
}
|
|
429
|
+
async function createBespokeOrder(config, accessToken, payload) {
|
|
430
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
431
|
+
if (accessToken) headers["Authorization"] = `Bearer ${accessToken}`;
|
|
432
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/storefront/bespoke`, {
|
|
433
|
+
method: "POST",
|
|
434
|
+
headers,
|
|
435
|
+
body: JSON.stringify(payload),
|
|
436
|
+
fallbackErrorMessage: "Failed to create bespoke order"
|
|
299
437
|
});
|
|
300
|
-
if (!response.ok) throw new Error("Failed to find order");
|
|
301
|
-
const data = await response.json();
|
|
302
438
|
return normaliseStorefrontOrder(data);
|
|
303
439
|
}
|
|
304
|
-
async function
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
440
|
+
async function createServiceBookingOrder(config, accessToken, payload) {
|
|
441
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
442
|
+
if (accessToken) headers["Authorization"] = `Bearer ${accessToken}`;
|
|
443
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/storefront/service`, {
|
|
444
|
+
method: "POST",
|
|
445
|
+
headers,
|
|
446
|
+
body: JSON.stringify(payload),
|
|
447
|
+
fallbackErrorMessage: "Failed to create service booking order"
|
|
448
|
+
});
|
|
449
|
+
return normaliseStorefrontOrder(data);
|
|
450
|
+
}
|
|
451
|
+
async function findOrder(config, params) {
|
|
452
|
+
if (!params.email || !params.order_id) {
|
|
453
|
+
throw new Error("Both email and order_id are required to find an order.");
|
|
454
|
+
}
|
|
455
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/track`, {
|
|
456
|
+
method: "POST",
|
|
457
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
458
|
+
body: JSON.stringify({ order_id: params.order_id, email: params.email }),
|
|
459
|
+
fallbackErrorMessage: "Failed to find order"
|
|
310
460
|
});
|
|
311
|
-
if (!response.ok) throw new Error("Failed to find order by token");
|
|
312
|
-
const data = await response.json();
|
|
313
461
|
return normaliseStorefrontOrder(data);
|
|
314
462
|
}
|
|
315
463
|
async function getOrders(config, accessToken, params) {
|
|
@@ -317,45 +465,110 @@ async function getOrders(config, accessToken, params) {
|
|
|
317
465
|
if (params?.email) queryParams.set("email", params.email);
|
|
318
466
|
if (params?.page) queryParams.set("page", params.page.toString());
|
|
319
467
|
if (params?.page_size) queryParams.set("page_size", params.page_size.toString());
|
|
320
|
-
const
|
|
321
|
-
headers:
|
|
322
|
-
|
|
323
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
324
|
-
"X-Business-ID": config.businessId
|
|
325
|
-
}
|
|
468
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/?${queryParams.toString()}`, {
|
|
469
|
+
headers: authHeaders(config, accessToken),
|
|
470
|
+
fallbackErrorMessage: "Failed to get orders"
|
|
326
471
|
});
|
|
327
|
-
if (!response.ok) throw new Error("Failed to get orders");
|
|
328
|
-
const data = await response.json();
|
|
329
472
|
const items = Array.isArray(data) ? data : data.items ?? [];
|
|
330
473
|
return items.map(normaliseStorefrontOrder);
|
|
331
474
|
}
|
|
332
475
|
async function cancelOrder(config, accessToken, orderId, reason) {
|
|
333
|
-
const
|
|
476
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/${orderId}/cancel/`, {
|
|
334
477
|
method: "POST",
|
|
335
|
-
headers: {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
"X-Business-ID": config.businessId
|
|
340
|
-
},
|
|
341
|
-
body: JSON.stringify({ reason })
|
|
342
|
-
});
|
|
343
|
-
if (!response.ok) throw new Error("Failed to cancel order");
|
|
344
|
-
const data = await response.json();
|
|
478
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
479
|
+
body: JSON.stringify({ reason }),
|
|
480
|
+
fallbackErrorMessage: "Failed to cancel order"
|
|
481
|
+
});
|
|
345
482
|
return normaliseStorefrontOrder(data);
|
|
346
483
|
}
|
|
347
|
-
async function trackOrder(config, orderId,
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
352
|
-
"X-Business-ID": config.businessId
|
|
353
|
-
}
|
|
484
|
+
async function trackOrder(config, orderId, accessToken) {
|
|
485
|
+
const data = await apiRequest(`${config.backendUrls.store}/orders/${orderId}`, {
|
|
486
|
+
headers: authHeaders(config, accessToken),
|
|
487
|
+
fallbackErrorMessage: "Failed to track order"
|
|
354
488
|
});
|
|
355
|
-
if (!response.ok) throw new Error("Failed to track order");
|
|
356
|
-
const data = await response.json();
|
|
357
489
|
return normaliseStorefrontOrder(data);
|
|
358
490
|
}
|
|
491
|
+
async function validatePromoCode(config, code, cartTotal) {
|
|
492
|
+
try {
|
|
493
|
+
return await apiRequest(`${config.backendUrls.store}/sales/discounts/validate`, {
|
|
494
|
+
method: "POST",
|
|
495
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
496
|
+
body: JSON.stringify({ code, cart_total: cartTotal }),
|
|
497
|
+
fallbackErrorMessage: "Invalid promo code"
|
|
498
|
+
});
|
|
499
|
+
} catch (err) {
|
|
500
|
+
const message = err instanceof ApiError ? err.message : "Invalid promo code";
|
|
501
|
+
return { valid: false, discount_amount: 0, discount_type: "fixed", message };
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
async function resolveRedirectOrJson(url, fallbackErrorMessage) {
|
|
505
|
+
const response = await fetch(url, { redirect: "manual" });
|
|
506
|
+
if (response.status >= 300 && response.status < 400) {
|
|
507
|
+
const location = response.headers.get("location");
|
|
508
|
+
if (!location) {
|
|
509
|
+
throw new Error(`${fallbackErrorMessage}: server redirected with no destination URL.`);
|
|
510
|
+
}
|
|
511
|
+
return { type: "redirect", url: location };
|
|
512
|
+
}
|
|
513
|
+
const body = await response.json().catch(() => ({}));
|
|
514
|
+
if (!response.ok) {
|
|
515
|
+
throw new ApiError(extractDigitalDownloadError(body, fallbackErrorMessage), response.status, body);
|
|
516
|
+
}
|
|
517
|
+
return { type: "json", data: body };
|
|
518
|
+
}
|
|
519
|
+
function extractDigitalDownloadError(body, fallback) {
|
|
520
|
+
if (typeof body === "object" && body !== null && "detail" in body && typeof body.detail === "string") {
|
|
521
|
+
return body.detail;
|
|
522
|
+
}
|
|
523
|
+
return fallback;
|
|
524
|
+
}
|
|
525
|
+
async function resolveDigitalDownload(config, orderId, token) {
|
|
526
|
+
const result = await resolveRedirectOrJson(
|
|
527
|
+
`${config.backendUrls.store}/orders/${orderId}/download/${token}`,
|
|
528
|
+
"Failed to resolve digital download link"
|
|
529
|
+
);
|
|
530
|
+
if (result.type === "redirect") return result;
|
|
531
|
+
return { type: "listing", ...result.data };
|
|
532
|
+
}
|
|
533
|
+
async function resolveDigitalDownloadFile(config, orderId, token, fileId) {
|
|
534
|
+
const result = await resolveRedirectOrJson(
|
|
535
|
+
`${config.backendUrls.store}/orders/${orderId}/download/${token}/${fileId}`,
|
|
536
|
+
"Failed to resolve this file's download link"
|
|
537
|
+
);
|
|
538
|
+
if (result.type !== "redirect") {
|
|
539
|
+
throw new Error("Failed to resolve this file's download link: server did not return a redirect.");
|
|
540
|
+
}
|
|
541
|
+
return result.url;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/services/consultation.service.ts
|
|
545
|
+
async function createConsultation(config, accessToken, params) {
|
|
546
|
+
return apiRequest(`${config.backendUrls.crm}/consultations/`, {
|
|
547
|
+
method: "POST",
|
|
548
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
549
|
+
body: JSON.stringify(params),
|
|
550
|
+
fallbackErrorMessage: "Failed to submit your request"
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// src/services/feedback.service.ts
|
|
555
|
+
async function createFeedback(config, accessToken, params) {
|
|
556
|
+
return apiRequest(`${config.backendUrls.crm}/feedback/`, {
|
|
557
|
+
method: "POST",
|
|
558
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
559
|
+
body: JSON.stringify(params),
|
|
560
|
+
fallbackErrorMessage: "Failed to submit your message"
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
async function getMyFeedback(config, accessToken, params) {
|
|
564
|
+
const query = new URLSearchParams();
|
|
565
|
+
if (params?.page) query.set("page", String(params.page));
|
|
566
|
+
if (params?.page_size) query.set("page_size", String(params.page_size));
|
|
567
|
+
return apiRequest(`${config.backendUrls.crm}/feedback/my?${query.toString()}`, {
|
|
568
|
+
headers: authHeaders(config, accessToken),
|
|
569
|
+
fallbackErrorMessage: "Failed to load your requests"
|
|
570
|
+
});
|
|
571
|
+
}
|
|
359
572
|
|
|
360
573
|
// src/constants.ts
|
|
361
574
|
var STORAGE_KEYS = {
|
|
@@ -366,88 +579,145 @@ var STORAGE_KEYS = {
|
|
|
366
579
|
STOREFRONT_STATE: "storefront_state_v3"
|
|
367
580
|
};
|
|
368
581
|
|
|
582
|
+
// src/utils/customer.ts
|
|
583
|
+
function buildFullName(firstname, lastname) {
|
|
584
|
+
const name = [firstname, lastname].filter(Boolean).join(" ").trim();
|
|
585
|
+
return name || void 0;
|
|
586
|
+
}
|
|
587
|
+
function splitFullName(fullName) {
|
|
588
|
+
if (!fullName?.trim()) return { firstname: "", lastname: "" };
|
|
589
|
+
const parts = fullName.trim().split(/\s+/);
|
|
590
|
+
return {
|
|
591
|
+
firstname: parts[0] ?? "",
|
|
592
|
+
lastname: parts.slice(1).join(" ")
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
|
|
369
596
|
// src/services/auth.service.ts
|
|
370
|
-
async function loginCustomer(config, payload) {
|
|
371
|
-
const
|
|
597
|
+
async function loginCustomer(config, payload, guestSessionId) {
|
|
598
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
599
|
+
if (guestSessionId) {
|
|
600
|
+
headers["X-Guest-Session"] = guestSessionId;
|
|
601
|
+
}
|
|
602
|
+
return apiRequest(`${config.backendUrls.auth}/auth/login/customer/`, {
|
|
372
603
|
method: "POST",
|
|
373
|
-
headers
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
"X-Business-ID": config.businessId
|
|
377
|
-
},
|
|
378
|
-
body: JSON.stringify({
|
|
379
|
-
...payload,
|
|
380
|
-
tenant_id: config.businessId
|
|
381
|
-
})
|
|
604
|
+
headers,
|
|
605
|
+
body: JSON.stringify(payload),
|
|
606
|
+
fallbackErrorMessage: "Login failed"
|
|
382
607
|
});
|
|
383
|
-
if (!response.ok) {
|
|
384
|
-
throw new Error("Login failed");
|
|
385
|
-
}
|
|
386
|
-
const data = await response.json();
|
|
387
|
-
return data;
|
|
388
608
|
}
|
|
389
|
-
async function registerCustomer(config, payload) {
|
|
390
|
-
const
|
|
609
|
+
async function registerCustomer(config, payload, guestSessionId) {
|
|
610
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
611
|
+
if (guestSessionId) {
|
|
612
|
+
headers["X-Guest-Session"] = guestSessionId;
|
|
613
|
+
}
|
|
614
|
+
return apiRequest(`${config.backendUrls.auth}/auth/register/customer/`, {
|
|
391
615
|
method: "POST",
|
|
392
|
-
headers
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
"X-Business-ID": config.businessId
|
|
396
|
-
},
|
|
397
|
-
body: JSON.stringify({
|
|
398
|
-
...payload,
|
|
399
|
-
tenant_id: config.businessId
|
|
400
|
-
})
|
|
616
|
+
headers,
|
|
617
|
+
body: JSON.stringify(payload),
|
|
618
|
+
fallbackErrorMessage: "Registration failed"
|
|
401
619
|
});
|
|
402
|
-
if (!response.ok) {
|
|
403
|
-
throw new Error("Registration failed");
|
|
404
|
-
}
|
|
405
|
-
const data = await response.json();
|
|
406
|
-
return data;
|
|
407
620
|
}
|
|
408
621
|
async function refreshToken(config, refresh) {
|
|
409
|
-
|
|
622
|
+
return apiRequest(`${config.backendUrls.auth}/auth/token/refresh/`, {
|
|
410
623
|
method: "POST",
|
|
411
|
-
headers:
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
body: JSON.stringify({ refresh })
|
|
624
|
+
headers: JSON_HEADERS,
|
|
625
|
+
body: JSON.stringify({ refresh }),
|
|
626
|
+
fallbackErrorMessage: "Token refresh failed"
|
|
415
627
|
});
|
|
416
|
-
if (!response.ok) {
|
|
417
|
-
throw new Error("Token refresh failed");
|
|
418
|
-
}
|
|
419
|
-
const data = await response.json();
|
|
420
|
-
return data;
|
|
421
628
|
}
|
|
422
629
|
async function logout(config, refresh) {
|
|
423
630
|
const payload = refresh ? { refresh } : {};
|
|
424
631
|
try {
|
|
425
|
-
await
|
|
632
|
+
await apiRequest(`${config.backendUrls.auth}/auth/logout/`, {
|
|
426
633
|
method: "POST",
|
|
427
|
-
headers:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
body: JSON.stringify(payload)
|
|
634
|
+
headers: JSON_HEADERS,
|
|
635
|
+
body: JSON.stringify(payload),
|
|
636
|
+
fallbackErrorMessage: "Server-side logout failed"
|
|
431
637
|
});
|
|
432
|
-
} catch {
|
|
638
|
+
} catch (err) {
|
|
639
|
+
if (err instanceof ApiError) {
|
|
640
|
+
console.error(`[auth.service] Server-side logout failed with status ${err.status}; local session will still be cleared.`);
|
|
641
|
+
} else {
|
|
642
|
+
console.error("[auth.service] Server-side logout request failed; local session will still be cleared.", err);
|
|
643
|
+
}
|
|
433
644
|
}
|
|
434
645
|
}
|
|
435
646
|
async function verifySocialToken(config, provider, token) {
|
|
436
|
-
|
|
647
|
+
return apiRequest(`${config.backendUrls.auth}/auth/social/verify/${provider}/`, {
|
|
437
648
|
method: "POST",
|
|
438
|
-
headers: {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
body: JSON.stringify({
|
|
442
|
-
id_token: token,
|
|
443
|
-
storefront_key: config.storefrontApiKey
|
|
444
|
-
})
|
|
649
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
650
|
+
body: JSON.stringify({ id_token: token }),
|
|
651
|
+
fallbackErrorMessage: "Social token verification failed"
|
|
445
652
|
});
|
|
446
|
-
|
|
447
|
-
|
|
653
|
+
}
|
|
654
|
+
async function requestCustomerOtp(config, payload) {
|
|
655
|
+
await apiRequest(`${config.backendUrls.auth}/auth/login/customer/passwordless/request/`, {
|
|
656
|
+
method: "POST",
|
|
657
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
658
|
+
body: JSON.stringify(payload),
|
|
659
|
+
fallbackErrorMessage: "Failed to send login code"
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
async function verifyCustomerOtp(config, payload, guestSessionId) {
|
|
663
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
664
|
+
if (guestSessionId) {
|
|
665
|
+
headers["X-Guest-Session"] = guestSessionId;
|
|
448
666
|
}
|
|
449
|
-
|
|
450
|
-
|
|
667
|
+
return apiRequest(`${config.backendUrls.auth}/auth/login/customer/passwordless/verify/`, {
|
|
668
|
+
method: "POST",
|
|
669
|
+
headers,
|
|
670
|
+
body: JSON.stringify(payload),
|
|
671
|
+
fallbackErrorMessage: "Invalid or expired code"
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
async function forgotPasswordCustomer(config, payload) {
|
|
675
|
+
return apiRequest(`${config.backendUrls.auth}/auth/forgot-password/customer/`, {
|
|
676
|
+
method: "POST",
|
|
677
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
678
|
+
body: JSON.stringify(payload),
|
|
679
|
+
fallbackErrorMessage: "Failed to request password reset"
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
async function resetPasswordCustomer(config, payload) {
|
|
683
|
+
return apiRequest(`${config.backendUrls.auth}/auth/reset-password/customer/`, {
|
|
684
|
+
method: "POST",
|
|
685
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
686
|
+
body: JSON.stringify(payload),
|
|
687
|
+
fallbackErrorMessage: "Invalid or expired reset code"
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
async function deactivateCustomerAccount(config, accessToken, payload) {
|
|
691
|
+
try {
|
|
692
|
+
const data = await apiRequest(`${config.backendUrls.auth}/auth/customer/deactivate/`, {
|
|
693
|
+
method: "POST",
|
|
694
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
695
|
+
body: JSON.stringify(payload || {}),
|
|
696
|
+
fallbackErrorMessage: "Failed to deactivate account"
|
|
697
|
+
});
|
|
698
|
+
return { status: "success", detail: data.detail };
|
|
699
|
+
} catch (err) {
|
|
700
|
+
if (err instanceof ApiError && err.status === 409) {
|
|
701
|
+
return { status: "confirmation_required", data: err.body };
|
|
702
|
+
}
|
|
703
|
+
throw err;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
async function requestCustomerReactivation(config, payload) {
|
|
707
|
+
return apiRequest(`${config.backendUrls.auth}/auth/customer/reactivate/`, {
|
|
708
|
+
method: "POST",
|
|
709
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
710
|
+
body: JSON.stringify(payload),
|
|
711
|
+
fallbackErrorMessage: "Failed to request reactivation"
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
async function verifyCustomerReactivation(config, payload) {
|
|
715
|
+
return apiRequest(`${config.backendUrls.auth}/auth/customer/reactivate/verify/`, {
|
|
716
|
+
method: "POST",
|
|
717
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
718
|
+
body: JSON.stringify(payload),
|
|
719
|
+
fallbackErrorMessage: "Invalid or expired reactivation code"
|
|
720
|
+
});
|
|
451
721
|
}
|
|
452
722
|
function parseJwtPayload(token) {
|
|
453
723
|
try {
|
|
@@ -502,70 +772,94 @@ function buildCustomerFromClaims(claims) {
|
|
|
502
772
|
}
|
|
503
773
|
async function getMe(config, accessToken) {
|
|
504
774
|
if (!config || !accessToken) {
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
775
|
+
const data2 = await apiRequest("/api/auth/me", {
|
|
776
|
+
credentials: "include",
|
|
777
|
+
fallbackErrorMessage: "Failed to fetch profile"
|
|
778
|
+
});
|
|
779
|
+
return mapAuthUserToCustomer(data2.user);
|
|
509
780
|
}
|
|
510
|
-
const
|
|
511
|
-
headers:
|
|
512
|
-
|
|
513
|
-
}
|
|
781
|
+
const data = await apiRequest(`${config.backendUrls.auth}/auth/profile/`, {
|
|
782
|
+
headers: authHeaders(config, accessToken),
|
|
783
|
+
fallbackErrorMessage: "Failed to fetch profile"
|
|
514
784
|
});
|
|
515
|
-
if (!response.ok) {
|
|
516
|
-
throw new Error("Failed to fetch profile");
|
|
517
|
-
}
|
|
518
|
-
const data = await response.json();
|
|
519
785
|
return mapAuthUserToCustomer(data);
|
|
520
786
|
}
|
|
521
787
|
async function getAuthUser(config, accessToken) {
|
|
522
788
|
if (!config || !accessToken) {
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
789
|
+
const data = await apiRequest("/api/auth/me", {
|
|
790
|
+
credentials: "include",
|
|
791
|
+
fallbackErrorMessage: "Failed to fetch auth user"
|
|
792
|
+
});
|
|
793
|
+
return data.user;
|
|
527
794
|
}
|
|
528
|
-
|
|
529
|
-
headers:
|
|
530
|
-
|
|
531
|
-
}
|
|
795
|
+
return apiRequest(`${config.backendUrls.auth}/auth/profile/`, {
|
|
796
|
+
headers: authHeaders(config, accessToken),
|
|
797
|
+
fallbackErrorMessage: "Failed to fetch auth user"
|
|
532
798
|
});
|
|
533
|
-
if (!response.ok) {
|
|
534
|
-
throw new Error("Failed to fetch auth user");
|
|
535
|
-
}
|
|
536
|
-
const data = await response.json();
|
|
537
|
-
return data;
|
|
538
799
|
}
|
|
539
800
|
async function updateProfile(configOrPayload, accessTokenOrPayload, payloadParam) {
|
|
540
801
|
const isArg1Config = typeof configOrPayload === "object" && configOrPayload !== null && "businessId" in configOrPayload;
|
|
541
802
|
if (!isArg1Config) {
|
|
542
803
|
const payload2 = configOrPayload;
|
|
543
|
-
|
|
804
|
+
return apiRequest("/api/auth/profile", {
|
|
544
805
|
method: "PUT",
|
|
545
|
-
headers:
|
|
806
|
+
headers: JSON_HEADERS,
|
|
546
807
|
credentials: "include",
|
|
547
|
-
body: JSON.stringify(payload2)
|
|
808
|
+
body: JSON.stringify(payload2),
|
|
809
|
+
fallbackErrorMessage: "Failed to update profile"
|
|
548
810
|
});
|
|
549
|
-
if (!response2.ok) throw new Error("Failed to update profile");
|
|
550
|
-
return response2.json();
|
|
551
811
|
}
|
|
552
812
|
const config = configOrPayload;
|
|
553
813
|
const accessToken = accessTokenOrPayload;
|
|
554
814
|
const payload = payloadParam;
|
|
555
|
-
const
|
|
815
|
+
const data = await apiRequest(`${config.backendUrls.auth}/auth/profile/`, {
|
|
556
816
|
method: "PUT",
|
|
557
|
-
headers: {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
},
|
|
561
|
-
body: JSON.stringify(payload)
|
|
817
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
818
|
+
body: JSON.stringify(payload),
|
|
819
|
+
fallbackErrorMessage: "Failed to update profile"
|
|
562
820
|
});
|
|
563
|
-
if (!response.ok) {
|
|
564
|
-
throw new Error("Failed to update profile");
|
|
565
|
-
}
|
|
566
|
-
const data = await response.json();
|
|
567
821
|
return mapAuthUserToCustomer(data);
|
|
568
822
|
}
|
|
823
|
+
async function changePassword(config, accessToken, payload) {
|
|
824
|
+
return apiRequest(`${config.backendUrls.auth}/auth/change-password/`, {
|
|
825
|
+
method: "POST",
|
|
826
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
827
|
+
body: JSON.stringify(payload),
|
|
828
|
+
fallbackErrorMessage: "Failed to change password"
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
async function getStorefrontBusinessInfo(config) {
|
|
832
|
+
return apiRequest(`${config.backendUrls.auth}/auth/storefront/business-info/`, {
|
|
833
|
+
headers: storefrontHeaders(config),
|
|
834
|
+
fallbackErrorMessage: "Failed to fetch business info"
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
async function getPresignedUploadUrl(config, accessToken, params) {
|
|
838
|
+
const query = new URLSearchParams(
|
|
839
|
+
Object.entries(params).filter(([, v]) => v !== void 0)
|
|
840
|
+
);
|
|
841
|
+
return apiRequest(
|
|
842
|
+
`${config.backendUrls.auth}/auth/media/presigned-url/?${query.toString()}`,
|
|
843
|
+
{
|
|
844
|
+
method: "POST",
|
|
845
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
846
|
+
fallbackErrorMessage: "Failed to get presigned upload URL"
|
|
847
|
+
}
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
async function confirmMediaUpload(config, accessToken, params) {
|
|
851
|
+
const query = new URLSearchParams(
|
|
852
|
+
Object.entries(params).filter(([, v]) => v !== void 0)
|
|
853
|
+
);
|
|
854
|
+
return apiRequest(
|
|
855
|
+
`${config.backendUrls.auth}/auth/media/confirm-upload/?${query.toString()}`,
|
|
856
|
+
{
|
|
857
|
+
method: "POST",
|
|
858
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
859
|
+
fallbackErrorMessage: "Failed to confirm upload"
|
|
860
|
+
}
|
|
861
|
+
);
|
|
862
|
+
}
|
|
569
863
|
async function silentRefresh(config, refresh) {
|
|
570
864
|
try {
|
|
571
865
|
const data = await refreshToken(config, refresh);
|
|
@@ -576,25 +870,11 @@ async function silentRefresh(config, refresh) {
|
|
|
576
870
|
const user = buildCustomerFromClaims(claims);
|
|
577
871
|
const provider = user.provider;
|
|
578
872
|
return { user, provider, newAccessToken: data.access, newRefreshToken: data.refresh };
|
|
579
|
-
} catch {
|
|
873
|
+
} catch (err) {
|
|
874
|
+
console.error("[auth.service] Silent token refresh failed:", err);
|
|
580
875
|
return null;
|
|
581
876
|
}
|
|
582
877
|
}
|
|
583
|
-
function buildFullName(firstname, lastname) {
|
|
584
|
-
if (firstname && lastname) return `${firstname} ${lastname}`;
|
|
585
|
-
return firstname || lastname || "";
|
|
586
|
-
}
|
|
587
|
-
function splitFullName(fullName) {
|
|
588
|
-
if (!fullName) return { firstname: "", lastname: "" };
|
|
589
|
-
const parts = fullName.trim().split(/\s+/);
|
|
590
|
-
if (parts.length === 1) {
|
|
591
|
-
return { firstname: parts[0], lastname: "" };
|
|
592
|
-
}
|
|
593
|
-
return {
|
|
594
|
-
firstname: parts[0],
|
|
595
|
-
lastname: parts.slice(1).join(" ")
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
878
|
function storeTokens(accessToken, refreshToken2) {
|
|
599
879
|
if (typeof window !== "undefined") {
|
|
600
880
|
localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, accessToken);
|
|
@@ -616,1061 +896,369 @@ function getStoredTokens() {
|
|
|
616
896
|
refreshToken: localStorage.getItem(STORAGE_KEYS.REFRESH_TOKEN)
|
|
617
897
|
};
|
|
618
898
|
}
|
|
899
|
+
async function getCustomerAddresses(config, accessToken) {
|
|
900
|
+
const data = await apiRequest(`${config.backendUrls.auth}/auth/profile/addresses/`, {
|
|
901
|
+
headers: authHeaders(config, accessToken),
|
|
902
|
+
fallbackErrorMessage: "Failed to fetch saved addresses"
|
|
903
|
+
});
|
|
904
|
+
return data.results;
|
|
905
|
+
}
|
|
906
|
+
async function createCustomerAddress(config, accessToken, payload) {
|
|
907
|
+
return apiRequest(`${config.backendUrls.auth}/auth/profile/addresses/`, {
|
|
908
|
+
method: "POST",
|
|
909
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
910
|
+
body: JSON.stringify(payload),
|
|
911
|
+
fallbackErrorMessage: "Failed to save address"
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
async function updateCustomerAddress(config, accessToken, addressId, payload) {
|
|
915
|
+
return apiRequest(`${config.backendUrls.auth}/auth/profile/addresses/${addressId}/`, {
|
|
916
|
+
method: "PATCH",
|
|
917
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
918
|
+
body: JSON.stringify(payload),
|
|
919
|
+
fallbackErrorMessage: "Failed to update address"
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
async function deleteCustomerAddress(config, accessToken, addressId) {
|
|
923
|
+
await apiRequest(`${config.backendUrls.auth}/auth/profile/addresses/${addressId}/`, {
|
|
924
|
+
method: "DELETE",
|
|
925
|
+
headers: authHeaders(config, accessToken),
|
|
926
|
+
fallbackErrorMessage: "Failed to delete address"
|
|
927
|
+
});
|
|
928
|
+
}
|
|
619
929
|
|
|
620
|
-
// src/
|
|
930
|
+
// src/utils/graphql-url.ts
|
|
621
931
|
import { GraphQLClient } from "graphql-request";
|
|
622
|
-
function
|
|
932
|
+
function resolveGraphQLEndpoint(url) {
|
|
933
|
+
if (typeof window === "undefined") return url;
|
|
934
|
+
try {
|
|
935
|
+
new URL(url);
|
|
936
|
+
return url;
|
|
937
|
+
} catch {
|
|
938
|
+
return `${window.location.origin}${url}`;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function createGraphQLClient(config, accessToken) {
|
|
623
942
|
const headers = {
|
|
624
943
|
"Content-Type": "application/json",
|
|
625
944
|
"Accept": "application/json",
|
|
626
945
|
"X-Storefront-Key": config.storefrontApiKey,
|
|
627
946
|
"X-Business-ID": config.businessId
|
|
628
947
|
};
|
|
629
|
-
|
|
630
|
-
}
|
|
631
|
-
var GET_STOREFRONT_PRODUCTS = `
|
|
632
|
-
query GetStorefrontProducts($page: Int!, $pageSize: Int!, $collectionSlug: String, $search: String) {
|
|
633
|
-
storefront_products(page: $page, pageSize: $pageSize, collectionSlug: $collectionSlug, search: $search) {
|
|
634
|
-
items {
|
|
635
|
-
id
|
|
636
|
-
business_id
|
|
637
|
-
name
|
|
638
|
-
slug
|
|
639
|
-
description
|
|
640
|
-
brand
|
|
641
|
-
product_type
|
|
642
|
-
requires_shipping
|
|
643
|
-
is_consumable
|
|
644
|
-
is_bespoke
|
|
645
|
-
base_price
|
|
646
|
-
currency
|
|
647
|
-
images
|
|
648
|
-
tags
|
|
649
|
-
custom_fields { label unit required }
|
|
650
|
-
is_published
|
|
651
|
-
is_featured
|
|
652
|
-
is_popular
|
|
653
|
-
is_new
|
|
654
|
-
is_temporary
|
|
655
|
-
digital_file_key
|
|
656
|
-
download_limit
|
|
657
|
-
download_expires_at
|
|
658
|
-
weight_kg
|
|
659
|
-
length_cm
|
|
660
|
-
width_cm
|
|
661
|
-
height_cm
|
|
662
|
-
created_at
|
|
663
|
-
updated_at
|
|
664
|
-
variants {
|
|
665
|
-
id
|
|
666
|
-
product_id
|
|
667
|
-
sku
|
|
668
|
-
attributes
|
|
669
|
-
price
|
|
670
|
-
images
|
|
671
|
-
weight_kg
|
|
672
|
-
is_active
|
|
673
|
-
inventory {
|
|
674
|
-
id
|
|
675
|
-
product_id
|
|
676
|
-
variant_id
|
|
677
|
-
quantity
|
|
678
|
-
reserved
|
|
679
|
-
reorder_point
|
|
680
|
-
reorder_quantity
|
|
681
|
-
track_quantity
|
|
682
|
-
allow_backorder
|
|
683
|
-
available
|
|
684
|
-
is_in_stock
|
|
685
|
-
is_low_stock
|
|
686
|
-
updated_at
|
|
687
|
-
}
|
|
688
|
-
created_at
|
|
689
|
-
updated_at
|
|
690
|
-
}
|
|
691
|
-
collections {
|
|
692
|
-
id
|
|
693
|
-
business_id
|
|
694
|
-
name
|
|
695
|
-
slug
|
|
696
|
-
description
|
|
697
|
-
image
|
|
698
|
-
collection_type
|
|
699
|
-
rules
|
|
700
|
-
status
|
|
701
|
-
sort_order
|
|
702
|
-
created_at
|
|
703
|
-
updated_at
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
total
|
|
707
|
-
page
|
|
708
|
-
page_size
|
|
709
|
-
total_pages
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
`;
|
|
713
|
-
var GET_STOREFRONT_PRODUCT_BY_SLUG = `
|
|
714
|
-
query GetStorefrontProductBySlug($slug: String!) {
|
|
715
|
-
storefront_product_by_slug(slug: $slug) {
|
|
716
|
-
id
|
|
717
|
-
business_id
|
|
718
|
-
name
|
|
719
|
-
slug
|
|
720
|
-
description
|
|
721
|
-
brand
|
|
722
|
-
product_type
|
|
723
|
-
requires_shipping
|
|
724
|
-
is_consumable
|
|
725
|
-
is_bespoke
|
|
726
|
-
base_price
|
|
727
|
-
currency
|
|
728
|
-
images
|
|
729
|
-
tags
|
|
730
|
-
custom_fields { label unit required }
|
|
731
|
-
is_published
|
|
732
|
-
is_featured
|
|
733
|
-
is_popular
|
|
734
|
-
is_new
|
|
735
|
-
is_temporary
|
|
736
|
-
digital_file_key
|
|
737
|
-
download_limit
|
|
738
|
-
download_expires_at
|
|
739
|
-
weight_kg
|
|
740
|
-
length_cm
|
|
741
|
-
width_cm
|
|
742
|
-
height_cm
|
|
743
|
-
created_at
|
|
744
|
-
updated_at
|
|
745
|
-
variants {
|
|
746
|
-
id
|
|
747
|
-
product_id
|
|
748
|
-
sku
|
|
749
|
-
attributes
|
|
750
|
-
price
|
|
751
|
-
images
|
|
752
|
-
weight_kg
|
|
753
|
-
is_active
|
|
754
|
-
inventory {
|
|
755
|
-
id
|
|
756
|
-
product_id
|
|
757
|
-
variant_id
|
|
758
|
-
quantity
|
|
759
|
-
reserved
|
|
760
|
-
reorder_point
|
|
761
|
-
reorder_quantity
|
|
762
|
-
track_quantity
|
|
763
|
-
allow_backorder
|
|
764
|
-
available
|
|
765
|
-
is_in_stock
|
|
766
|
-
is_low_stock
|
|
767
|
-
updated_at
|
|
768
|
-
}
|
|
769
|
-
created_at
|
|
770
|
-
updated_at
|
|
771
|
-
}
|
|
772
|
-
collections {
|
|
773
|
-
id
|
|
774
|
-
business_id
|
|
775
|
-
name
|
|
776
|
-
slug
|
|
777
|
-
description
|
|
778
|
-
image
|
|
779
|
-
collection_type
|
|
780
|
-
rules
|
|
781
|
-
status
|
|
782
|
-
sort_order
|
|
783
|
-
created_at
|
|
784
|
-
updated_at
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
`;
|
|
789
|
-
var GET_STOREFRONT_LATEST = `
|
|
790
|
-
query GetStorefrontLatest($page: Int!, $pageSize: Int!) {
|
|
791
|
-
storefront_latest(page: $page, pageSize: $pageSize) {
|
|
792
|
-
items {
|
|
793
|
-
id
|
|
794
|
-
business_id
|
|
795
|
-
name
|
|
796
|
-
slug
|
|
797
|
-
description
|
|
798
|
-
brand
|
|
799
|
-
product_type
|
|
800
|
-
requires_shipping
|
|
801
|
-
is_consumable
|
|
802
|
-
is_bespoke
|
|
803
|
-
base_price
|
|
804
|
-
currency
|
|
805
|
-
images
|
|
806
|
-
tags
|
|
807
|
-
custom_fields { label unit required }
|
|
808
|
-
is_published
|
|
809
|
-
is_featured
|
|
810
|
-
is_popular
|
|
811
|
-
is_new
|
|
812
|
-
is_temporary
|
|
813
|
-
digital_file_key
|
|
814
|
-
download_limit
|
|
815
|
-
download_expires_at
|
|
816
|
-
weight_kg
|
|
817
|
-
length_cm
|
|
818
|
-
width_cm
|
|
819
|
-
height_cm
|
|
820
|
-
created_at
|
|
821
|
-
updated_at
|
|
822
|
-
variants {
|
|
823
|
-
id
|
|
824
|
-
product_id
|
|
825
|
-
sku
|
|
826
|
-
attributes
|
|
827
|
-
price
|
|
828
|
-
images
|
|
829
|
-
weight_kg
|
|
830
|
-
is_active
|
|
831
|
-
inventory {
|
|
832
|
-
id
|
|
833
|
-
product_id
|
|
834
|
-
variant_id
|
|
835
|
-
quantity
|
|
836
|
-
reserved
|
|
837
|
-
reorder_point
|
|
838
|
-
reorder_quantity
|
|
839
|
-
track_quantity
|
|
840
|
-
allow_backorder
|
|
841
|
-
available
|
|
842
|
-
is_in_stock
|
|
843
|
-
is_low_stock
|
|
844
|
-
updated_at
|
|
845
|
-
}
|
|
846
|
-
created_at
|
|
847
|
-
updated_at
|
|
848
|
-
}
|
|
849
|
-
collections {
|
|
850
|
-
id
|
|
851
|
-
business_id
|
|
852
|
-
name
|
|
853
|
-
slug
|
|
854
|
-
description
|
|
855
|
-
image
|
|
856
|
-
collection_type
|
|
857
|
-
rules
|
|
858
|
-
status
|
|
859
|
-
sort_order
|
|
860
|
-
created_at
|
|
861
|
-
updated_at
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
total
|
|
865
|
-
page
|
|
866
|
-
page_size
|
|
867
|
-
total_pages
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
`;
|
|
871
|
-
var GET_STOREFRONT_POPULAR = `
|
|
872
|
-
query GetStorefrontPopular($page: Int!, $pageSize: Int!) {
|
|
873
|
-
storefront_popular(page: $page, pageSize: $pageSize) {
|
|
874
|
-
items {
|
|
875
|
-
id
|
|
876
|
-
business_id
|
|
877
|
-
name
|
|
878
|
-
slug
|
|
879
|
-
description
|
|
880
|
-
brand
|
|
881
|
-
product_type
|
|
882
|
-
requires_shipping
|
|
883
|
-
is_consumable
|
|
884
|
-
is_bespoke
|
|
885
|
-
base_price
|
|
886
|
-
currency
|
|
887
|
-
images
|
|
888
|
-
tags
|
|
889
|
-
custom_fields { label unit required }
|
|
890
|
-
is_published
|
|
891
|
-
is_featured
|
|
892
|
-
is_popular
|
|
893
|
-
is_new
|
|
894
|
-
is_temporary
|
|
895
|
-
digital_file_key
|
|
896
|
-
download_limit
|
|
897
|
-
download_expires_at
|
|
898
|
-
weight_kg
|
|
899
|
-
length_cm
|
|
900
|
-
width_cm
|
|
901
|
-
height_cm
|
|
902
|
-
created_at
|
|
903
|
-
updated_at
|
|
904
|
-
variants {
|
|
905
|
-
id
|
|
906
|
-
product_id
|
|
907
|
-
sku
|
|
908
|
-
attributes
|
|
909
|
-
price
|
|
910
|
-
images
|
|
911
|
-
weight_kg
|
|
912
|
-
is_active
|
|
913
|
-
inventory {
|
|
914
|
-
id
|
|
915
|
-
product_id
|
|
916
|
-
variant_id
|
|
917
|
-
quantity
|
|
918
|
-
reserved
|
|
919
|
-
reorder_point
|
|
920
|
-
reorder_quantity
|
|
921
|
-
track_quantity
|
|
922
|
-
allow_backorder
|
|
923
|
-
available
|
|
924
|
-
is_in_stock
|
|
925
|
-
is_low_stock
|
|
926
|
-
updated_at
|
|
927
|
-
}
|
|
928
|
-
created_at
|
|
929
|
-
updated_at
|
|
930
|
-
}
|
|
931
|
-
collections {
|
|
932
|
-
id
|
|
933
|
-
business_id
|
|
934
|
-
name
|
|
935
|
-
slug
|
|
936
|
-
description
|
|
937
|
-
image
|
|
938
|
-
collection_type
|
|
939
|
-
rules
|
|
940
|
-
status
|
|
941
|
-
sort_order
|
|
942
|
-
created_at
|
|
943
|
-
updated_at
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
total
|
|
947
|
-
page
|
|
948
|
-
page_size
|
|
949
|
-
total_pages
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
`;
|
|
953
|
-
var GET_STOREFRONT_FEATURED = `
|
|
954
|
-
query GetStorefrontFeatured($page: Int!, $pageSize: Int!) {
|
|
955
|
-
storefront_featured(page: $page, pageSize: $pageSize) {
|
|
956
|
-
items {
|
|
957
|
-
id
|
|
958
|
-
business_id
|
|
959
|
-
name
|
|
960
|
-
slug
|
|
961
|
-
description
|
|
962
|
-
brand
|
|
963
|
-
product_type
|
|
964
|
-
requires_shipping
|
|
965
|
-
is_consumable
|
|
966
|
-
is_bespoke
|
|
967
|
-
base_price
|
|
968
|
-
currency
|
|
969
|
-
images
|
|
970
|
-
tags
|
|
971
|
-
custom_fields { label unit required }
|
|
972
|
-
is_published
|
|
973
|
-
is_featured
|
|
974
|
-
is_popular
|
|
975
|
-
is_new
|
|
976
|
-
is_temporary
|
|
977
|
-
digital_file_key
|
|
978
|
-
download_limit
|
|
979
|
-
download_expires_at
|
|
980
|
-
weight_kg
|
|
981
|
-
length_cm
|
|
982
|
-
width_cm
|
|
983
|
-
height_cm
|
|
984
|
-
created_at
|
|
985
|
-
updated_at
|
|
986
|
-
variants {
|
|
987
|
-
id
|
|
988
|
-
product_id
|
|
989
|
-
sku
|
|
990
|
-
attributes
|
|
991
|
-
price
|
|
992
|
-
images
|
|
993
|
-
weight_kg
|
|
994
|
-
is_active
|
|
995
|
-
inventory {
|
|
996
|
-
id
|
|
997
|
-
product_id
|
|
998
|
-
variant_id
|
|
999
|
-
quantity
|
|
1000
|
-
reserved
|
|
1001
|
-
reorder_point
|
|
1002
|
-
reorder_quantity
|
|
1003
|
-
track_quantity
|
|
1004
|
-
allow_backorder
|
|
1005
|
-
available
|
|
1006
|
-
is_in_stock
|
|
1007
|
-
is_low_stock
|
|
1008
|
-
updated_at
|
|
1009
|
-
}
|
|
1010
|
-
created_at
|
|
1011
|
-
updated_at
|
|
1012
|
-
}
|
|
1013
|
-
collections {
|
|
1014
|
-
id
|
|
1015
|
-
business_id
|
|
1016
|
-
name
|
|
1017
|
-
slug
|
|
1018
|
-
description
|
|
1019
|
-
image
|
|
1020
|
-
collection_type
|
|
1021
|
-
rules
|
|
1022
|
-
status
|
|
1023
|
-
sort_order
|
|
1024
|
-
created_at
|
|
1025
|
-
updated_at
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
total
|
|
1029
|
-
page
|
|
1030
|
-
page_size
|
|
1031
|
-
total_pages
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
`;
|
|
1035
|
-
var GET_STOREFRONT_NEW = `
|
|
1036
|
-
query GetStorefrontNew($page: Int!, $pageSize: Int!) {
|
|
1037
|
-
storefront_new(page: $page, pageSize: $pageSize) {
|
|
1038
|
-
items {
|
|
1039
|
-
id
|
|
1040
|
-
business_id
|
|
1041
|
-
name
|
|
1042
|
-
slug
|
|
1043
|
-
description
|
|
1044
|
-
brand
|
|
1045
|
-
product_type
|
|
1046
|
-
requires_shipping
|
|
1047
|
-
is_consumable
|
|
1048
|
-
is_bespoke
|
|
1049
|
-
base_price
|
|
1050
|
-
currency
|
|
1051
|
-
sale_price
|
|
1052
|
-
sale_start
|
|
1053
|
-
sale_end
|
|
1054
|
-
images
|
|
1055
|
-
tags
|
|
1056
|
-
custom_fields { label unit required }
|
|
1057
|
-
is_published
|
|
1058
|
-
is_featured
|
|
1059
|
-
is_popular
|
|
1060
|
-
is_new
|
|
1061
|
-
is_temporary
|
|
1062
|
-
digital_file_key
|
|
1063
|
-
download_limit
|
|
1064
|
-
download_expires_at
|
|
1065
|
-
weight_kg
|
|
1066
|
-
length_cm
|
|
1067
|
-
width_cm
|
|
1068
|
-
height_cm
|
|
1069
|
-
created_at
|
|
1070
|
-
updated_at
|
|
1071
|
-
variants {
|
|
1072
|
-
id
|
|
1073
|
-
product_id
|
|
1074
|
-
sku
|
|
1075
|
-
attributes
|
|
1076
|
-
price
|
|
1077
|
-
images
|
|
1078
|
-
weight_kg
|
|
1079
|
-
is_active
|
|
1080
|
-
inventory {
|
|
1081
|
-
id
|
|
1082
|
-
product_id
|
|
1083
|
-
variant_id
|
|
1084
|
-
quantity
|
|
1085
|
-
reserved
|
|
1086
|
-
reorder_point
|
|
1087
|
-
reorder_quantity
|
|
1088
|
-
track_quantity
|
|
1089
|
-
allow_backorder
|
|
1090
|
-
available
|
|
1091
|
-
is_in_stock
|
|
1092
|
-
is_low_stock
|
|
1093
|
-
updated_at
|
|
1094
|
-
}
|
|
1095
|
-
created_at
|
|
1096
|
-
updated_at
|
|
1097
|
-
}
|
|
1098
|
-
collections {
|
|
1099
|
-
id
|
|
1100
|
-
business_id
|
|
1101
|
-
name
|
|
1102
|
-
slug
|
|
1103
|
-
description
|
|
1104
|
-
image
|
|
1105
|
-
collection_type
|
|
1106
|
-
rules
|
|
1107
|
-
status
|
|
1108
|
-
sort_order
|
|
1109
|
-
created_at
|
|
1110
|
-
updated_at
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
total
|
|
1114
|
-
page
|
|
1115
|
-
page_size
|
|
1116
|
-
total_pages
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
`;
|
|
1120
|
-
var GET_STOREFRONT_ON_SALE = `
|
|
1121
|
-
query GetStorefrontOnSale($page: Int!, $pageSize: Int!) {
|
|
1122
|
-
storefront_on_sale(page: $page, pageSize: $pageSize) {
|
|
1123
|
-
items {
|
|
1124
|
-
id
|
|
1125
|
-
business_id
|
|
1126
|
-
name
|
|
1127
|
-
slug
|
|
1128
|
-
description
|
|
1129
|
-
brand
|
|
1130
|
-
product_type
|
|
1131
|
-
requires_shipping
|
|
1132
|
-
is_consumable
|
|
1133
|
-
is_bespoke
|
|
1134
|
-
base_price
|
|
1135
|
-
currency
|
|
1136
|
-
sale_price
|
|
1137
|
-
sale_start
|
|
1138
|
-
sale_end
|
|
1139
|
-
images
|
|
1140
|
-
tags
|
|
1141
|
-
custom_fields { label unit required }
|
|
1142
|
-
is_published
|
|
1143
|
-
is_featured
|
|
1144
|
-
is_popular
|
|
1145
|
-
is_new
|
|
1146
|
-
is_temporary
|
|
1147
|
-
digital_file_key
|
|
1148
|
-
download_limit
|
|
1149
|
-
download_expires_at
|
|
1150
|
-
weight_kg
|
|
1151
|
-
length_cm
|
|
1152
|
-
width_cm
|
|
1153
|
-
height_cm
|
|
1154
|
-
created_at
|
|
1155
|
-
updated_at
|
|
1156
|
-
variants {
|
|
1157
|
-
id
|
|
1158
|
-
product_id
|
|
1159
|
-
sku
|
|
1160
|
-
attributes
|
|
1161
|
-
price
|
|
1162
|
-
images
|
|
1163
|
-
weight_kg
|
|
1164
|
-
is_active
|
|
1165
|
-
inventory {
|
|
1166
|
-
id
|
|
1167
|
-
product_id
|
|
1168
|
-
variant_id
|
|
1169
|
-
quantity
|
|
1170
|
-
reserved
|
|
1171
|
-
reorder_point
|
|
1172
|
-
reorder_quantity
|
|
1173
|
-
track_quantity
|
|
1174
|
-
allow_backorder
|
|
1175
|
-
available
|
|
1176
|
-
is_in_stock
|
|
1177
|
-
is_low_stock
|
|
1178
|
-
updated_at
|
|
1179
|
-
}
|
|
1180
|
-
created_at
|
|
1181
|
-
updated_at
|
|
1182
|
-
}
|
|
1183
|
-
collections {
|
|
1184
|
-
id
|
|
1185
|
-
business_id
|
|
1186
|
-
name
|
|
1187
|
-
slug
|
|
1188
|
-
description
|
|
1189
|
-
image
|
|
1190
|
-
collection_type
|
|
1191
|
-
rules
|
|
1192
|
-
status
|
|
1193
|
-
sort_order
|
|
1194
|
-
created_at
|
|
1195
|
-
updated_at
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
total
|
|
1199
|
-
page
|
|
1200
|
-
page_size
|
|
1201
|
-
total_pages
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
`;
|
|
1205
|
-
var GET_STOREFRONT_LOW_STOCK = `
|
|
1206
|
-
query GetStorefrontLowStock($page: Int!, $pageSize: Int!) {
|
|
1207
|
-
storefront_low_stock(page: $page, pageSize: $pageSize) {
|
|
1208
|
-
items {
|
|
1209
|
-
id
|
|
1210
|
-
business_id
|
|
1211
|
-
name
|
|
1212
|
-
slug
|
|
1213
|
-
description
|
|
1214
|
-
brand
|
|
1215
|
-
product_type
|
|
1216
|
-
requires_shipping
|
|
1217
|
-
is_consumable
|
|
1218
|
-
is_bespoke
|
|
1219
|
-
base_price
|
|
1220
|
-
currency
|
|
1221
|
-
sale_price
|
|
1222
|
-
sale_start
|
|
1223
|
-
sale_end
|
|
1224
|
-
images
|
|
1225
|
-
tags
|
|
1226
|
-
custom_fields { label unit required }
|
|
1227
|
-
is_published
|
|
1228
|
-
is_featured
|
|
1229
|
-
is_popular
|
|
1230
|
-
is_new
|
|
1231
|
-
is_temporary
|
|
1232
|
-
digital_file_key
|
|
1233
|
-
download_limit
|
|
1234
|
-
download_expires_at
|
|
1235
|
-
weight_kg
|
|
1236
|
-
length_cm
|
|
1237
|
-
width_cm
|
|
1238
|
-
height_cm
|
|
1239
|
-
created_at
|
|
1240
|
-
updated_at
|
|
1241
|
-
variants {
|
|
1242
|
-
id
|
|
1243
|
-
product_id
|
|
1244
|
-
sku
|
|
1245
|
-
attributes
|
|
1246
|
-
price
|
|
1247
|
-
images
|
|
1248
|
-
weight_kg
|
|
1249
|
-
is_active
|
|
1250
|
-
inventory {
|
|
1251
|
-
id
|
|
1252
|
-
product_id
|
|
1253
|
-
variant_id
|
|
1254
|
-
quantity
|
|
1255
|
-
reserved
|
|
1256
|
-
reorder_point
|
|
1257
|
-
reorder_quantity
|
|
1258
|
-
track_quantity
|
|
1259
|
-
allow_backorder
|
|
1260
|
-
available
|
|
1261
|
-
is_in_stock
|
|
1262
|
-
is_low_stock
|
|
1263
|
-
updated_at
|
|
1264
|
-
}
|
|
1265
|
-
created_at
|
|
1266
|
-
updated_at
|
|
1267
|
-
}
|
|
1268
|
-
collections {
|
|
1269
|
-
id
|
|
1270
|
-
business_id
|
|
1271
|
-
name
|
|
1272
|
-
slug
|
|
1273
|
-
description
|
|
1274
|
-
image
|
|
1275
|
-
collection_type
|
|
1276
|
-
rules
|
|
1277
|
-
status
|
|
1278
|
-
sort_order
|
|
1279
|
-
created_at
|
|
1280
|
-
updated_at
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
total
|
|
1284
|
-
page
|
|
1285
|
-
page_size
|
|
1286
|
-
total_pages
|
|
1287
|
-
}
|
|
948
|
+
if (accessToken) {
|
|
949
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
1288
950
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
business_id
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
width_cm
|
|
1320
|
-
height_cm
|
|
1321
|
-
created_at
|
|
1322
|
-
updated_at
|
|
1323
|
-
variants {
|
|
1324
|
-
id
|
|
1325
|
-
product_id
|
|
1326
|
-
sku
|
|
1327
|
-
attributes
|
|
1328
|
-
price
|
|
1329
|
-
images
|
|
1330
|
-
weight_kg
|
|
1331
|
-
is_active
|
|
1332
|
-
inventory {
|
|
1333
|
-
id
|
|
1334
|
-
product_id
|
|
1335
|
-
variant_id
|
|
1336
|
-
quantity
|
|
1337
|
-
reserved
|
|
1338
|
-
reorder_point
|
|
1339
|
-
reorder_quantity
|
|
1340
|
-
track_quantity
|
|
1341
|
-
allow_backorder
|
|
1342
|
-
available
|
|
1343
|
-
is_in_stock
|
|
1344
|
-
is_low_stock
|
|
1345
|
-
updated_at
|
|
1346
|
-
}
|
|
1347
|
-
created_at
|
|
1348
|
-
updated_at
|
|
1349
|
-
}
|
|
1350
|
-
collections {
|
|
1351
|
-
id
|
|
1352
|
-
business_id
|
|
1353
|
-
name
|
|
1354
|
-
slug
|
|
1355
|
-
description
|
|
1356
|
-
image
|
|
1357
|
-
collection_type
|
|
1358
|
-
rules
|
|
1359
|
-
status
|
|
1360
|
-
sort_order
|
|
1361
|
-
created_at
|
|
1362
|
-
updated_at
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
total
|
|
1366
|
-
page
|
|
1367
|
-
page_size
|
|
1368
|
-
total_pages
|
|
951
|
+
return new GraphQLClient(resolveGraphQLEndpoint(`${config.backendUrls.store}/graphql`), { headers });
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/generated/graphql.ts
|
|
955
|
+
var GetStorefrontCollectionsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontCollections" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_collections" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "CollectionFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "CollectionFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Collection" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] };
|
|
956
|
+
var GetStorefrontCollectionBySlugDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontCollectionBySlug" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "slug" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_collection_by_slug" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "slug" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "slug" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "CollectionFields" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "CollectionFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Collection" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] };
|
|
957
|
+
var GetStorefrontProductsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontProducts" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "collectionSlug" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "search" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "productType" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_products" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "collectionSlug" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "collectionSlug" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "search" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "search" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "productType" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "productType" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
958
|
+
var GetStorefrontProductBySlugDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontProductBySlug" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "slug" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_product_by_slug" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "slug" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "slug" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
959
|
+
var GetStorefrontPopularDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontPopular" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_popular" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
960
|
+
var GetStorefrontFeaturedDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontFeatured" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_featured" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
961
|
+
var GetStorefrontNewDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontNew" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_new" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
962
|
+
var GetStorefrontOnSaleDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontOnSale" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_on_sale" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
963
|
+
var GetStorefrontRecommendedDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontRecommended" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "excludeProductId" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_recommended" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "excludeProductId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "excludeProductId" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "ProductFields" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "ProductFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "Product" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "brand" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "requires_shipping" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_consumable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_bespoke" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_physical" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_non_returnable" } }, { "kind": "Field", "name": { "kind": "Name", "value": "deposit_percentage" } }, { "kind": "Field", "name": { "kind": "Name", "value": "base_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_start" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sale_end" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tags" } }, { "kind": "Field", "name": { "kind": "Name", "value": "custom_fields" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "label" } }, { "kind": "Field", "name": { "kind": "Name", "value": "unit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "required" } }, { "kind": "Field", "name": { "kind": "Name", "value": "field_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "options" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_published" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_featured" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_popular" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_new" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_temporary" } }, { "kind": "Field", "name": { "kind": "Name", "value": "average_rating" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rating_count" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel" } }, { "kind": "Field", "name": { "kind": "Name", "value": "source_channel_ref_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_duration_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_location_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_coverage_radius_km" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_requires_consultation" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_max_capacity_per_slot" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_buffer_minutes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_is_recurring" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_recurring_interval" } }, { "kind": "Field", "name": { "kind": "Name", "value": "service_project_based" } }, { "kind": "Field", "name": { "kind": "Name", "value": "digital_files" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "file_key" } }, { "kind": "Field", "name": { "kind": "Name", "value": "display_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_limit" } }, { "kind": "Field", "name": { "kind": "Name", "value": "download_expires_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "length_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "width_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "height_cm" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variants" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sku" } }, { "kind": "Field", "name": { "kind": "Name", "value": "attributes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "images" } }, { "kind": "Field", "name": { "kind": "Name", "value": "weight_kg" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_active" } }, { "kind": "Field", "name": { "kind": "Name", "value": "inventory" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "variant_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reserved" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_point" } }, { "kind": "Field", "name": { "kind": "Name", "value": "reorder_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "track_quantity" } }, { "kind": "Field", "name": { "kind": "Name", "value": "allow_backorder" } }, { "kind": "Field", "name": { "kind": "Name", "value": "available" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_in_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "is_low_stock" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collections" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "business_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "description" } }, { "kind": "Field", "name": { "kind": "Name", "value": "image_url" } }, { "kind": "Field", "name": { "kind": "Name", "value": "collection_type" } }, { "kind": "Field", "name": { "kind": "Name", "value": "rules" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "sort_order" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updated_at" } }] } }] } }] };
|
|
964
|
+
var GetStorefrontWishlistDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GetStorefrontWishlist" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "storefront_wishlist" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "page" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "page" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "pageSize" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "pageSize" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "items" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "notes" } }, { "kind": "Field", "name": { "kind": "Name", "value": "created_at" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_name" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_slug" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_price" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currency" } }, { "kind": "Field", "name": { "kind": "Name", "value": "product_image" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "total" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page" } }, { "kind": "Field", "name": { "kind": "Name", "value": "page_size" } }, { "kind": "Field", "name": { "kind": "Name", "value": "total_pages" } }] } }] } }] };
|
|
965
|
+
var CheckInStorefrontWishlistDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "CheckInStorefrontWishlist" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "productId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "check_in_storefront_wishlist" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "productId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "productId" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "in_wishlist" } }] } }] } }] };
|
|
966
|
+
|
|
967
|
+
// src/services/product.service.ts
|
|
968
|
+
function mapProductType(raw) {
|
|
969
|
+
switch (raw) {
|
|
970
|
+
case "PHYSICAL":
|
|
971
|
+
return "physical" /* PHYSICAL */;
|
|
972
|
+
case "DIGITAL":
|
|
973
|
+
return "digital" /* DIGITAL */;
|
|
974
|
+
case "SERVICE":
|
|
975
|
+
return "service" /* SERVICE */;
|
|
976
|
+
case "BESPOKE":
|
|
977
|
+
return "bespoke" /* BESPOKE */;
|
|
978
|
+
default: {
|
|
979
|
+
const _exhaustive = raw;
|
|
980
|
+
throw new Error(`Unhandled GraphQL ProductType member: ${_exhaustive}`);
|
|
1369
981
|
}
|
|
1370
982
|
}
|
|
1371
|
-
|
|
983
|
+
}
|
|
984
|
+
function mapCustomFieldType(raw) {
|
|
985
|
+
if (raw === "text" || raw === "choice") return raw;
|
|
986
|
+
throw new Error(`Unrecognised custom field field_type from backend: "${raw}"`);
|
|
987
|
+
}
|
|
988
|
+
function mapProduct(raw) {
|
|
989
|
+
return {
|
|
990
|
+
...raw,
|
|
991
|
+
product_type: mapProductType(raw.product_type),
|
|
992
|
+
custom_fields: raw.custom_fields.map((f) => ({
|
|
993
|
+
...f,
|
|
994
|
+
unit: f.unit ?? void 0,
|
|
995
|
+
field_type: mapCustomFieldType(f.field_type)
|
|
996
|
+
})),
|
|
997
|
+
description: raw.description ?? void 0,
|
|
998
|
+
brand: raw.brand ?? void 0,
|
|
999
|
+
is_physical: raw.is_physical ?? void 0,
|
|
1000
|
+
sale_price: raw.sale_price ?? void 0,
|
|
1001
|
+
sale_start: raw.sale_start ?? void 0,
|
|
1002
|
+
sale_end: raw.sale_end ?? void 0,
|
|
1003
|
+
source_channel_ref_id: raw.source_channel_ref_id ?? void 0,
|
|
1004
|
+
download_limit: raw.download_limit ?? void 0,
|
|
1005
|
+
download_expires_at: raw.download_expires_at ?? void 0,
|
|
1006
|
+
service_type: raw.service_type ?? void 0,
|
|
1007
|
+
service_duration_minutes: raw.service_duration_minutes ?? void 0,
|
|
1008
|
+
service_location_type: raw.service_location_type ?? void 0,
|
|
1009
|
+
service_coverage_radius_km: raw.service_coverage_radius_km ?? void 0,
|
|
1010
|
+
service_max_capacity_per_slot: raw.service_max_capacity_per_slot ?? void 0,
|
|
1011
|
+
service_recurring_interval: raw.service_recurring_interval ?? void 0,
|
|
1012
|
+
length_cm: raw.length_cm ?? void 0,
|
|
1013
|
+
width_cm: raw.width_cm ?? void 0,
|
|
1014
|
+
height_cm: raw.height_cm ?? void 0,
|
|
1015
|
+
average_rating: raw.average_rating ?? void 0,
|
|
1016
|
+
created_at: raw.created_at,
|
|
1017
|
+
updated_at: raw.updated_at,
|
|
1018
|
+
variants: raw.variants.map((v) => ({
|
|
1019
|
+
...v,
|
|
1020
|
+
sku: v.sku ?? void 0,
|
|
1021
|
+
attributes: v.attributes ? JSON.parse(v.attributes) : {},
|
|
1022
|
+
price: v.price ?? void 0,
|
|
1023
|
+
weight_kg: v.weight_kg ?? void 0,
|
|
1024
|
+
inventory: v.inventory ? {
|
|
1025
|
+
...v.inventory,
|
|
1026
|
+
variant_id: v.inventory.variant_id ?? void 0,
|
|
1027
|
+
updated_at: v.inventory.updated_at
|
|
1028
|
+
} : void 0,
|
|
1029
|
+
created_at: v.created_at,
|
|
1030
|
+
updated_at: v.updated_at
|
|
1031
|
+
})),
|
|
1032
|
+
collections: raw.collections.map((c) => ({
|
|
1033
|
+
...c,
|
|
1034
|
+
business_id: c.business_id ?? void 0,
|
|
1035
|
+
description: c.description ?? void 0,
|
|
1036
|
+
image_url: c.image_url ?? void 0,
|
|
1037
|
+
rules: c.rules ?? void 0,
|
|
1038
|
+
created_at: c.created_at,
|
|
1039
|
+
updated_at: c.updated_at
|
|
1040
|
+
}))
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
function mapProductConnection(connection) {
|
|
1044
|
+
return { ...connection, items: connection.items.map(mapProduct) };
|
|
1045
|
+
}
|
|
1372
1046
|
async function getStorefrontProducts(config, params) {
|
|
1373
1047
|
const client = createGraphQLClient(config);
|
|
1374
|
-
const
|
|
1048
|
+
const data = await client.request(GetStorefrontProductsDocument, {
|
|
1375
1049
|
page: params?.page || 1,
|
|
1376
1050
|
pageSize: params?.pageSize || 20,
|
|
1377
1051
|
collectionSlug: params?.collectionSlug,
|
|
1378
|
-
search: params?.search
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
return data.storefront_products;
|
|
1052
|
+
search: params?.search,
|
|
1053
|
+
productType: params?.productType
|
|
1054
|
+
});
|
|
1055
|
+
return mapProductConnection(data.storefront_products);
|
|
1382
1056
|
}
|
|
1383
1057
|
async function getStorefrontProductBySlug(config, slug) {
|
|
1384
1058
|
const client = createGraphQLClient(config);
|
|
1385
|
-
const data = await client.request(
|
|
1386
|
-
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
const variables = {
|
|
1391
|
-
page: params?.page || 1,
|
|
1392
|
-
pageSize: params?.pageSize || 4
|
|
1393
|
-
};
|
|
1394
|
-
const data = await client.request(GET_STOREFRONT_LATEST, variables);
|
|
1395
|
-
return data.storefront_latest;
|
|
1059
|
+
const data = await client.request(GetStorefrontProductBySlugDocument, { slug });
|
|
1060
|
+
if (!data.storefront_product_by_slug) {
|
|
1061
|
+
throw new Error(`Product not found: ${slug}`);
|
|
1062
|
+
}
|
|
1063
|
+
return mapProduct(data.storefront_product_by_slug);
|
|
1396
1064
|
}
|
|
1397
1065
|
async function getPopularProducts(config, params) {
|
|
1398
1066
|
const client = createGraphQLClient(config);
|
|
1399
|
-
const
|
|
1067
|
+
const data = await client.request(GetStorefrontPopularDocument, {
|
|
1400
1068
|
page: params?.page || 1,
|
|
1401
1069
|
pageSize: params?.pageSize || 4
|
|
1402
|
-
};
|
|
1403
|
-
|
|
1404
|
-
return data.storefront_popular;
|
|
1070
|
+
});
|
|
1071
|
+
return mapProductConnection(data.storefront_popular);
|
|
1405
1072
|
}
|
|
1406
1073
|
async function getFeaturedProducts(config, params) {
|
|
1407
1074
|
const client = createGraphQLClient(config);
|
|
1408
|
-
const
|
|
1075
|
+
const data = await client.request(GetStorefrontFeaturedDocument, {
|
|
1409
1076
|
page: params?.page || 1,
|
|
1410
1077
|
pageSize: params?.pageSize || 4
|
|
1411
|
-
};
|
|
1412
|
-
|
|
1413
|
-
return data.storefront_featured;
|
|
1078
|
+
});
|
|
1079
|
+
return mapProductConnection(data.storefront_featured);
|
|
1414
1080
|
}
|
|
1415
1081
|
async function getNewProducts(config, params) {
|
|
1416
1082
|
const client = createGraphQLClient(config);
|
|
1417
|
-
const
|
|
1083
|
+
const data = await client.request(GetStorefrontNewDocument, {
|
|
1418
1084
|
page: params?.page || 1,
|
|
1419
1085
|
pageSize: params?.pageSize || 4
|
|
1420
|
-
};
|
|
1421
|
-
|
|
1422
|
-
return data.storefront_new;
|
|
1086
|
+
});
|
|
1087
|
+
return mapProductConnection(data.storefront_new);
|
|
1423
1088
|
}
|
|
1424
1089
|
async function getOnSaleProducts(config, params) {
|
|
1425
1090
|
const client = createGraphQLClient(config);
|
|
1426
|
-
const
|
|
1427
|
-
page: params?.page || 1,
|
|
1428
|
-
pageSize: params?.pageSize || 4
|
|
1429
|
-
};
|
|
1430
|
-
const data = await client.request(GET_STOREFRONT_ON_SALE, variables);
|
|
1431
|
-
return data.storefront_on_sale;
|
|
1432
|
-
}
|
|
1433
|
-
async function getLowStockProducts(config, params) {
|
|
1434
|
-
const client = createGraphQLClient(config);
|
|
1435
|
-
const variables = {
|
|
1091
|
+
const data = await client.request(GetStorefrontOnSaleDocument, {
|
|
1436
1092
|
page: params?.page || 1,
|
|
1437
1093
|
pageSize: params?.pageSize || 4
|
|
1438
|
-
};
|
|
1439
|
-
|
|
1440
|
-
return data.storefront_low_stock;
|
|
1094
|
+
});
|
|
1095
|
+
return mapProductConnection(data.storefront_on_sale);
|
|
1441
1096
|
}
|
|
1442
1097
|
async function getRecommendedProducts(config, params) {
|
|
1443
1098
|
const client = createGraphQLClient(config);
|
|
1444
|
-
const
|
|
1099
|
+
const data = await client.request(GetStorefrontRecommendedDocument, {
|
|
1445
1100
|
page: params?.page || 1,
|
|
1446
1101
|
pageSize: params?.pageSize || 4,
|
|
1447
1102
|
excludeProductId: params?.excludeProductId
|
|
1448
|
-
};
|
|
1449
|
-
|
|
1450
|
-
return data.storefront_recommended;
|
|
1103
|
+
});
|
|
1104
|
+
return mapProductConnection(data.storefront_recommended);
|
|
1451
1105
|
}
|
|
1452
1106
|
|
|
1453
1107
|
// src/services/collection.service.ts
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
description
|
|
1464
|
-
image
|
|
1465
|
-
collection_type
|
|
1466
|
-
rules
|
|
1467
|
-
status
|
|
1468
|
-
sort_order
|
|
1469
|
-
created_at
|
|
1470
|
-
updated_at
|
|
1471
|
-
}
|
|
1472
|
-
total
|
|
1473
|
-
page
|
|
1474
|
-
page_size
|
|
1475
|
-
total_pages
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
`;
|
|
1479
|
-
var GET_STOREFRONT_COLLECTION_BY_SLUG = `
|
|
1480
|
-
query GetStorefrontCollectionBySlug($slug: String!) {
|
|
1481
|
-
storefront_collection_by_slug(slug: $slug) {
|
|
1482
|
-
id
|
|
1483
|
-
business_id
|
|
1484
|
-
name
|
|
1485
|
-
slug
|
|
1486
|
-
description
|
|
1487
|
-
image
|
|
1488
|
-
collection_type
|
|
1489
|
-
rules
|
|
1490
|
-
status
|
|
1491
|
-
sort_order
|
|
1492
|
-
created_at
|
|
1493
|
-
updated_at
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
`;
|
|
1497
|
-
function createGraphQLClient2(config) {
|
|
1498
|
-
const headers = {
|
|
1499
|
-
"Content-Type": "application/json",
|
|
1500
|
-
"Accept": "application/json",
|
|
1501
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1502
|
-
"X-Business-ID": config.businessId
|
|
1108
|
+
function mapCollection(raw) {
|
|
1109
|
+
return {
|
|
1110
|
+
...raw,
|
|
1111
|
+
business_id: raw.business_id ?? void 0,
|
|
1112
|
+
description: raw.description ?? void 0,
|
|
1113
|
+
image_url: raw.image_url ?? void 0,
|
|
1114
|
+
rules: raw.rules ?? void 0,
|
|
1115
|
+
created_at: raw.created_at,
|
|
1116
|
+
updated_at: raw.updated_at
|
|
1503
1117
|
};
|
|
1504
|
-
return new GraphQLClient2(`${config.backendUrls.store}/graphql`, { headers });
|
|
1505
1118
|
}
|
|
1506
1119
|
async function getStorefrontCollections(config, params) {
|
|
1507
|
-
const client =
|
|
1508
|
-
const
|
|
1120
|
+
const client = createGraphQLClient(config);
|
|
1121
|
+
const data = await client.request(GetStorefrontCollectionsDocument, {
|
|
1509
1122
|
page: params?.page || 1,
|
|
1510
1123
|
pageSize: params?.pageSize || 20
|
|
1511
|
-
};
|
|
1512
|
-
|
|
1513
|
-
return data.storefront_collections;
|
|
1124
|
+
});
|
|
1125
|
+
return { ...data.storefront_collections, items: data.storefront_collections.items.map(mapCollection) };
|
|
1514
1126
|
}
|
|
1515
1127
|
async function getStorefrontCollectionBySlug(config, slug) {
|
|
1516
|
-
const client =
|
|
1517
|
-
const data = await client.request(
|
|
1518
|
-
|
|
1128
|
+
const client = createGraphQLClient(config);
|
|
1129
|
+
const data = await client.request(GetStorefrontCollectionBySlugDocument, { slug });
|
|
1130
|
+
if (!data.storefront_collection_by_slug) {
|
|
1131
|
+
throw new Error(`Collection not found: ${slug}`);
|
|
1132
|
+
}
|
|
1133
|
+
return mapCollection(data.storefront_collection_by_slug);
|
|
1519
1134
|
}
|
|
1520
1135
|
|
|
1521
1136
|
// src/services/wishlist.service.ts
|
|
1522
|
-
import { GraphQLClient as GraphQLClient3 } from "graphql-request";
|
|
1523
|
-
var GET_STOREFRONT_WISHLIST = `
|
|
1524
|
-
query GetStorefrontWishlist($page: Int!, $pageSize: Int!) {
|
|
1525
|
-
storefront_wishlist(page: $page, pageSize: $pageSize) {
|
|
1526
|
-
items {
|
|
1527
|
-
id
|
|
1528
|
-
product_id
|
|
1529
|
-
notes
|
|
1530
|
-
created_at
|
|
1531
|
-
product_name
|
|
1532
|
-
product_slug
|
|
1533
|
-
product_price
|
|
1534
|
-
currency
|
|
1535
|
-
product_image
|
|
1536
|
-
}
|
|
1537
|
-
total
|
|
1538
|
-
page
|
|
1539
|
-
page_size
|
|
1540
|
-
total_pages
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
`;
|
|
1544
|
-
var CHECK_IN_STOREFRONT_WISHLIST = `
|
|
1545
|
-
query CheckInStorefrontWishlist($productId: String!) {
|
|
1546
|
-
check_in_storefront_wishlist(productId: $productId) {
|
|
1547
|
-
in_wishlist
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
`;
|
|
1551
|
-
function createGraphQLClient3(config, accessToken) {
|
|
1552
|
-
const headers = {
|
|
1553
|
-
"Content-Type": "application/json",
|
|
1554
|
-
"Accept": "application/json",
|
|
1555
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1556
|
-
"X-Business-ID": config.businessId
|
|
1557
|
-
};
|
|
1558
|
-
if (accessToken) {
|
|
1559
|
-
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
1560
|
-
}
|
|
1561
|
-
return new GraphQLClient3(`${config.backendUrls.store}/graphql`, { headers });
|
|
1562
|
-
}
|
|
1563
1137
|
async function getWishlist(config, accessToken, params) {
|
|
1564
|
-
const client =
|
|
1565
|
-
const
|
|
1138
|
+
const client = createGraphQLClient(config, accessToken);
|
|
1139
|
+
const data = await client.request(GetStorefrontWishlistDocument, {
|
|
1566
1140
|
page: params?.page || 1,
|
|
1567
1141
|
pageSize: params?.pageSize || 20
|
|
1142
|
+
});
|
|
1143
|
+
return {
|
|
1144
|
+
...data.storefront_wishlist,
|
|
1145
|
+
items: data.storefront_wishlist.items.map((item) => ({
|
|
1146
|
+
...item,
|
|
1147
|
+
created_at: item.created_at,
|
|
1148
|
+
notes: item.notes ?? void 0,
|
|
1149
|
+
product_name: item.product_name ?? void 0,
|
|
1150
|
+
product_slug: item.product_slug ?? void 0,
|
|
1151
|
+
product_price: item.product_price ?? void 0,
|
|
1152
|
+
currency: item.currency ?? void 0,
|
|
1153
|
+
product_image: item.product_image ?? void 0
|
|
1154
|
+
}))
|
|
1568
1155
|
};
|
|
1569
|
-
const data = await client.request(GET_STOREFRONT_WISHLIST, variables);
|
|
1570
|
-
return data.storefront_wishlist;
|
|
1571
1156
|
}
|
|
1572
1157
|
async function checkInWishlist(config, accessToken, productId) {
|
|
1573
|
-
const client =
|
|
1574
|
-
const data = await client.request(
|
|
1158
|
+
const client = createGraphQLClient(config, accessToken);
|
|
1159
|
+
const data = await client.request(CheckInStorefrontWishlistDocument, { productId });
|
|
1575
1160
|
return data.check_in_storefront_wishlist;
|
|
1576
1161
|
}
|
|
1577
1162
|
async function addToWishlist(config, accessToken, productId, notes) {
|
|
1578
|
-
|
|
1163
|
+
return apiRequest(`${config.backendUrls.store}/wishlist/`, {
|
|
1579
1164
|
method: "POST",
|
|
1580
|
-
headers: {
|
|
1581
|
-
"Content-Type": "application/json",
|
|
1582
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
1583
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1584
|
-
"X-Business-ID": config.businessId
|
|
1585
|
-
},
|
|
1165
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1586
1166
|
body: JSON.stringify({
|
|
1587
1167
|
product_id: productId,
|
|
1588
1168
|
notes: notes || void 0
|
|
1589
|
-
})
|
|
1169
|
+
}),
|
|
1170
|
+
fallbackErrorMessage: "Failed to add to wishlist"
|
|
1590
1171
|
});
|
|
1591
|
-
if (!response.ok) throw new Error("Failed to add to wishlist");
|
|
1592
|
-
return response.json();
|
|
1593
1172
|
}
|
|
1594
1173
|
async function removeFromWishlist(config, accessToken, itemId) {
|
|
1595
|
-
|
|
1174
|
+
await apiRequest(`${config.backendUrls.store}/wishlist/${itemId}`, {
|
|
1596
1175
|
method: "DELETE",
|
|
1597
|
-
headers:
|
|
1598
|
-
|
|
1599
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1600
|
-
"X-Business-ID": config.businessId
|
|
1601
|
-
}
|
|
1176
|
+
headers: authHeaders(config, accessToken),
|
|
1177
|
+
fallbackErrorMessage: "Failed to remove from wishlist"
|
|
1602
1178
|
});
|
|
1603
|
-
if (!response.ok) throw new Error("Failed to remove from wishlist");
|
|
1604
1179
|
}
|
|
1605
1180
|
async function removeProductFromWishlist(config, accessToken, productId) {
|
|
1606
|
-
|
|
1181
|
+
await apiRequest(`${config.backendUrls.store}/wishlist/product/${productId}`, {
|
|
1607
1182
|
method: "DELETE",
|
|
1608
|
-
headers:
|
|
1609
|
-
|
|
1610
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1611
|
-
"X-Business-ID": config.businessId
|
|
1612
|
-
}
|
|
1183
|
+
headers: authHeaders(config, accessToken),
|
|
1184
|
+
fallbackErrorMessage: "Failed to remove product from wishlist"
|
|
1613
1185
|
});
|
|
1614
|
-
if (!response.ok) throw new Error("Failed to remove product from wishlist");
|
|
1615
1186
|
}
|
|
1616
1187
|
|
|
1617
1188
|
// src/services/payment.service.ts
|
|
1189
|
+
function isValidUUID(str) {
|
|
1190
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str);
|
|
1191
|
+
}
|
|
1192
|
+
async function getAvailablePaymentMethods(config, currency, countryCode) {
|
|
1193
|
+
const params = {};
|
|
1194
|
+
if (currency) params.currency = currency;
|
|
1195
|
+
if (countryCode) params.country_code = countryCode;
|
|
1196
|
+
const query = new URLSearchParams(params).toString();
|
|
1197
|
+
return apiRequest(`${config.backendUrls.payment}/payments/storefront/methods${query ? `?${query}` : ""}`, {
|
|
1198
|
+
headers: storefrontHeaders(config),
|
|
1199
|
+
fallbackErrorMessage: "Failed to fetch available payment methods"
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1618
1202
|
async function createDedicatedAccount(config, accessToken, request) {
|
|
1619
|
-
const
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1203
|
+
const origin = request.storefront_origin || (typeof window !== "undefined" ? window.location.origin : "");
|
|
1204
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
1205
|
+
if (accessToken) {
|
|
1206
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
1207
|
+
}
|
|
1208
|
+
if (origin) {
|
|
1209
|
+
headers["Origin"] = origin;
|
|
1210
|
+
}
|
|
1211
|
+
return apiRequest(`${config.backendUrls.payment}/payments/storefront/dedicated-account`, {
|
|
1624
1212
|
method: "POST",
|
|
1625
|
-
headers
|
|
1626
|
-
"Content-Type": "application/json",
|
|
1627
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
1628
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1629
|
-
"X-Business-ID": config.businessId
|
|
1630
|
-
},
|
|
1213
|
+
headers,
|
|
1631
1214
|
body: JSON.stringify({
|
|
1632
1215
|
order_id: request.order_id && isValidUUID(request.order_id) ? request.order_id : void 0,
|
|
1633
1216
|
amount: request.amount,
|
|
1634
1217
|
customer_email: request.customer_email,
|
|
1635
1218
|
customer_name: request.customer_name,
|
|
1636
1219
|
currency: request.currency,
|
|
1220
|
+
gateway: request.gateway,
|
|
1637
1221
|
idempotency_key: request.idempotency_key
|
|
1638
|
-
})
|
|
1222
|
+
}),
|
|
1223
|
+
fallbackErrorMessage: "Failed to create dedicated account"
|
|
1639
1224
|
});
|
|
1640
|
-
if (!response.ok) throw new Error("Failed to create dedicated account");
|
|
1641
|
-
const data = await response.json();
|
|
1642
|
-
return data;
|
|
1643
1225
|
}
|
|
1644
1226
|
async function initiatePayment(config, accessToken, request) {
|
|
1645
|
-
const isValidUUID = (str) => {
|
|
1646
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1647
|
-
return uuidRegex.test(str);
|
|
1648
|
-
};
|
|
1649
1227
|
const validOrderId = request.order_id && isValidUUID(request.order_id) ? request.order_id : void 0;
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1228
|
+
const origin = request.storefront_origin || (typeof window !== "undefined" ? window.location.origin : "");
|
|
1229
|
+
const headers = { ...JSON_HEADERS, ...storefrontHeaders(config) };
|
|
1230
|
+
if (accessToken) {
|
|
1231
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
1232
|
+
}
|
|
1233
|
+
if (origin) {
|
|
1234
|
+
headers["Origin"] = origin;
|
|
1235
|
+
}
|
|
1236
|
+
const data = await apiRequest(
|
|
1237
|
+
`${config.backendUrls.payment}/payments/storefront/initiate`,
|
|
1238
|
+
{
|
|
1239
|
+
method: "POST",
|
|
1240
|
+
headers,
|
|
1241
|
+
body: JSON.stringify({
|
|
1242
|
+
amount: request.amount,
|
|
1243
|
+
currency: request.currency,
|
|
1244
|
+
// Same real backend default as getAvailablePaymentMethods above
|
|
1245
|
+
// (huma's own `default:"NG"` on this field) — omit rather than
|
|
1246
|
+
// hardcode a client-side copy of it.
|
|
1247
|
+
country_code: request.country_code,
|
|
1248
|
+
gateway: request.gateway,
|
|
1666
1249
|
order_id: validOrderId,
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1250
|
+
quote_id: request.quote_id,
|
|
1251
|
+
metadata_json: {
|
|
1252
|
+
customer_email: request.customer_email,
|
|
1253
|
+
customer_name: request.customer_name ?? "",
|
|
1254
|
+
order_id: validOrderId,
|
|
1255
|
+
...request.metadata ?? {}
|
|
1256
|
+
},
|
|
1257
|
+
idempotency_key: request.idempotency_key
|
|
1258
|
+
}),
|
|
1259
|
+
fallbackErrorMessage: "Failed to initiate payment"
|
|
1260
|
+
}
|
|
1261
|
+
);
|
|
1674
1262
|
return {
|
|
1675
1263
|
id: data.id,
|
|
1676
1264
|
gateway_ref: data.gateway_ref,
|
|
@@ -1679,311 +1267,241 @@ async function initiatePayment(config, accessToken, request) {
|
|
|
1679
1267
|
checkout_url: data.metadata_json?.checkout_url ?? ""
|
|
1680
1268
|
};
|
|
1681
1269
|
}
|
|
1682
|
-
async function
|
|
1683
|
-
|
|
1684
|
-
method: "POST",
|
|
1685
|
-
headers: {
|
|
1686
|
-
"Content-Type": "application/json",
|
|
1687
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1688
|
-
"X-Business-ID": config.businessId
|
|
1689
|
-
},
|
|
1690
|
-
body: JSON.stringify({ amount })
|
|
1691
|
-
});
|
|
1692
|
-
if (!response.ok) throw new Error("Failed to request quote");
|
|
1693
|
-
const data = await response.json();
|
|
1694
|
-
return data;
|
|
1695
|
-
}
|
|
1696
|
-
async function verifyTransaction(configOrReference, reference) {
|
|
1697
|
-
if (typeof configOrReference === "string") {
|
|
1698
|
-
const ref2 = configOrReference;
|
|
1699
|
-
const response2 = await fetch(`/api/payments/verify/${ref2}`, {
|
|
1700
|
-
method: "POST",
|
|
1701
|
-
headers: { "Content-Type": "application/json" }
|
|
1702
|
-
});
|
|
1703
|
-
if (!response2.ok) throw new Error("Failed to verify transaction");
|
|
1704
|
-
return response2.json();
|
|
1705
|
-
}
|
|
1706
|
-
const config = configOrReference;
|
|
1707
|
-
const ref = reference || "";
|
|
1708
|
-
const response = await fetch(`${config.backendUrls.payment}/payments/verify/${ref}`, {
|
|
1270
|
+
async function verifyTransaction(config, reference) {
|
|
1271
|
+
return apiRequest(`${config.backendUrls.payment}/payments/verify/${reference}`, {
|
|
1709
1272
|
method: "POST",
|
|
1710
|
-
headers: {
|
|
1711
|
-
|
|
1712
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1713
|
-
"X-Business-ID": config.businessId
|
|
1714
|
-
}
|
|
1273
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1274
|
+
fallbackErrorMessage: "Failed to verify transaction"
|
|
1715
1275
|
});
|
|
1716
|
-
if (!response.ok) throw new Error("Failed to verify transaction");
|
|
1717
|
-
const data = await response.json();
|
|
1718
|
-
return data;
|
|
1719
1276
|
}
|
|
1720
1277
|
async function getTransactionStatus(config, transactionId) {
|
|
1721
|
-
|
|
1722
|
-
headers:
|
|
1723
|
-
|
|
1724
|
-
|
|
1278
|
+
return apiRequest(`${config.backendUrls.payment}/payments/transactions/${transactionId}`, {
|
|
1279
|
+
headers: storefrontHeaders(config),
|
|
1280
|
+
fallbackErrorMessage: "Failed to get transaction status"
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
async function getWalletBalance(config, accessToken) {
|
|
1284
|
+
return apiRequest(`${config.backendUrls.payment}/wallet/balance`, {
|
|
1285
|
+
headers: authHeaders(config, accessToken),
|
|
1286
|
+
fallbackErrorMessage: "Failed to fetch wallet balance"
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
async function getWalletLedger(config, accessToken, params) {
|
|
1290
|
+
const page = params?.page ?? 1;
|
|
1291
|
+
const pageSize = params?.page_size ?? 20;
|
|
1292
|
+
return apiRequest(
|
|
1293
|
+
`${config.backendUrls.payment}/wallet/ledger?page=${page}&page_size=${pageSize}`,
|
|
1294
|
+
{
|
|
1295
|
+
headers: authHeaders(config, accessToken),
|
|
1296
|
+
fallbackErrorMessage: "Failed to fetch wallet ledger"
|
|
1725
1297
|
}
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
async function claimWalletCredit(config, accessToken, claimToken) {
|
|
1301
|
+
return apiRequest(`${config.backendUrls.payment}/wallet/claim`, {
|
|
1302
|
+
method: "POST",
|
|
1303
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1304
|
+
body: JSON.stringify({ claim_token: claimToken }),
|
|
1305
|
+
fallbackErrorMessage: "Failed to claim wallet credit"
|
|
1726
1306
|
});
|
|
1727
|
-
if (!response.ok) throw new Error("Failed to get transaction status");
|
|
1728
|
-
const data = await response.json();
|
|
1729
|
-
return data;
|
|
1730
1307
|
}
|
|
1731
1308
|
var paymentService = {
|
|
1309
|
+
getAvailablePaymentMethods,
|
|
1732
1310
|
createDedicatedAccount,
|
|
1733
1311
|
initiatePayment,
|
|
1734
|
-
requestQuote,
|
|
1735
1312
|
verifyTransaction,
|
|
1736
|
-
getTransactionStatus
|
|
1313
|
+
getTransactionStatus,
|
|
1314
|
+
getWalletBalance,
|
|
1315
|
+
getWalletLedger,
|
|
1316
|
+
claimWalletCredit
|
|
1737
1317
|
};
|
|
1738
1318
|
|
|
1739
|
-
// src/services/
|
|
1740
|
-
async function
|
|
1741
|
-
|
|
1319
|
+
// src/services/logistics.service.ts
|
|
1320
|
+
async function getShippingRates(config, payload) {
|
|
1321
|
+
return apiRequest(`${config.backendUrls.store}/logistics/shipping/rates`, {
|
|
1742
1322
|
method: "POST",
|
|
1743
|
-
headers: {
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1747
|
-
"X-Business-ID": config.businessId
|
|
1748
|
-
},
|
|
1749
|
-
body: JSON.stringify(payload)
|
|
1750
|
-
});
|
|
1751
|
-
if (!response.ok) throw new Error("Failed to create consultation");
|
|
1752
|
-
return response.json();
|
|
1753
|
-
}
|
|
1754
|
-
async function getConsultations(config, accessToken) {
|
|
1755
|
-
const response = await fetch(`${config.backendUrls.store}/social/consultations/`, {
|
|
1756
|
-
headers: {
|
|
1757
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
1758
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1759
|
-
"X-Business-ID": config.businessId
|
|
1760
|
-
}
|
|
1323
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1324
|
+
body: JSON.stringify(payload),
|
|
1325
|
+
fallbackErrorMessage: "Failed to get shipping rates"
|
|
1761
1326
|
});
|
|
1762
|
-
if (!response.ok) throw new Error("Failed to get consultations");
|
|
1763
|
-
return response.json();
|
|
1764
1327
|
}
|
|
1765
|
-
async function
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
}
|
|
1328
|
+
async function validateShippingAddress(config, payload) {
|
|
1329
|
+
return apiRequest(`${config.backendUrls.store}/logistics/shipping-address/validate`, {
|
|
1330
|
+
method: "POST",
|
|
1331
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1332
|
+
body: JSON.stringify(payload),
|
|
1333
|
+
fallbackErrorMessage: "Failed to validate shipping address"
|
|
1772
1334
|
});
|
|
1773
|
-
if (!response.ok) throw new Error("Failed to get consultation");
|
|
1774
|
-
return response.json();
|
|
1775
1335
|
}
|
|
1776
|
-
async function
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1336
|
+
async function fetchLocationList(config, path, coords, fallbackErrorMessage) {
|
|
1337
|
+
const params = new URLSearchParams();
|
|
1338
|
+
if (coords) {
|
|
1339
|
+
params.set("latitude", String(coords.latitude));
|
|
1340
|
+
params.set("longitude", String(coords.longitude));
|
|
1341
|
+
}
|
|
1342
|
+
const qs = params.toString();
|
|
1343
|
+
return apiRequest(`${config.backendUrls.store}/logistics/${path}${qs ? `?${qs}` : ""}`, {
|
|
1344
|
+
headers: storefrontHeaders(config),
|
|
1345
|
+
fallbackErrorMessage
|
|
1786
1346
|
});
|
|
1787
1347
|
}
|
|
1788
|
-
async function
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
},
|
|
1797
|
-
body: JSON.stringify(payload)
|
|
1798
|
-
});
|
|
1799
|
-
if (!response.ok) throw new Error("Failed to accept quote");
|
|
1800
|
-
return response.json();
|
|
1801
|
-
}
|
|
1802
|
-
async function rejectQuote(config, accessToken, id, reason) {
|
|
1803
|
-
const response = await fetch(`${config.backendUrls.store}/social/consultations/${id}/reject-quote`, {
|
|
1804
|
-
method: "POST",
|
|
1805
|
-
headers: {
|
|
1806
|
-
"Content-Type": "application/json",
|
|
1807
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
1808
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1809
|
-
"X-Business-ID": config.businessId
|
|
1810
|
-
},
|
|
1811
|
-
body: JSON.stringify({ reason })
|
|
1812
|
-
});
|
|
1813
|
-
if (!response.ok) throw new Error("Failed to reject quote");
|
|
1814
|
-
return response.json();
|
|
1815
|
-
}
|
|
1816
|
-
var consultationService = {
|
|
1817
|
-
createConsultation,
|
|
1818
|
-
getConsultations,
|
|
1819
|
-
getConsultation,
|
|
1820
|
-
sendMessage,
|
|
1821
|
-
acceptQuote,
|
|
1822
|
-
rejectQuote
|
|
1823
|
-
};
|
|
1824
|
-
|
|
1825
|
-
// src/services/logistics.service.ts
|
|
1826
|
-
async function getShippingRates(config, payload) {
|
|
1827
|
-
const response = await fetch(`${config.backendUrls.store}/logistics/shipping/rates`, {
|
|
1348
|
+
async function listPickupLocations(config, coords) {
|
|
1349
|
+
return fetchLocationList(config, "pickup-locations", coords, "Failed to list pickup locations");
|
|
1350
|
+
}
|
|
1351
|
+
async function listBusinessLocations(config, coords) {
|
|
1352
|
+
return fetchLocationList(config, "locations", coords, "Failed to list business locations");
|
|
1353
|
+
}
|
|
1354
|
+
async function reverseGeocode(config, payload) {
|
|
1355
|
+
return apiRequest(`${config.backendUrls.store}/logistics/reverse-geocode`, {
|
|
1828
1356
|
method: "POST",
|
|
1829
|
-
headers: {
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
"X-Business-ID": config.businessId
|
|
1833
|
-
},
|
|
1834
|
-
body: JSON.stringify(payload)
|
|
1835
|
-
});
|
|
1836
|
-
if (!response.ok) throw new Error("Failed to get shipping rates");
|
|
1837
|
-
return response.json();
|
|
1838
|
-
}
|
|
1839
|
-
async function getSellerShippingAddress(config) {
|
|
1840
|
-
const response = await fetch(`${config.backendUrls.store}/logistics/shipping-address`, {
|
|
1841
|
-
headers: {
|
|
1842
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1843
|
-
"X-Business-ID": config.businessId
|
|
1844
|
-
}
|
|
1357
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1358
|
+
body: JSON.stringify(payload),
|
|
1359
|
+
fallbackErrorMessage: "Failed to reverse geocode coordinates"
|
|
1845
1360
|
});
|
|
1846
|
-
if (!response.ok) throw new Error("Failed to get seller shipping address");
|
|
1847
|
-
return response.json();
|
|
1848
1361
|
}
|
|
1849
|
-
async function
|
|
1850
|
-
|
|
1362
|
+
async function decodePlusCode(config, payload) {
|
|
1363
|
+
return apiRequest(`${config.backendUrls.store}/logistics/plus-code/decode`, {
|
|
1851
1364
|
method: "POST",
|
|
1852
|
-
headers: {
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1365
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1366
|
+
body: JSON.stringify(payload),
|
|
1367
|
+
fallbackErrorMessage: "Failed to decode Plus Code"
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
async function autocompleteAddress(config, q, country) {
|
|
1371
|
+
const params = new URLSearchParams();
|
|
1372
|
+
params.set("q", q);
|
|
1373
|
+
if (country) params.set("country", country);
|
|
1374
|
+
return apiRequest(`${config.backendUrls.store}/logistics/address/autocomplete?${params.toString()}`, {
|
|
1375
|
+
headers: storefrontHeaders(config),
|
|
1376
|
+
fallbackErrorMessage: "Failed to autocomplete address"
|
|
1858
1377
|
});
|
|
1859
|
-
if (!response.ok) throw new Error("Failed to validate shipping address");
|
|
1860
|
-
return response.json();
|
|
1861
1378
|
}
|
|
1862
1379
|
var logisticsService = {
|
|
1863
1380
|
getShippingRates,
|
|
1864
|
-
|
|
1865
|
-
|
|
1381
|
+
validateShippingAddress,
|
|
1382
|
+
listPickupLocations,
|
|
1383
|
+
listBusinessLocations,
|
|
1384
|
+
reverseGeocode,
|
|
1385
|
+
decodePlusCode,
|
|
1386
|
+
autocompleteAddress
|
|
1866
1387
|
};
|
|
1867
1388
|
|
|
1868
1389
|
// src/services/bespoke.service.ts
|
|
1869
1390
|
async function checkAvailability(config, product_id) {
|
|
1870
|
-
|
|
1871
|
-
headers:
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1391
|
+
return apiRequest(`${config.backendUrls.store}/bespoke/capacity/availability/${product_id}`, {
|
|
1392
|
+
headers: storefrontHeaders(config),
|
|
1393
|
+
fallbackErrorMessage: "Failed to check bespoke availability"
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
async function approveBespokeDeliverable(config, accessToken, orderId) {
|
|
1397
|
+
return apiRequest(`${config.backendUrls.store}/orders/${orderId}/bespoke/approve`, {
|
|
1398
|
+
method: "POST",
|
|
1399
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1400
|
+
body: JSON.stringify({}),
|
|
1401
|
+
fallbackErrorMessage: "Failed to approve deliverable"
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
async function requestBespokeRevision(config, accessToken, orderId, notes) {
|
|
1405
|
+
return apiRequest(`${config.backendUrls.store}/orders/${orderId}/bespoke/request-revision`, {
|
|
1406
|
+
method: "POST",
|
|
1407
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1408
|
+
body: JSON.stringify({ notes }),
|
|
1409
|
+
fallbackErrorMessage: "Failed to request revision"
|
|
1875
1410
|
});
|
|
1876
|
-
if (!response.ok) throw new Error("Failed to check bespoke availability");
|
|
1877
|
-
return response.json();
|
|
1878
1411
|
}
|
|
1879
1412
|
var bespokeService = {
|
|
1880
|
-
checkAvailability
|
|
1413
|
+
checkAvailability,
|
|
1414
|
+
approveBespokeDeliverable,
|
|
1415
|
+
requestBespokeRevision
|
|
1881
1416
|
};
|
|
1882
1417
|
|
|
1883
1418
|
// src/services/service-booking.service.ts
|
|
1884
|
-
async function getAvailableSlots(config,
|
|
1885
|
-
const
|
|
1886
|
-
|
|
1419
|
+
async function getAvailableSlots(config, productId, date, params) {
|
|
1420
|
+
const query = new URLSearchParams({ date });
|
|
1421
|
+
if (params?.staffId) query.set("staff_id", params.staffId);
|
|
1422
|
+
if (params?.locationId) query.set("location_id", params.locationId);
|
|
1423
|
+
if (params?.customerLatitude !== void 0) query.set("customer_latitude", String(params.customerLatitude));
|
|
1424
|
+
if (params?.customerLongitude !== void 0) query.set("customer_longitude", String(params.customerLongitude));
|
|
1425
|
+
return apiRequest(
|
|
1426
|
+
`${config.backendUrls.store}/catalog/products/${productId}/available-slots?${query.toString()}`,
|
|
1887
1427
|
{
|
|
1888
|
-
headers:
|
|
1889
|
-
|
|
1890
|
-
"X-Business-ID": config.businessId
|
|
1891
|
-
}
|
|
1428
|
+
headers: storefrontHeaders(config),
|
|
1429
|
+
fallbackErrorMessage: "Failed to get available slots"
|
|
1892
1430
|
}
|
|
1893
1431
|
);
|
|
1894
|
-
if (!response.ok) throw new Error("Failed to get available slots");
|
|
1895
|
-
return response.json();
|
|
1896
1432
|
}
|
|
1897
1433
|
async function bookAppointment(config, accessToken, payload) {
|
|
1898
|
-
|
|
1434
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/schedule`, {
|
|
1899
1435
|
method: "POST",
|
|
1900
|
-
headers: {
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
if (
|
|
1909
|
-
|
|
1910
|
-
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
headers: {
|
|
1914
|
-
"Authorization": `Bearer ${accessToken}`,
|
|
1915
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1916
|
-
"X-Business-ID": config.businessId
|
|
1917
|
-
}
|
|
1436
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1437
|
+
body: JSON.stringify(payload),
|
|
1438
|
+
fallbackErrorMessage: "Failed to book appointment"
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
async function getAppointments(config, accessToken, params) {
|
|
1442
|
+
const query = new URLSearchParams();
|
|
1443
|
+
if (params?.status) query.set("status", params.status);
|
|
1444
|
+
if (params?.page) query.set("page", String(params.page));
|
|
1445
|
+
if (params?.page_size) query.set("page_size", String(params.page_size));
|
|
1446
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/my?${query.toString()}`, {
|
|
1447
|
+
headers: authHeaders(config, accessToken),
|
|
1448
|
+
fallbackErrorMessage: "Failed to get appointments"
|
|
1918
1449
|
});
|
|
1919
|
-
if (!response.ok) throw new Error("Failed to get appointments");
|
|
1920
|
-
return response.json();
|
|
1921
1450
|
}
|
|
1922
1451
|
async function getAppointment(config, accessToken, id) {
|
|
1923
|
-
|
|
1924
|
-
headers:
|
|
1925
|
-
|
|
1926
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1927
|
-
"X-Business-ID": config.businessId
|
|
1928
|
-
}
|
|
1452
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${id}`, {
|
|
1453
|
+
headers: authHeaders(config, accessToken),
|
|
1454
|
+
fallbackErrorMessage: "Failed to get appointment"
|
|
1929
1455
|
});
|
|
1930
|
-
if (!response.ok) throw new Error("Failed to get appointment");
|
|
1931
|
-
return response.json();
|
|
1932
1456
|
}
|
|
1933
|
-
async function cancelAppointment(config, accessToken, id) {
|
|
1934
|
-
|
|
1935
|
-
method: "
|
|
1936
|
-
headers: {
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
"X-Business-ID": config.businessId
|
|
1940
|
-
}
|
|
1457
|
+
async function cancelAppointment(config, accessToken, id, payload) {
|
|
1458
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${id}/cancel`, {
|
|
1459
|
+
method: "POST",
|
|
1460
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1461
|
+
body: JSON.stringify(payload ?? {}),
|
|
1462
|
+
fallbackErrorMessage: "Failed to cancel appointment"
|
|
1941
1463
|
});
|
|
1942
1464
|
}
|
|
1943
|
-
async function
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
}
|
|
1465
|
+
async function rescheduleAppointment(config, accessToken, id, payload) {
|
|
1466
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${id}/reschedule`, {
|
|
1467
|
+
method: "POST",
|
|
1468
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1469
|
+
body: JSON.stringify(payload),
|
|
1470
|
+
fallbackErrorMessage: "Failed to reschedule appointment"
|
|
1950
1471
|
});
|
|
1951
|
-
if (!response.ok) throw new Error("Failed to get deliverables");
|
|
1952
|
-
return response.json();
|
|
1953
1472
|
}
|
|
1954
|
-
async function
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
{
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1473
|
+
async function disputeAppointment(config, accessToken, id, payload) {
|
|
1474
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${id}/dispute`, {
|
|
1475
|
+
method: "POST",
|
|
1476
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1477
|
+
body: JSON.stringify(payload),
|
|
1478
|
+
fallbackErrorMessage: "Failed to open dispute"
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
async function confirmAppointmentCompletion(config, accessToken, id, payload) {
|
|
1482
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${id}/confirm`, {
|
|
1483
|
+
method: "POST",
|
|
1484
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1485
|
+
body: JSON.stringify(payload ?? {}),
|
|
1486
|
+
fallbackErrorMessage: "Failed to confirm completion"
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
async function getMilestones(config, accessToken, bookingId) {
|
|
1490
|
+
return apiRequest(`${config.backendUrls.store}/service/bookings/${bookingId}/milestones`, {
|
|
1491
|
+
headers: authHeaders(config, accessToken),
|
|
1492
|
+
fallbackErrorMessage: "Failed to get milestones"
|
|
1493
|
+
});
|
|
1970
1494
|
}
|
|
1971
|
-
async function
|
|
1972
|
-
|
|
1973
|
-
`${config.backendUrls.store}/service/
|
|
1495
|
+
async function approveMilestone(config, accessToken, bookingId, milestoneId, payload) {
|
|
1496
|
+
return apiRequest(
|
|
1497
|
+
`${config.backendUrls.store}/service/bookings/${bookingId}/milestones/${milestoneId}/approve`,
|
|
1974
1498
|
{
|
|
1975
1499
|
method: "POST",
|
|
1976
|
-
headers: {
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
1980
|
-
"X-Business-ID": config.businessId
|
|
1981
|
-
},
|
|
1982
|
-
body: JSON.stringify({ approved: false, feedback })
|
|
1500
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1501
|
+
body: JSON.stringify(payload ?? {}),
|
|
1502
|
+
fallbackErrorMessage: "Failed to approve milestone"
|
|
1983
1503
|
}
|
|
1984
1504
|
);
|
|
1985
|
-
if (!response.ok) throw new Error("Failed to request revision");
|
|
1986
|
-
return response.json();
|
|
1987
1505
|
}
|
|
1988
1506
|
var serviceBookingService = {
|
|
1989
1507
|
getAvailableSlots,
|
|
@@ -1991,41 +1509,111 @@ var serviceBookingService = {
|
|
|
1991
1509
|
getAppointments,
|
|
1992
1510
|
getAppointment,
|
|
1993
1511
|
cancelAppointment,
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1512
|
+
rescheduleAppointment,
|
|
1513
|
+
disputeAppointment,
|
|
1514
|
+
confirmAppointmentCompletion,
|
|
1515
|
+
getMilestones,
|
|
1516
|
+
approveMilestone
|
|
1997
1517
|
};
|
|
1998
1518
|
|
|
1999
1519
|
// src/services/notifications.service.ts
|
|
1520
|
+
function bearerHeaders(accessToken) {
|
|
1521
|
+
return { Authorization: `Bearer ${accessToken}` };
|
|
1522
|
+
}
|
|
2000
1523
|
async function sendContactEmail(config, payload) {
|
|
2001
|
-
|
|
1524
|
+
return apiRequest(`${config.backendUrls.notifications}/contact/send-contact-email`, {
|
|
2002
1525
|
method: "POST",
|
|
2003
|
-
headers: {
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
"X-Business-ID": config.businessId
|
|
2007
|
-
},
|
|
2008
|
-
body: JSON.stringify(payload)
|
|
1526
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1527
|
+
body: JSON.stringify(payload),
|
|
1528
|
+
fallbackErrorMessage: "Failed to send contact email"
|
|
2009
1529
|
});
|
|
2010
|
-
if (!response.ok) throw new Error("Failed to send contact email");
|
|
2011
|
-
return response.json();
|
|
2012
1530
|
}
|
|
2013
1531
|
async function sendContactConfirmation(config, payload) {
|
|
2014
|
-
|
|
1532
|
+
return apiRequest(`${config.backendUrls.notifications}/contact/send-contact-confirmation`, {
|
|
1533
|
+
method: "POST",
|
|
1534
|
+
headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
|
|
1535
|
+
body: JSON.stringify(payload),
|
|
1536
|
+
fallbackErrorMessage: "Failed to send contact confirmation"
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
async function getNotificationPreferences(config, accessToken) {
|
|
1540
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications/preferences/`, {
|
|
1541
|
+
headers: bearerHeaders(accessToken),
|
|
1542
|
+
fallbackErrorMessage: "Failed to fetch notification preferences"
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
async function updateNotificationPreferences(config, accessToken, payload) {
|
|
1546
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications/preferences/`, {
|
|
1547
|
+
method: "PATCH",
|
|
1548
|
+
headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
|
|
1549
|
+
body: JSON.stringify(payload),
|
|
1550
|
+
fallbackErrorMessage: "Failed to update notification preferences"
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
async function getVapidPublicKey(config) {
|
|
1554
|
+
return apiRequest(`${config.backendUrls.notifications}/push/vapid-public-key`, {
|
|
1555
|
+
fallbackErrorMessage: "Failed to fetch VAPID public key"
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
async function subscribeToPush(config, accessToken, params) {
|
|
1559
|
+
return apiRequest(`${config.backendUrls.notifications}/push/subscribe`, {
|
|
1560
|
+
method: "POST",
|
|
1561
|
+
headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
|
|
1562
|
+
body: JSON.stringify(params),
|
|
1563
|
+
fallbackErrorMessage: "Failed to subscribe to push notifications"
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
async function unsubscribeFromPush(config, accessToken, endpoint) {
|
|
1567
|
+
return apiRequest(`${config.backendUrls.notifications}/push/subscribe`, {
|
|
1568
|
+
method: "DELETE",
|
|
1569
|
+
headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
|
|
1570
|
+
body: JSON.stringify({ endpoint }),
|
|
1571
|
+
fallbackErrorMessage: "Failed to unsubscribe from push notifications"
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
async function getNotificationInbox(config, accessToken, params) {
|
|
1575
|
+
const query = new URLSearchParams();
|
|
1576
|
+
if (params?.page) query.set("page", String(params.page));
|
|
1577
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
1578
|
+
if (params?.unread_only) query.set("unread_only", "true");
|
|
1579
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications?${query.toString()}`, {
|
|
1580
|
+
headers: bearerHeaders(accessToken),
|
|
1581
|
+
fallbackErrorMessage: "Failed to fetch notifications"
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
async function markNotificationRead(config, accessToken, notificationId) {
|
|
1585
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications/${notificationId}/read`, {
|
|
1586
|
+
method: "POST",
|
|
1587
|
+
headers: bearerHeaders(accessToken),
|
|
1588
|
+
fallbackErrorMessage: "Failed to mark notification as read"
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
async function markAllNotificationsRead(config, accessToken) {
|
|
1592
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications/mark-all-read`, {
|
|
1593
|
+
method: "POST",
|
|
1594
|
+
headers: bearerHeaders(accessToken),
|
|
1595
|
+
fallbackErrorMessage: "Failed to mark all notifications as read"
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
async function trackNotificationClick(config, accessToken, notificationId) {
|
|
1599
|
+
return apiRequest(`${config.backendUrls.notifications}/notifications/${notificationId}/click`, {
|
|
2015
1600
|
method: "POST",
|
|
2016
|
-
headers:
|
|
2017
|
-
|
|
2018
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
2019
|
-
"X-Business-ID": config.businessId
|
|
2020
|
-
},
|
|
2021
|
-
body: JSON.stringify(payload)
|
|
1601
|
+
headers: bearerHeaders(accessToken),
|
|
1602
|
+
fallbackErrorMessage: "Failed to track notification click"
|
|
2022
1603
|
});
|
|
2023
|
-
if (!response.ok) throw new Error("Failed to send contact confirmation");
|
|
2024
|
-
return response.json();
|
|
2025
1604
|
}
|
|
2026
1605
|
var notificationsService = {
|
|
2027
1606
|
sendContactEmail,
|
|
2028
|
-
sendContactConfirmation
|
|
1607
|
+
sendContactConfirmation,
|
|
1608
|
+
getNotificationPreferences,
|
|
1609
|
+
updateNotificationPreferences,
|
|
1610
|
+
getVapidPublicKey,
|
|
1611
|
+
subscribeToPush,
|
|
1612
|
+
unsubscribeFromPush,
|
|
1613
|
+
getNotificationInbox,
|
|
1614
|
+
markNotificationRead,
|
|
1615
|
+
markAllNotificationsRead,
|
|
1616
|
+
trackNotificationClick
|
|
2029
1617
|
};
|
|
2030
1618
|
|
|
2031
1619
|
// src/services/app.service.ts
|
|
@@ -2043,34 +1631,22 @@ async function googleTranslate(text, target, source = "en") {
|
|
|
2043
1631
|
|
|
2044
1632
|
// src/services/config.service.ts
|
|
2045
1633
|
async function getSupportedLanguages(config) {
|
|
2046
|
-
|
|
2047
|
-
headers:
|
|
2048
|
-
|
|
2049
|
-
"X-Business-ID": config.businessId
|
|
2050
|
-
}
|
|
1634
|
+
return apiRequest(`${config.backendUrls.payment}/config/supported-languages`, {
|
|
1635
|
+
headers: storefrontHeaders(config),
|
|
1636
|
+
fallbackErrorMessage: "Failed to get supported languages"
|
|
2051
1637
|
});
|
|
2052
|
-
if (!response.ok) throw new Error("Failed to get supported languages");
|
|
2053
|
-
return response.json();
|
|
2054
1638
|
}
|
|
2055
1639
|
async function getSupportedCurrencies(config) {
|
|
2056
|
-
|
|
2057
|
-
headers:
|
|
2058
|
-
|
|
2059
|
-
"X-Business-ID": config.businessId
|
|
2060
|
-
}
|
|
1640
|
+
return apiRequest(`${config.backendUrls.payment}/config/supported-currencies`, {
|
|
1641
|
+
headers: storefrontHeaders(config),
|
|
1642
|
+
fallbackErrorMessage: "Failed to get supported currencies"
|
|
2061
1643
|
});
|
|
2062
|
-
if (!response.ok) throw new Error("Failed to get supported currencies");
|
|
2063
|
-
return response.json();
|
|
2064
1644
|
}
|
|
2065
1645
|
async function getBusinessConfig(config) {
|
|
2066
|
-
|
|
2067
|
-
headers:
|
|
2068
|
-
|
|
2069
|
-
"X-Business-ID": config.businessId
|
|
2070
|
-
}
|
|
1646
|
+
return apiRequest(`${config.backendUrls.auth}/internal/businesses/${config.businessId}/`, {
|
|
1647
|
+
headers: storefrontHeaders(config),
|
|
1648
|
+
fallbackErrorMessage: "Failed to get business config"
|
|
2071
1649
|
});
|
|
2072
|
-
if (!response.ok) throw new Error("Failed to get business config");
|
|
2073
|
-
return response.json();
|
|
2074
1650
|
}
|
|
2075
1651
|
var configService = {
|
|
2076
1652
|
getSupportedLanguages,
|
|
@@ -2079,133 +1655,292 @@ var configService = {
|
|
|
2079
1655
|
};
|
|
2080
1656
|
|
|
2081
1657
|
// src/services/cms.service.ts
|
|
2082
|
-
async function listCmsEntries(config, modelSlug, params) {
|
|
1658
|
+
async function listCmsEntries(config, businessUuid, modelSlug, params) {
|
|
2083
1659
|
const queryParams = new URLSearchParams();
|
|
2084
1660
|
queryParams.set("page", (params?.page || 1).toString());
|
|
2085
1661
|
queryParams.set("page_size", (params?.page_size || 50).toString());
|
|
2086
|
-
|
|
2087
|
-
`${config.backendUrls.cms}/sdk/${
|
|
1662
|
+
return apiRequest(
|
|
1663
|
+
`${config.backendUrls.cms}/sdk/${businessUuid}/${modelSlug}/entries?${queryParams.toString()}`,
|
|
2088
1664
|
{
|
|
2089
|
-
headers:
|
|
2090
|
-
|
|
2091
|
-
"X-Business-ID": config.businessId
|
|
2092
|
-
}
|
|
1665
|
+
headers: storefrontHeaders(config),
|
|
1666
|
+
fallbackErrorMessage: "Failed to list CMS entries"
|
|
2093
1667
|
}
|
|
2094
1668
|
);
|
|
2095
|
-
if (!response.ok) throw new Error("Failed to list CMS entries");
|
|
2096
|
-
return response.json();
|
|
2097
1669
|
}
|
|
2098
|
-
async function getCmsEntry(config, modelSlug, entryId) {
|
|
2099
|
-
|
|
2100
|
-
`${config.backendUrls.cms}/sdk/${
|
|
1670
|
+
async function getCmsEntry(config, businessUuid, modelSlug, entryId) {
|
|
1671
|
+
return apiRequest(
|
|
1672
|
+
`${config.backendUrls.cms}/sdk/${businessUuid}/${modelSlug}/entries/${entryId}`,
|
|
2101
1673
|
{
|
|
2102
|
-
headers:
|
|
2103
|
-
|
|
2104
|
-
"X-Business-ID": config.businessId
|
|
2105
|
-
}
|
|
1674
|
+
headers: storefrontHeaders(config),
|
|
1675
|
+
fallbackErrorMessage: "Failed to get CMS entry"
|
|
2106
1676
|
}
|
|
2107
1677
|
);
|
|
2108
|
-
if (!response.ok) throw new Error("Failed to get CMS entry");
|
|
2109
|
-
return response.json();
|
|
2110
1678
|
}
|
|
2111
|
-
async function createCmsEntry(config, accessToken, modelSlug, params) {
|
|
2112
|
-
|
|
2113
|
-
`${config.backendUrls.cms}/sdk/${
|
|
1679
|
+
async function createCmsEntry(config, businessUuid, accessToken, modelSlug, params) {
|
|
1680
|
+
return apiRequest(
|
|
1681
|
+
`${config.backendUrls.cms}/sdk/${businessUuid}/${modelSlug}/entries`,
|
|
2114
1682
|
{
|
|
2115
1683
|
method: "POST",
|
|
2116
|
-
headers: {
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
2120
|
-
"X-Business-ID": config.businessId
|
|
2121
|
-
},
|
|
2122
|
-
body: JSON.stringify(params)
|
|
1684
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1685
|
+
body: JSON.stringify(params),
|
|
1686
|
+
fallbackErrorMessage: "Failed to create CMS entry"
|
|
2123
1687
|
}
|
|
2124
1688
|
);
|
|
2125
|
-
if (!response.ok) throw new Error("Failed to create CMS entry");
|
|
2126
|
-
return response.json();
|
|
2127
1689
|
}
|
|
2128
|
-
async function updateCmsEntry(config, accessToken, modelSlug, entryId, params) {
|
|
2129
|
-
|
|
2130
|
-
`${config.backendUrls.cms}/sdk/${
|
|
1690
|
+
async function updateCmsEntry(config, businessUuid, accessToken, modelSlug, entryId, params) {
|
|
1691
|
+
return apiRequest(
|
|
1692
|
+
`${config.backendUrls.cms}/sdk/${businessUuid}/${modelSlug}/entries/${entryId}`,
|
|
2131
1693
|
{
|
|
2132
1694
|
method: "PUT",
|
|
2133
|
-
headers: {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
2137
|
-
"X-Business-ID": config.businessId
|
|
2138
|
-
},
|
|
2139
|
-
body: JSON.stringify(params)
|
|
1695
|
+
headers: { ...JSON_HEADERS, ...authHeaders(config, accessToken) },
|
|
1696
|
+
body: JSON.stringify(params),
|
|
1697
|
+
fallbackErrorMessage: "Failed to update CMS entry"
|
|
2140
1698
|
}
|
|
2141
1699
|
);
|
|
2142
|
-
if (!response.ok) throw new Error("Failed to update CMS entry");
|
|
2143
|
-
return response.json();
|
|
2144
1700
|
}
|
|
2145
|
-
async function deleteCmsEntry(config, accessToken, modelSlug, entryId) {
|
|
2146
|
-
|
|
2147
|
-
`${config.backendUrls.cms}/sdk/${
|
|
1701
|
+
async function deleteCmsEntry(config, businessUuid, accessToken, modelSlug, entryId) {
|
|
1702
|
+
await apiRequest(
|
|
1703
|
+
`${config.backendUrls.cms}/sdk/${businessUuid}/${modelSlug}/entries/${entryId}`,
|
|
2148
1704
|
{
|
|
2149
1705
|
method: "DELETE",
|
|
2150
|
-
headers:
|
|
2151
|
-
|
|
2152
|
-
"X-Storefront-Key": config.storefrontApiKey,
|
|
2153
|
-
"X-Business-ID": config.businessId
|
|
2154
|
-
}
|
|
1706
|
+
headers: authHeaders(config, accessToken),
|
|
1707
|
+
fallbackErrorMessage: "Failed to delete CMS entry"
|
|
2155
1708
|
}
|
|
2156
1709
|
);
|
|
2157
|
-
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
// src/services/legal.service.ts
|
|
1713
|
+
async function getMerchantLegalDocument(config, businessUuid, documentType, fetchOptions) {
|
|
1714
|
+
if (!businessUuid || !config?.backendUrls?.cms) return null;
|
|
1715
|
+
try {
|
|
1716
|
+
const res = await fetch(
|
|
1717
|
+
`${config.backendUrls.cms}/cms/legal/storefront/${businessUuid}/${documentType}`,
|
|
1718
|
+
fetchOptions
|
|
1719
|
+
);
|
|
1720
|
+
if (!res.ok) return null;
|
|
1721
|
+
return await res.json();
|
|
1722
|
+
} catch {
|
|
1723
|
+
return null;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
// src/services/review.service.ts
|
|
1728
|
+
function fetchWithConfig(url, config, options = {}) {
|
|
1729
|
+
const headers = {
|
|
1730
|
+
...JSON_HEADERS,
|
|
1731
|
+
Accept: "application/json",
|
|
1732
|
+
...options.headers
|
|
1733
|
+
};
|
|
1734
|
+
if (config.storefrontApiKey) headers["X-Storefront-Key"] = config.storefrontApiKey;
|
|
1735
|
+
if (config.businessId) headers["X-Business-ID"] = config.businessId;
|
|
1736
|
+
if (config.authToken) headers["Authorization"] = `Bearer ${config.authToken}`;
|
|
1737
|
+
return apiRequest(url, { ...options, headers, fallbackErrorMessage: options.fallbackErrorMessage ?? "Request failed" });
|
|
1738
|
+
}
|
|
1739
|
+
async function createReview(reviewData, config) {
|
|
1740
|
+
const url = `${config.backendUrls.crm}/reviews`;
|
|
1741
|
+
return fetchWithConfig(url, config, {
|
|
1742
|
+
method: "POST",
|
|
1743
|
+
body: JSON.stringify(reviewData),
|
|
1744
|
+
fallbackErrorMessage: "Failed to create review"
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
async function updateReview(reviewId, reviewData, config) {
|
|
1748
|
+
const url = `${config.backendUrls.crm}/reviews/${reviewId}`;
|
|
1749
|
+
return fetchWithConfig(url, config, {
|
|
1750
|
+
method: "PUT",
|
|
1751
|
+
body: JSON.stringify(reviewData),
|
|
1752
|
+
fallbackErrorMessage: "Failed to update review"
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
async function getProductReviews(productId, params = {}, config) {
|
|
1756
|
+
const queryParams = new URLSearchParams();
|
|
1757
|
+
if (params.page) queryParams.append("page", params.page.toString());
|
|
1758
|
+
if (params.page_size) queryParams.append("page_size", params.page_size.toString());
|
|
1759
|
+
if (params.moderation_status) queryParams.append("moderation_status", params.moderation_status);
|
|
1760
|
+
const url = `${config.backendUrls.crm}/products/${productId}/reviews?${queryParams.toString()}`;
|
|
1761
|
+
return fetchWithConfig(url, config, { fallbackErrorMessage: "Failed to fetch product reviews" });
|
|
1762
|
+
}
|
|
1763
|
+
async function createComment(commentData, config) {
|
|
1764
|
+
const url = `${config.backendUrls.crm}/comments`;
|
|
1765
|
+
return fetchWithConfig(url, config, {
|
|
1766
|
+
method: "POST",
|
|
1767
|
+
body: JSON.stringify(commentData),
|
|
1768
|
+
fallbackErrorMessage: "Failed to create comment"
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
async function updateComment(commentId, commentData, config) {
|
|
1772
|
+
const url = `${config.backendUrls.crm}/comments/${commentId}`;
|
|
1773
|
+
return fetchWithConfig(url, config, {
|
|
1774
|
+
method: "PUT",
|
|
1775
|
+
body: JSON.stringify(commentData),
|
|
1776
|
+
fallbackErrorMessage: "Failed to update comment"
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
async function getProductComments(productId, params = {}, config) {
|
|
1780
|
+
const queryParams = new URLSearchParams();
|
|
1781
|
+
if (params.page) queryParams.append("page", params.page.toString());
|
|
1782
|
+
if (params.page_size) queryParams.append("page_size", params.page_size.toString());
|
|
1783
|
+
if (params.moderation_status) queryParams.append("moderation_status", params.moderation_status);
|
|
1784
|
+
const url = `${config.backendUrls.crm}/products/${productId}/comments?${queryParams.toString()}`;
|
|
1785
|
+
return fetchWithConfig(url, config, { fallbackErrorMessage: "Failed to fetch product comments" });
|
|
1786
|
+
}
|
|
1787
|
+
async function getPendingReviews(config) {
|
|
1788
|
+
const url = `${config.backendUrls.crm}/admin/reviews/pending`;
|
|
1789
|
+
return fetchWithConfig(url, config, { fallbackErrorMessage: "Failed to fetch pending reviews" });
|
|
1790
|
+
}
|
|
1791
|
+
async function getPendingComments(config) {
|
|
1792
|
+
const url = `${config.backendUrls.crm}/admin/comments/pending`;
|
|
1793
|
+
return fetchWithConfig(url, config, { fallbackErrorMessage: "Failed to fetch pending comments" });
|
|
1794
|
+
}
|
|
1795
|
+
async function moderateReview(reviewId, action, config) {
|
|
1796
|
+
const url = `${config.backendUrls.crm}/admin/reviews/${reviewId}/moderate`;
|
|
1797
|
+
return fetchWithConfig(url, config, {
|
|
1798
|
+
method: "POST",
|
|
1799
|
+
body: JSON.stringify(action),
|
|
1800
|
+
fallbackErrorMessage: "Failed to moderate review"
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
async function moderateComment(commentId, action, config) {
|
|
1804
|
+
const url = `${config.backendUrls.crm}/admin/comments/${commentId}/moderate`;
|
|
1805
|
+
return fetchWithConfig(url, config, {
|
|
1806
|
+
method: "POST",
|
|
1807
|
+
body: JSON.stringify(action),
|
|
1808
|
+
fallbackErrorMessage: "Failed to moderate comment"
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
async function merchantReplyToReview(reviewId, replyData, config) {
|
|
1812
|
+
const url = `${config.backendUrls.crm}/admin/reviews/${reviewId}/reply`;
|
|
1813
|
+
return fetchWithConfig(url, config, {
|
|
1814
|
+
method: "POST",
|
|
1815
|
+
body: JSON.stringify(replyData),
|
|
1816
|
+
fallbackErrorMessage: "Failed to post merchant reply"
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// src/services/media.service.ts
|
|
1821
|
+
async function uploadMediaFile(params) {
|
|
1822
|
+
const presignedUrlEndpoint = params.presignedUrlEndpoint ?? "/api/auth/media/presigned-url";
|
|
1823
|
+
const confirmUploadEndpoint = params.confirmUploadEndpoint ?? "/api/auth/media/confirm-upload";
|
|
1824
|
+
const { presigned_url, storage_path } = await apiRequest(presignedUrlEndpoint, {
|
|
1825
|
+
method: "POST",
|
|
1826
|
+
headers: JSON_HEADERS,
|
|
1827
|
+
credentials: "include",
|
|
1828
|
+
body: JSON.stringify({
|
|
1829
|
+
filename: params.file.name,
|
|
1830
|
+
content_type: params.file.type,
|
|
1831
|
+
context: params.context,
|
|
1832
|
+
entity_id: params.entityId,
|
|
1833
|
+
affiliation: params.affiliation,
|
|
1834
|
+
owner_id: params.ownerId
|
|
1835
|
+
}),
|
|
1836
|
+
fallbackErrorMessage: "Could not start upload"
|
|
1837
|
+
});
|
|
1838
|
+
const putResponse = await fetch(presigned_url, {
|
|
1839
|
+
method: "PUT",
|
|
1840
|
+
headers: { "Content-Type": params.file.type },
|
|
1841
|
+
body: params.file
|
|
1842
|
+
});
|
|
1843
|
+
if (!putResponse.ok) {
|
|
1844
|
+
throw new Error(`Failed to upload ${params.file.name}`);
|
|
1845
|
+
}
|
|
1846
|
+
return apiRequest(confirmUploadEndpoint, {
|
|
1847
|
+
method: "POST",
|
|
1848
|
+
headers: JSON_HEADERS,
|
|
1849
|
+
credentials: "include",
|
|
1850
|
+
body: JSON.stringify({
|
|
1851
|
+
storage_path,
|
|
1852
|
+
entity_id: params.entityId,
|
|
1853
|
+
original_filename: params.file.name,
|
|
1854
|
+
content_type: params.file.type,
|
|
1855
|
+
size: params.file.size,
|
|
1856
|
+
context: params.context,
|
|
1857
|
+
affiliation: params.affiliation,
|
|
1858
|
+
owner_id: params.ownerId
|
|
1859
|
+
}),
|
|
1860
|
+
fallbackErrorMessage: `Could not confirm upload of ${params.file.name}`
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
async function uploadMediaFiles(files, params) {
|
|
1864
|
+
const assets = [];
|
|
1865
|
+
const errors = [];
|
|
1866
|
+
for (const file of files) {
|
|
1867
|
+
try {
|
|
1868
|
+
assets.push(await uploadMediaFile({ ...params, file }));
|
|
1869
|
+
} catch (err) {
|
|
1870
|
+
errors.push({ file: file.name, message: err instanceof Error ? err.message : "Upload failed" });
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
return { assets, errors };
|
|
2158
1874
|
}
|
|
2159
1875
|
export {
|
|
2160
|
-
acceptQuote,
|
|
2161
1876
|
addToCart,
|
|
2162
1877
|
addToGuestCart,
|
|
2163
1878
|
addToWishlist,
|
|
2164
|
-
|
|
1879
|
+
approveBespokeDeliverable,
|
|
1880
|
+
approveMilestone,
|
|
1881
|
+
autocompleteAddress,
|
|
2165
1882
|
bespokeService,
|
|
2166
1883
|
bookAppointment,
|
|
2167
1884
|
cancelAppointment,
|
|
2168
1885
|
cancelOrder,
|
|
1886
|
+
changePassword,
|
|
2169
1887
|
checkAvailability,
|
|
2170
1888
|
checkInWishlist,
|
|
1889
|
+
claimWalletCredit,
|
|
2171
1890
|
clearCart,
|
|
2172
1891
|
clearGuestCart,
|
|
2173
1892
|
clearTokens,
|
|
2174
1893
|
configService,
|
|
2175
|
-
|
|
1894
|
+
confirmAppointmentCompletion,
|
|
1895
|
+
confirmMediaUpload,
|
|
1896
|
+
createBespokeOrder,
|
|
2176
1897
|
createCmsEntry,
|
|
1898
|
+
createComment,
|
|
2177
1899
|
createConsultation,
|
|
1900
|
+
createCustomerAddress,
|
|
2178
1901
|
createDedicatedAccount,
|
|
1902
|
+
createFeedback,
|
|
2179
1903
|
createOrder,
|
|
1904
|
+
createReview,
|
|
1905
|
+
createServiceBookingOrder,
|
|
1906
|
+
deactivateCustomerAccount,
|
|
1907
|
+
decodePlusCode,
|
|
2180
1908
|
deleteCmsEntry,
|
|
1909
|
+
deleteCustomerAddress,
|
|
1910
|
+
disputeAppointment,
|
|
2181
1911
|
findOrder,
|
|
2182
|
-
|
|
1912
|
+
forgotPasswordCustomer,
|
|
2183
1913
|
getAppointment,
|
|
2184
1914
|
getAppointments,
|
|
2185
1915
|
getAuthUser,
|
|
1916
|
+
getAvailablePaymentMethods,
|
|
2186
1917
|
getAvailableSlots,
|
|
2187
1918
|
getBusinessConfig,
|
|
2188
1919
|
getCart,
|
|
2189
1920
|
getCmsEntry,
|
|
2190
|
-
|
|
2191
|
-
getConsultations,
|
|
2192
|
-
getDeliverables,
|
|
1921
|
+
getCustomerAddresses,
|
|
2193
1922
|
getFeaturedProducts,
|
|
2194
1923
|
getGuestCart,
|
|
2195
|
-
getGuestCartCount,
|
|
2196
1924
|
getGuestCartProductType,
|
|
2197
|
-
getGuestCartSubtotal,
|
|
2198
|
-
getLatestProducts,
|
|
2199
|
-
getLowStockProducts,
|
|
2200
1925
|
getMe,
|
|
1926
|
+
getMerchantLegalDocument,
|
|
1927
|
+
getMilestones,
|
|
1928
|
+
getMyFeedback,
|
|
2201
1929
|
getNewProducts,
|
|
1930
|
+
getNotificationInbox,
|
|
1931
|
+
getNotificationPreferences,
|
|
2202
1932
|
getOnSaleProducts,
|
|
2203
1933
|
getOrders,
|
|
1934
|
+
getPendingComments,
|
|
1935
|
+
getPendingReviews,
|
|
2204
1936
|
getPopularProducts,
|
|
1937
|
+
getPresignedUploadUrl,
|
|
1938
|
+
getProductComments,
|
|
1939
|
+
getProductReviews,
|
|
2205
1940
|
getRecommendedProducts,
|
|
2206
|
-
getSellerShippingAddress,
|
|
2207
1941
|
getShippingRates,
|
|
2208
1942
|
getStoredTokens,
|
|
1943
|
+
getStorefrontBusinessInfo,
|
|
2209
1944
|
getStorefrontCollectionBySlug,
|
|
2210
1945
|
getStorefrontCollections,
|
|
2211
1946
|
getStorefrontProductBySlug,
|
|
@@ -2213,39 +1948,65 @@ export {
|
|
|
2213
1948
|
getSupportedCurrencies,
|
|
2214
1949
|
getSupportedLanguages,
|
|
2215
1950
|
getTransactionStatus,
|
|
1951
|
+
getVapidPublicKey,
|
|
1952
|
+
getWalletBalance,
|
|
1953
|
+
getWalletLedger,
|
|
2216
1954
|
getWishlist,
|
|
2217
1955
|
googleTranslate,
|
|
2218
1956
|
initiatePayment,
|
|
1957
|
+
listBusinessLocations,
|
|
2219
1958
|
listCmsEntries,
|
|
1959
|
+
listPickupLocations,
|
|
2220
1960
|
loginCustomer,
|
|
2221
1961
|
logisticsService,
|
|
2222
1962
|
logout,
|
|
2223
1963
|
mapAuthUserToCustomer,
|
|
1964
|
+
markAllNotificationsRead,
|
|
1965
|
+
markNotificationRead,
|
|
1966
|
+
merchantReplyToReview,
|
|
2224
1967
|
mergeGuestCart,
|
|
2225
1968
|
mergeGuestCartIfPresent,
|
|
1969
|
+
moderateComment,
|
|
1970
|
+
moderateReview,
|
|
2226
1971
|
notificationsService,
|
|
2227
1972
|
paymentService,
|
|
2228
1973
|
refreshToken,
|
|
2229
1974
|
registerCustomer,
|
|
2230
|
-
rejectQuote,
|
|
2231
1975
|
removeFromCart,
|
|
2232
1976
|
removeFromGuestCart,
|
|
2233
1977
|
removeFromWishlist,
|
|
2234
1978
|
removeProductFromWishlist,
|
|
2235
|
-
|
|
2236
|
-
|
|
1979
|
+
requestBespokeRevision,
|
|
1980
|
+
requestCustomerOtp,
|
|
1981
|
+
requestCustomerReactivation,
|
|
1982
|
+
rescheduleAppointment,
|
|
1983
|
+
resetPasswordCustomer,
|
|
1984
|
+
resolveDigitalDownload,
|
|
1985
|
+
resolveDigitalDownloadFile,
|
|
1986
|
+
reverseGeocode,
|
|
2237
1987
|
sendContactConfirmation,
|
|
2238
1988
|
sendContactEmail,
|
|
2239
|
-
sendMessage,
|
|
2240
1989
|
serviceBookingService,
|
|
2241
1990
|
silentRefresh,
|
|
2242
1991
|
storeTokens,
|
|
1992
|
+
subscribeToPush,
|
|
1993
|
+
trackNotificationClick,
|
|
2243
1994
|
trackOrder,
|
|
1995
|
+
unsubscribeFromPush,
|
|
2244
1996
|
updateCartItem,
|
|
2245
1997
|
updateCmsEntry,
|
|
1998
|
+
updateComment,
|
|
1999
|
+
updateCustomerAddress,
|
|
2246
2000
|
updateGuestCartItemQuantity,
|
|
2001
|
+
updateNotificationPreferences,
|
|
2247
2002
|
updateProfile,
|
|
2003
|
+
updateReview,
|
|
2004
|
+
uploadMediaFile,
|
|
2005
|
+
uploadMediaFiles,
|
|
2006
|
+
validatePromoCode,
|
|
2248
2007
|
validateShippingAddress,
|
|
2008
|
+
verifyCustomerOtp,
|
|
2009
|
+
verifyCustomerReactivation,
|
|
2249
2010
|
verifySocialToken,
|
|
2250
2011
|
verifyTransaction
|
|
2251
2012
|
};
|