arky-sdk 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config-CPkOgumU.d.cts +16 -0
- package/dist/config-CPkOgumU.d.ts +16 -0
- package/dist/index.cjs +1615 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +268 -0
- package/dist/index.d.ts +268 -26
- package/dist/index.js +1555 -56
- package/dist/index.js.map +1 -0
- package/dist/stores.cjs +2148 -0
- package/dist/stores.cjs.map +1 -0
- package/dist/stores.d.cts +218 -0
- package/dist/stores.d.ts +218 -0
- package/dist/stores.js +2111 -0
- package/dist/stores.js.map +1 -0
- package/dist/types.cjs +13 -0
- package/dist/types.cjs.map +1 -0
- package/dist/{types/index.d.ts → types.d.cts} +25 -24
- package/dist/types.d.ts +245 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.cjs +725 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +9 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +680 -0
- package/dist/utils.js.map +1 -0
- package/dist/validation-C9UAYKke.d.cts +245 -0
- package/dist/validation-DIvAzYjG.d.ts +245 -0
- package/package.json +17 -11
- package/dist/api/cms.d.ts +0 -19
- package/dist/api/cms.d.ts.map +0 -1
- package/dist/api/cms.js +0 -41
- package/dist/api/eshop.d.ts +0 -89
- package/dist/api/eshop.d.ts.map +0 -1
- package/dist/api/eshop.js +0 -183
- package/dist/api/index.d.ts +0 -6
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -5
- package/dist/api/newsletter.d.ts +0 -32
- package/dist/api/newsletter.d.ts.map +0 -1
- package/dist/api/newsletter.js +0 -70
- package/dist/api/reservation.d.ts +0 -84
- package/dist/api/reservation.d.ts.map +0 -1
- package/dist/api/reservation.js +0 -239
- package/dist/config.d.ts +0 -15
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -20
- package/dist/index.d.ts.map +0 -1
- package/dist/services/auth.d.ts +0 -17
- package/dist/services/auth.d.ts.map +0 -1
- package/dist/services/auth.js +0 -62
- package/dist/services/http.d.ts +0 -20
- package/dist/services/http.d.ts.map +0 -1
- package/dist/services/http.js +0 -73
- package/dist/stores/business.d.ts +0 -28
- package/dist/stores/business.d.ts.map +0 -1
- package/dist/stores/business.js +0 -122
- package/dist/stores/cart.d.ts +0 -8
- package/dist/stores/cart.d.ts.map +0 -1
- package/dist/stores/cart.js +0 -20
- package/dist/stores/eshop.d.ts +0 -121
- package/dist/stores/eshop.d.ts.map +0 -1
- package/dist/stores/eshop.js +0 -377
- package/dist/stores/index.d.ts +0 -7
- package/dist/stores/index.d.ts.map +0 -1
- package/dist/stores/index.js +0 -19
- package/dist/stores/reservation.d.ts +0 -237
- package/dist/stores/reservation.d.ts.map +0 -1
- package/dist/stores/reservation.js +0 -853
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -8
- package/dist/utils/blocks.d.ts +0 -30
- package/dist/utils/blocks.d.ts.map +0 -1
- package/dist/utils/blocks.js +0 -237
- package/dist/utils/currency.d.ts +0 -9
- package/dist/utils/currency.d.ts.map +0 -1
- package/dist/utils/currency.js +0 -99
- package/dist/utils/errors.d.ts +0 -121
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -114
- package/dist/utils/i18n.d.ts +0 -5
- package/dist/utils/i18n.d.ts.map +0 -1
- package/dist/utils/i18n.js +0 -37
- package/dist/utils/index.d.ts +0 -9
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -10
- package/dist/utils/price.d.ts +0 -33
- package/dist/utils/price.d.ts.map +0 -1
- package/dist/utils/price.js +0 -141
- package/dist/utils/queryParams.d.ts +0 -21
- package/dist/utils/queryParams.d.ts.map +0 -1
- package/dist/utils/queryParams.js +0 -47
- package/dist/utils/svg.d.ts +0 -17
- package/dist/utils/svg.d.ts.map +0 -1
- package/dist/utils/svg.js +0 -62
- package/dist/utils/text.d.ts +0 -26
- package/dist/utils/text.d.ts.map +0 -1
- package/dist/utils/text.js +0 -64
- package/dist/utils/timezone.d.ts +0 -9
- package/dist/utils/timezone.d.ts.map +0 -1
- package/dist/utils/timezone.js +0 -49
- package/dist/utils/validation.d.ts +0 -9
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -44
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1615 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var nanostores = require('nanostores');
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __esm = (fn, res) => function __init() {
|
|
8
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
|
+
};
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/config.ts
|
|
16
|
+
var config_exports = {};
|
|
17
|
+
__export(config_exports, {
|
|
18
|
+
API_URL: () => exports.API_URL,
|
|
19
|
+
BUSINESS_ID: () => exports.BUSINESS_ID,
|
|
20
|
+
STORAGE_URL: () => exports.STORAGE_URL,
|
|
21
|
+
getGlobalConfig: () => getGlobalConfig,
|
|
22
|
+
setGlobalConfig: () => setGlobalConfig
|
|
23
|
+
});
|
|
24
|
+
function setGlobalConfig(config) {
|
|
25
|
+
globalConfig = config;
|
|
26
|
+
exports.API_URL = config.apiUrl;
|
|
27
|
+
exports.BUSINESS_ID = config.businessId;
|
|
28
|
+
exports.STORAGE_URL = config.storageUrl || "";
|
|
29
|
+
}
|
|
30
|
+
function getGlobalConfig() {
|
|
31
|
+
if (!globalConfig) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"Arky SDK not initialized. Call initArky() or create an ArkyClient instance."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return globalConfig;
|
|
37
|
+
}
|
|
38
|
+
var globalConfig; exports.API_URL = void 0; exports.BUSINESS_ID = void 0; exports.STORAGE_URL = void 0;
|
|
39
|
+
var init_config = __esm({
|
|
40
|
+
"src/config.ts"() {
|
|
41
|
+
globalConfig = null;
|
|
42
|
+
exports.API_URL = "";
|
|
43
|
+
exports.BUSINESS_ID = "";
|
|
44
|
+
exports.STORAGE_URL = "";
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// src/index.ts
|
|
49
|
+
init_config();
|
|
50
|
+
|
|
51
|
+
// src/types/index.ts
|
|
52
|
+
var PaymentMethod = /* @__PURE__ */ ((PaymentMethod2) => {
|
|
53
|
+
PaymentMethod2["Cash"] = "CASH";
|
|
54
|
+
PaymentMethod2["CreditCard"] = "CREDIT_CARD";
|
|
55
|
+
PaymentMethod2["Free"] = "FREE";
|
|
56
|
+
return PaymentMethod2;
|
|
57
|
+
})(PaymentMethod || {});
|
|
58
|
+
|
|
59
|
+
// src/api/cms.ts
|
|
60
|
+
init_config();
|
|
61
|
+
|
|
62
|
+
// src/utils/queryParams.ts
|
|
63
|
+
function buildQueryString(params) {
|
|
64
|
+
const queryParts = [];
|
|
65
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
66
|
+
if (value === null || value === void 0) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
const jsonString = JSON.stringify(value);
|
|
71
|
+
queryParts.push(`${key}=${encodeURIComponent(jsonString)}`);
|
|
72
|
+
} else if (typeof value === "string") {
|
|
73
|
+
queryParts.push(`${key}=${encodeURIComponent(value)}`);
|
|
74
|
+
} else if (typeof value === "number" || typeof value === "boolean") {
|
|
75
|
+
queryParts.push(`${key}=${value}`);
|
|
76
|
+
} else if (typeof value === "object") {
|
|
77
|
+
const jsonString = JSON.stringify(value);
|
|
78
|
+
queryParts.push(`${key}=${encodeURIComponent(jsonString)}`);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
|
|
82
|
+
}
|
|
83
|
+
function appendQueryString(url, params) {
|
|
84
|
+
const queryString = buildQueryString(params);
|
|
85
|
+
return queryString ? `${url}${queryString}` : url;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/services/http.ts
|
|
89
|
+
async function get(url, options) {
|
|
90
|
+
try {
|
|
91
|
+
const finalUrl = options?.params ? appendQueryString(url, options.params) : url;
|
|
92
|
+
const response = await fetch(finalUrl);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
95
|
+
}
|
|
96
|
+
const data = await response.json();
|
|
97
|
+
return {
|
|
98
|
+
value: data,
|
|
99
|
+
success: true
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
103
|
+
return {
|
|
104
|
+
value: null,
|
|
105
|
+
success: false,
|
|
106
|
+
error: errorMsg
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function post(url, data, options) {
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch(url, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: {
|
|
115
|
+
"Content-Type": "application/json"
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify(data)
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
121
|
+
}
|
|
122
|
+
const responseData = await response.json();
|
|
123
|
+
return {
|
|
124
|
+
value: responseData,
|
|
125
|
+
success: true
|
|
126
|
+
};
|
|
127
|
+
} catch (error) {
|
|
128
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
129
|
+
return {
|
|
130
|
+
value: null,
|
|
131
|
+
success: false,
|
|
132
|
+
error: errorMsg
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
var httpClient = {
|
|
137
|
+
get,
|
|
138
|
+
post
|
|
139
|
+
};
|
|
140
|
+
var http_default = httpClient;
|
|
141
|
+
|
|
142
|
+
// src/api/cms.ts
|
|
143
|
+
var getCollection = async (id) => {
|
|
144
|
+
const url = `${exports.API_URL}/v1/businesses/${exports.BUSINESS_ID}/collections/${id}`;
|
|
145
|
+
const { value } = await http_default.get(url);
|
|
146
|
+
return value;
|
|
147
|
+
};
|
|
148
|
+
var getCollections = async ({ name = null, ids = null }) => {
|
|
149
|
+
const url = `${exports.API_URL}/v1/businesses/${exports.BUSINESS_ID}/collections`;
|
|
150
|
+
const response = await http_default.get(url, {
|
|
151
|
+
params: { name, ids }
|
|
152
|
+
});
|
|
153
|
+
return response.value;
|
|
154
|
+
};
|
|
155
|
+
var getCollectionEntries = async ({
|
|
156
|
+
collectionId,
|
|
157
|
+
limit,
|
|
158
|
+
cursor,
|
|
159
|
+
ids = null
|
|
160
|
+
}) => {
|
|
161
|
+
const url = `${exports.API_URL}/v1/businesses/${exports.BUSINESS_ID}/collections/${collectionId}/entries`;
|
|
162
|
+
const response = await http_default.get(url, {
|
|
163
|
+
params: { limit, cursor, ids }
|
|
164
|
+
});
|
|
165
|
+
return response.value;
|
|
166
|
+
};
|
|
167
|
+
var createCollectionEntry = async (collectionEntryData) => {
|
|
168
|
+
const url = `${exports.API_URL}/v1/businesses/${exports.BUSINESS_ID}/collections/${collectionEntryData.collectionId}/entries`;
|
|
169
|
+
const result = await http_default.post(url, collectionEntryData, {
|
|
170
|
+
successMessage: "Created successfully",
|
|
171
|
+
errorMessage: "Failed to create collection"
|
|
172
|
+
});
|
|
173
|
+
return result;
|
|
174
|
+
};
|
|
175
|
+
var getCollectionEntry = async ({ collectionId, id }) => {
|
|
176
|
+
const url = `${exports.API_URL}/v1/businesses/${exports.BUSINESS_ID}/collections/${collectionId}/entries/${id}`;
|
|
177
|
+
const response = await http_default.get(url);
|
|
178
|
+
return response;
|
|
179
|
+
};
|
|
180
|
+
var cmsApi = {
|
|
181
|
+
getCollection,
|
|
182
|
+
getCollections,
|
|
183
|
+
getCollectionEntries,
|
|
184
|
+
getCollectionEntry,
|
|
185
|
+
createCollectionEntry
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/api/eshop.ts
|
|
189
|
+
init_config();
|
|
190
|
+
|
|
191
|
+
// src/api/reservation.ts
|
|
192
|
+
init_config();
|
|
193
|
+
var reservationApi = {
|
|
194
|
+
// Get quote for reservation parts
|
|
195
|
+
async getQuote({
|
|
196
|
+
token,
|
|
197
|
+
businessId,
|
|
198
|
+
market,
|
|
199
|
+
currency: currency2,
|
|
200
|
+
userId,
|
|
201
|
+
parts,
|
|
202
|
+
paymentMethod = "CASH",
|
|
203
|
+
promoCode
|
|
204
|
+
}) {
|
|
205
|
+
try {
|
|
206
|
+
const lines = parts.map((part) => ({
|
|
207
|
+
type: "SERVICE",
|
|
208
|
+
serviceId: part.serviceId,
|
|
209
|
+
quantity: 1
|
|
210
|
+
}));
|
|
211
|
+
const payload = {
|
|
212
|
+
businessId,
|
|
213
|
+
market,
|
|
214
|
+
currency: currency2,
|
|
215
|
+
userId,
|
|
216
|
+
paymentMethod,
|
|
217
|
+
lines,
|
|
218
|
+
promoCode: promoCode || void 0,
|
|
219
|
+
shippingMethodId: null
|
|
220
|
+
};
|
|
221
|
+
const res = await fetch(`${exports.API_URL}/v1/payments/quote`, {
|
|
222
|
+
method: "POST",
|
|
223
|
+
headers: {
|
|
224
|
+
"Content-Type": "application/json",
|
|
225
|
+
"Authorization": `Bearer ${token}`
|
|
226
|
+
},
|
|
227
|
+
body: JSON.stringify(payload)
|
|
228
|
+
});
|
|
229
|
+
const text = await res.text();
|
|
230
|
+
if (!res.ok) {
|
|
231
|
+
try {
|
|
232
|
+
const json = JSON.parse(text);
|
|
233
|
+
return { success: false, error: json.reason || json.error || "Failed to fetch quote", code: json.code };
|
|
234
|
+
} catch {
|
|
235
|
+
return { success: false, error: text || "Failed to fetch quote" };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const quote = text ? JSON.parse(text) : null;
|
|
239
|
+
return { success: true, data: quote };
|
|
240
|
+
} catch (e) {
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
error: e.message || "Failed to fetch quote"
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
// Get available slots for a service
|
|
248
|
+
async getAvailableSlots({
|
|
249
|
+
businessId,
|
|
250
|
+
serviceId,
|
|
251
|
+
from,
|
|
252
|
+
to,
|
|
253
|
+
limit = 1e3,
|
|
254
|
+
providerId = null
|
|
255
|
+
}) {
|
|
256
|
+
const url = `${exports.API_URL}/v1/businesses/${businessId}/services/${serviceId}/available-slots`;
|
|
257
|
+
const response = await http_default.get(url, {
|
|
258
|
+
params: {
|
|
259
|
+
from,
|
|
260
|
+
to,
|
|
261
|
+
limit,
|
|
262
|
+
providerId
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
if (response.success) {
|
|
266
|
+
const json = response.value;
|
|
267
|
+
return {
|
|
268
|
+
success: true,
|
|
269
|
+
data: json.data?.items || json.items || []
|
|
270
|
+
};
|
|
271
|
+
} else {
|
|
272
|
+
console.error("Error fetching available slots:", response.error);
|
|
273
|
+
return {
|
|
274
|
+
success: false,
|
|
275
|
+
error: response.error,
|
|
276
|
+
data: []
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
// Get all providers for a service
|
|
281
|
+
async getProviders({ businessId, serviceId, limit = 50 }) {
|
|
282
|
+
const url = `${exports.API_URL}/v1/businesses/${businessId}/providers`;
|
|
283
|
+
const response = await http_default.get(url, {
|
|
284
|
+
params: {
|
|
285
|
+
serviceId,
|
|
286
|
+
limit
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
if (response.success) {
|
|
290
|
+
const json = response.value;
|
|
291
|
+
return {
|
|
292
|
+
success: true,
|
|
293
|
+
data: json.items || []
|
|
294
|
+
};
|
|
295
|
+
} else {
|
|
296
|
+
console.error("Error loading providers:", response.error);
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
error: response.error,
|
|
300
|
+
data: []
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
// Get guest token or create a new one
|
|
305
|
+
async getGuestToken() {
|
|
306
|
+
try {
|
|
307
|
+
const res = await fetch(`${exports.API_URL}/v1/users/login`, {
|
|
308
|
+
method: "POST",
|
|
309
|
+
headers: { "Content-Type": "application/json" },
|
|
310
|
+
body: JSON.stringify({ provider: "GUEST" })
|
|
311
|
+
});
|
|
312
|
+
if (!res.ok) throw new Error("Guest login failed");
|
|
313
|
+
const json = await res.json();
|
|
314
|
+
return {
|
|
315
|
+
success: true,
|
|
316
|
+
data: { token: json.accessToken }
|
|
317
|
+
};
|
|
318
|
+
} catch (e) {
|
|
319
|
+
return {
|
|
320
|
+
success: false,
|
|
321
|
+
error: e.message
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
// Update user's phone number
|
|
326
|
+
async updateProfilePhone({ token, phoneNumber }) {
|
|
327
|
+
try {
|
|
328
|
+
const res = await fetch(`${exports.API_URL}/v1/users/update`, {
|
|
329
|
+
method: "PUT",
|
|
330
|
+
headers: {
|
|
331
|
+
"Content-Type": "application/json",
|
|
332
|
+
Authorization: `Bearer ${token}`
|
|
333
|
+
},
|
|
334
|
+
body: JSON.stringify({
|
|
335
|
+
phoneNumber,
|
|
336
|
+
phoneNumbers: [],
|
|
337
|
+
addresses: []
|
|
338
|
+
})
|
|
339
|
+
});
|
|
340
|
+
if (!res.ok) {
|
|
341
|
+
const error = await res.text() || res.statusText;
|
|
342
|
+
return {
|
|
343
|
+
success: false,
|
|
344
|
+
error
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
success: true
|
|
349
|
+
};
|
|
350
|
+
} catch (e) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: e.message
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
// Verify phone number with code
|
|
358
|
+
async verifyPhoneCode({ token, phoneNumber, code }) {
|
|
359
|
+
try {
|
|
360
|
+
const res = await fetch(`${exports.API_URL}/v1/users/confirm/phone-number`, {
|
|
361
|
+
method: "PUT",
|
|
362
|
+
headers: {
|
|
363
|
+
"Content-Type": "application/json",
|
|
364
|
+
Authorization: `Bearer ${token}`
|
|
365
|
+
},
|
|
366
|
+
body: JSON.stringify({
|
|
367
|
+
phoneNumber,
|
|
368
|
+
code
|
|
369
|
+
})
|
|
370
|
+
});
|
|
371
|
+
if (!res.ok) {
|
|
372
|
+
const error = await res.text() || res.statusText;
|
|
373
|
+
return {
|
|
374
|
+
success: false,
|
|
375
|
+
error
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
return {
|
|
379
|
+
success: true
|
|
380
|
+
};
|
|
381
|
+
} catch (e) {
|
|
382
|
+
return {
|
|
383
|
+
success: false,
|
|
384
|
+
error: e.message
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
// Complete reservation checkout - Backend calculates currency from market
|
|
389
|
+
async checkout({
|
|
390
|
+
token,
|
|
391
|
+
businessId,
|
|
392
|
+
parts,
|
|
393
|
+
paymentMethod = "CASH",
|
|
394
|
+
blocks = [],
|
|
395
|
+
market = "US",
|
|
396
|
+
promoCode
|
|
397
|
+
}) {
|
|
398
|
+
try {
|
|
399
|
+
const payload = {
|
|
400
|
+
businessId,
|
|
401
|
+
blocks,
|
|
402
|
+
market,
|
|
403
|
+
parts: parts.map((p) => ({
|
|
404
|
+
serviceId: p.serviceId,
|
|
405
|
+
from: p.from,
|
|
406
|
+
to: p.to,
|
|
407
|
+
blocks: p.blocks,
|
|
408
|
+
reservationMethod: p.reservationMethod,
|
|
409
|
+
providerId: p.providerId
|
|
410
|
+
}))
|
|
411
|
+
};
|
|
412
|
+
if (paymentMethod !== void 0) {
|
|
413
|
+
payload.paymentMethod = paymentMethod;
|
|
414
|
+
}
|
|
415
|
+
if (promoCode) {
|
|
416
|
+
payload.promoCode = promoCode;
|
|
417
|
+
}
|
|
418
|
+
const res = await fetch(`${exports.API_URL}/v1/reservations/checkout`, {
|
|
419
|
+
method: "POST",
|
|
420
|
+
headers: {
|
|
421
|
+
"Content-Type": "application/json",
|
|
422
|
+
Authorization: `Bearer ${token}`
|
|
423
|
+
},
|
|
424
|
+
body: JSON.stringify(payload)
|
|
425
|
+
});
|
|
426
|
+
if (!res.ok) {
|
|
427
|
+
const error = await res.text() || res.statusText;
|
|
428
|
+
throw new Error(error);
|
|
429
|
+
}
|
|
430
|
+
const json = await res.json();
|
|
431
|
+
return {
|
|
432
|
+
success: true,
|
|
433
|
+
data: json
|
|
434
|
+
// Should include reservationId and clientSecret for payments
|
|
435
|
+
};
|
|
436
|
+
} catch (e) {
|
|
437
|
+
return {
|
|
438
|
+
success: false,
|
|
439
|
+
error: e.message
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// src/api/eshop.ts
|
|
446
|
+
var eshopApi = {
|
|
447
|
+
// Get products
|
|
448
|
+
async getProducts({
|
|
449
|
+
businessId,
|
|
450
|
+
categoryIds = null,
|
|
451
|
+
status = "ACTIVE",
|
|
452
|
+
limit = 20,
|
|
453
|
+
cursor = null
|
|
454
|
+
}) {
|
|
455
|
+
const url = `${exports.API_URL}/v1/businesses/${encodeURIComponent(businessId)}/products`;
|
|
456
|
+
const response = await http_default.get(url, {
|
|
457
|
+
params: {
|
|
458
|
+
categoryIds: categoryIds && categoryIds.length > 0 ? categoryIds : void 0,
|
|
459
|
+
status,
|
|
460
|
+
limit,
|
|
461
|
+
cursor
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
if (response.success) {
|
|
465
|
+
const json = response.value;
|
|
466
|
+
return {
|
|
467
|
+
success: true,
|
|
468
|
+
data: json.items || [],
|
|
469
|
+
cursor: json.cursor,
|
|
470
|
+
total: json.total || 0
|
|
471
|
+
};
|
|
472
|
+
} else {
|
|
473
|
+
console.error("Error fetching products:", response.error);
|
|
474
|
+
return {
|
|
475
|
+
success: false,
|
|
476
|
+
error: response.error,
|
|
477
|
+
data: []
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
// Get product by slug
|
|
482
|
+
async getProductBySlug({ businessId, slug }) {
|
|
483
|
+
try {
|
|
484
|
+
const url = `${exports.API_URL}/v1/businesses/${encodeURIComponent(businessId)}/products/slug/${encodeURIComponent(businessId)}/${encodeURIComponent(slug)}`;
|
|
485
|
+
const res = await fetch(url);
|
|
486
|
+
if (!res.ok) throw new Error("Product not found");
|
|
487
|
+
const json = await res.json();
|
|
488
|
+
return {
|
|
489
|
+
success: true,
|
|
490
|
+
data: json
|
|
491
|
+
};
|
|
492
|
+
} catch (e) {
|
|
493
|
+
console.error("Error fetching product:", e);
|
|
494
|
+
return {
|
|
495
|
+
success: false,
|
|
496
|
+
error: e.message,
|
|
497
|
+
data: null
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
// Get quote for cart (pricing with promo codes, shipping, taxes)
|
|
502
|
+
async getQuote({
|
|
503
|
+
token,
|
|
504
|
+
businessId,
|
|
505
|
+
items,
|
|
506
|
+
market,
|
|
507
|
+
currency: currency2,
|
|
508
|
+
userId,
|
|
509
|
+
paymentMethod,
|
|
510
|
+
shippingMethodId,
|
|
511
|
+
promoCode
|
|
512
|
+
}) {
|
|
513
|
+
try {
|
|
514
|
+
const lines = items.map((item) => ({
|
|
515
|
+
type: "PRODUCT_VARIANT",
|
|
516
|
+
productId: item.productId,
|
|
517
|
+
variantId: item.variantId,
|
|
518
|
+
quantity: item.quantity
|
|
519
|
+
}));
|
|
520
|
+
const payload = {
|
|
521
|
+
businessId,
|
|
522
|
+
market,
|
|
523
|
+
currency: currency2,
|
|
524
|
+
userId,
|
|
525
|
+
paymentMethod,
|
|
526
|
+
lines,
|
|
527
|
+
...shippingMethodId && { shippingMethodId },
|
|
528
|
+
...promoCode && { promoCode }
|
|
529
|
+
};
|
|
530
|
+
const res = await fetch(`${exports.API_URL}/v1/payments/quote`, {
|
|
531
|
+
method: "POST",
|
|
532
|
+
headers: {
|
|
533
|
+
"Content-Type": "application/json",
|
|
534
|
+
Authorization: `Bearer ${token}`
|
|
535
|
+
},
|
|
536
|
+
body: JSON.stringify(payload)
|
|
537
|
+
});
|
|
538
|
+
const text = await res.text();
|
|
539
|
+
if (!res.ok) {
|
|
540
|
+
try {
|
|
541
|
+
const json = JSON.parse(text);
|
|
542
|
+
return { success: false, error: json.reason || json.error || res.statusText, code: json.code };
|
|
543
|
+
} catch {
|
|
544
|
+
return { success: false, error: text || res.statusText };
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
const quote = text ? JSON.parse(text) : null;
|
|
548
|
+
return { success: true, data: quote };
|
|
549
|
+
} catch (e) {
|
|
550
|
+
console.error("Quote fetch failed:", e);
|
|
551
|
+
return {
|
|
552
|
+
success: false,
|
|
553
|
+
error: e.message
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
// Checkout - Backend calculates currency from market
|
|
558
|
+
async checkout({
|
|
559
|
+
token,
|
|
560
|
+
businessId,
|
|
561
|
+
items,
|
|
562
|
+
paymentMethod,
|
|
563
|
+
blocks,
|
|
564
|
+
market = "US",
|
|
565
|
+
shippingMethodId,
|
|
566
|
+
promoCode,
|
|
567
|
+
paymentIntentId = null
|
|
568
|
+
}) {
|
|
569
|
+
try {
|
|
570
|
+
const payload = {
|
|
571
|
+
businessId,
|
|
572
|
+
items,
|
|
573
|
+
paymentMethod,
|
|
574
|
+
blocks,
|
|
575
|
+
market,
|
|
576
|
+
...shippingMethodId && { shippingMethodId },
|
|
577
|
+
...promoCode && { promoCode },
|
|
578
|
+
...paymentIntentId && { paymentIntentId }
|
|
579
|
+
};
|
|
580
|
+
const res = await fetch(`${exports.API_URL}/v1/businesses/${encodeURIComponent(businessId)}/orders/checkout`, {
|
|
581
|
+
method: "POST",
|
|
582
|
+
headers: {
|
|
583
|
+
"Content-Type": "application/json",
|
|
584
|
+
Authorization: `Bearer ${token}`
|
|
585
|
+
},
|
|
586
|
+
body: JSON.stringify(payload)
|
|
587
|
+
});
|
|
588
|
+
const text = await res.text();
|
|
589
|
+
if (!res.ok) {
|
|
590
|
+
try {
|
|
591
|
+
const json2 = JSON.parse(text);
|
|
592
|
+
return { success: false, error: json2.reason || json2.error || res.statusText, code: json2.code };
|
|
593
|
+
} catch {
|
|
594
|
+
return { success: false, error: text || res.statusText };
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
const json = text ? JSON.parse(text) : null;
|
|
598
|
+
return { success: true, data: json };
|
|
599
|
+
} catch (e) {
|
|
600
|
+
return {
|
|
601
|
+
success: false,
|
|
602
|
+
error: e.message
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
// Create payment intent for Stripe
|
|
607
|
+
async createPaymentIntent({ amount, currency: currency2, businessId }) {
|
|
608
|
+
try {
|
|
609
|
+
const tokenResponse = await reservationApi.getGuestToken();
|
|
610
|
+
if (!tokenResponse.success || !tokenResponse.data) {
|
|
611
|
+
throw new Error("Failed to get guest token");
|
|
612
|
+
}
|
|
613
|
+
const token = tokenResponse.data.token;
|
|
614
|
+
const res = await fetch(`${exports.API_URL}/v1/businesses/${encodeURIComponent(businessId)}/payment/create-intent`, {
|
|
615
|
+
method: "POST",
|
|
616
|
+
headers: {
|
|
617
|
+
"Content-Type": "application/json",
|
|
618
|
+
Authorization: `Bearer ${token}`
|
|
619
|
+
},
|
|
620
|
+
body: JSON.stringify({
|
|
621
|
+
amount,
|
|
622
|
+
currency: currency2,
|
|
623
|
+
businessId
|
|
624
|
+
})
|
|
625
|
+
});
|
|
626
|
+
if (!res.ok) {
|
|
627
|
+
const error = await res.text() || res.statusText;
|
|
628
|
+
throw new Error(error);
|
|
629
|
+
}
|
|
630
|
+
const json = await res.json();
|
|
631
|
+
return {
|
|
632
|
+
success: true,
|
|
633
|
+
data: json
|
|
634
|
+
};
|
|
635
|
+
} catch (e) {
|
|
636
|
+
console.error("Payment intent creation failed:", e);
|
|
637
|
+
return {
|
|
638
|
+
success: false,
|
|
639
|
+
error: e.message
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// src/api/newsletter.ts
|
|
646
|
+
var newsletterApi = {
|
|
647
|
+
async find(payload) {
|
|
648
|
+
const params = new URLSearchParams({
|
|
649
|
+
businessId: payload.business_id
|
|
650
|
+
});
|
|
651
|
+
const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
652
|
+
const url = `${API_URL2}/v1/newsletters?${params.toString()}`;
|
|
653
|
+
const response = await fetch(url);
|
|
654
|
+
if (!response.ok) {
|
|
655
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
656
|
+
}
|
|
657
|
+
const backendResponse = await response.json();
|
|
658
|
+
return {
|
|
659
|
+
data: backendResponse.items || [],
|
|
660
|
+
meta: {
|
|
661
|
+
total: backendResponse.items?.length || 0,
|
|
662
|
+
page: 1,
|
|
663
|
+
per_page: backendResponse.items?.length || 0
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
},
|
|
667
|
+
async get(id) {
|
|
668
|
+
const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
669
|
+
const url = `${API_URL2}/v1/newsletters/${id}`;
|
|
670
|
+
const response = await fetch(url);
|
|
671
|
+
if (!response.ok) {
|
|
672
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
673
|
+
}
|
|
674
|
+
return await response.json();
|
|
675
|
+
},
|
|
676
|
+
async subscribe(payload) {
|
|
677
|
+
try {
|
|
678
|
+
const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
679
|
+
const url = `${API_URL2}/v1/newsletters/${payload.newsletterId}/subscribe`;
|
|
680
|
+
const response = await fetch(url, {
|
|
681
|
+
method: "POST",
|
|
682
|
+
headers: {
|
|
683
|
+
"Content-Type": "application/json"
|
|
684
|
+
},
|
|
685
|
+
body: JSON.stringify({
|
|
686
|
+
newsletterId: payload.newsletterId,
|
|
687
|
+
email: payload.email,
|
|
688
|
+
market: "US",
|
|
689
|
+
// Backend resolves currency from market
|
|
690
|
+
...payload.customerId && { customerId: payload.customerId },
|
|
691
|
+
...payload.payment && { payment: payload.payment }
|
|
692
|
+
})
|
|
693
|
+
});
|
|
694
|
+
if (!response.ok) {
|
|
695
|
+
const errorData = await response.json().catch(() => ({}));
|
|
696
|
+
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
|
|
697
|
+
}
|
|
698
|
+
const data = await response.json();
|
|
699
|
+
return {
|
|
700
|
+
success: true,
|
|
701
|
+
data
|
|
702
|
+
};
|
|
703
|
+
} catch (error) {
|
|
704
|
+
console.error("Newsletter subscription error:", error);
|
|
705
|
+
return {
|
|
706
|
+
success: false,
|
|
707
|
+
error: error instanceof Error ? error.message : "Failed to subscribe to newsletter"
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// src/services/auth.ts
|
|
714
|
+
init_config();
|
|
715
|
+
async function getGuestToken(currentToken = null) {
|
|
716
|
+
if (currentToken) return currentToken;
|
|
717
|
+
const response = await reservationApi.getGuestToken();
|
|
718
|
+
if (response.success && response.data) {
|
|
719
|
+
return response.data.token;
|
|
720
|
+
}
|
|
721
|
+
throw new Error("Failed to get guest token");
|
|
722
|
+
}
|
|
723
|
+
async function updateProfilePhone(token, phoneNumber) {
|
|
724
|
+
if (!phoneNumber) {
|
|
725
|
+
throw new Error("Phone number is required");
|
|
726
|
+
}
|
|
727
|
+
const response = await reservationApi.updateProfilePhone({ token, phoneNumber });
|
|
728
|
+
if (response.success) {
|
|
729
|
+
return { success: true };
|
|
730
|
+
} else {
|
|
731
|
+
throw new Error(response.error || "Failed to send verification code");
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
async function verifyPhoneCode(token, phoneNumber, code) {
|
|
735
|
+
if (!code) {
|
|
736
|
+
throw new Error("Verification code is required");
|
|
737
|
+
}
|
|
738
|
+
const response = await reservationApi.verifyPhoneCode({ token, phoneNumber, code });
|
|
739
|
+
if (response.success) {
|
|
740
|
+
return { success: true };
|
|
741
|
+
} else {
|
|
742
|
+
throw new Error(response.error || "Invalid verification code");
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
async function getBusinessConfig(businessId) {
|
|
746
|
+
try {
|
|
747
|
+
const response = await fetch(`${exports.API_URL}/v1/businesses/${businessId}`, {
|
|
748
|
+
method: "GET",
|
|
749
|
+
headers: {
|
|
750
|
+
"Content-Type": "application/json"
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
if (!response.ok) {
|
|
754
|
+
throw new Error(`Failed to fetch business config: ${response.status}`);
|
|
755
|
+
}
|
|
756
|
+
const business = await response.json();
|
|
757
|
+
return {
|
|
758
|
+
success: true,
|
|
759
|
+
data: business
|
|
760
|
+
};
|
|
761
|
+
} catch (error) {
|
|
762
|
+
return {
|
|
763
|
+
success: false,
|
|
764
|
+
error: error.message
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// src/utils/blocks.ts
|
|
770
|
+
init_config();
|
|
771
|
+
function getBlockLabel(block, locale = "en") {
|
|
772
|
+
if (!block) return "";
|
|
773
|
+
if (block.properties?.label) {
|
|
774
|
+
if (typeof block.properties.label === "object") {
|
|
775
|
+
return block.properties.label[locale] || block.properties.label.en || Object.values(block.properties.label)[0] || "";
|
|
776
|
+
}
|
|
777
|
+
if (typeof block.properties.label === "string") {
|
|
778
|
+
return block.properties.label;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) || "";
|
|
782
|
+
}
|
|
783
|
+
function formatBlockValue(block) {
|
|
784
|
+
if (!block || block.value === null || block.value === void 0) {
|
|
785
|
+
return "";
|
|
786
|
+
}
|
|
787
|
+
switch (block.type) {
|
|
788
|
+
case "BOOLEAN":
|
|
789
|
+
return block.value ? "Yes" : "No";
|
|
790
|
+
case "NUMBER":
|
|
791
|
+
if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
|
|
792
|
+
try {
|
|
793
|
+
return new Date(block.value).toLocaleDateString();
|
|
794
|
+
} catch (e) {
|
|
795
|
+
return String(block.value);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return String(block.value);
|
|
799
|
+
case "RELATIONSHIP":
|
|
800
|
+
if (Array.isArray(block.value) && block.value.length > 0) {
|
|
801
|
+
const firstValue = block.value[0];
|
|
802
|
+
if (firstValue && firstValue.mimeType) {
|
|
803
|
+
return firstValue.name || firstValue.id || "Media";
|
|
804
|
+
}
|
|
805
|
+
return firstValue.title || firstValue.name || firstValue.id || "Entry";
|
|
806
|
+
}
|
|
807
|
+
return String(block.value);
|
|
808
|
+
default:
|
|
809
|
+
return String(block.value);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
function prepareBlocksForSubmission(formData) {
|
|
813
|
+
const preparedBlocks = [];
|
|
814
|
+
Object.keys(formData).forEach((key) => {
|
|
815
|
+
if (formData[key] !== null && formData[key] !== void 0) {
|
|
816
|
+
preparedBlocks.push({
|
|
817
|
+
key,
|
|
818
|
+
value: [formData[key]]
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
return preparedBlocks;
|
|
823
|
+
}
|
|
824
|
+
function extractBlockValues(blocks) {
|
|
825
|
+
const values = {};
|
|
826
|
+
blocks.forEach((block) => {
|
|
827
|
+
if (block.value && block.value.length > 0) {
|
|
828
|
+
values[block.key] = block.value[0];
|
|
829
|
+
} else {
|
|
830
|
+
values[block.key] = null;
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
return values;
|
|
834
|
+
}
|
|
835
|
+
function getBlockTextValue(block, locale = "en") {
|
|
836
|
+
if (!block || !block.value || block.value.length === 0) return "";
|
|
837
|
+
const firstValue = block.value[0];
|
|
838
|
+
if (typeof firstValue === "object" && firstValue !== null) {
|
|
839
|
+
if (firstValue[locale]) return firstValue[locale];
|
|
840
|
+
if (firstValue.en) return firstValue.en;
|
|
841
|
+
const values = Object.values(firstValue);
|
|
842
|
+
return String(values[0] || "");
|
|
843
|
+
}
|
|
844
|
+
return String(firstValue);
|
|
845
|
+
}
|
|
846
|
+
var getBlockValue = (entry, blockKey) => {
|
|
847
|
+
if (!entry || !entry.blocks) return null;
|
|
848
|
+
const block = entry.blocks.find((f) => f.key === blockKey);
|
|
849
|
+
if (!block || !block.value || block.value.length === 0) return null;
|
|
850
|
+
return block.value[0];
|
|
851
|
+
};
|
|
852
|
+
var getBlockValues = (entry, blockKey) => {
|
|
853
|
+
if (!entry || !entry.blocks) return null;
|
|
854
|
+
const block = entry.blocks.find((f) => f.key === blockKey);
|
|
855
|
+
if (!block || !block.value || block.value.length === 0) return null;
|
|
856
|
+
return block.value;
|
|
857
|
+
};
|
|
858
|
+
function unwrapBlock(block, locale) {
|
|
859
|
+
if (!block?.type || block.value === void 0) return block;
|
|
860
|
+
if (block.type === "BLOCK") {
|
|
861
|
+
return block.value.map((obj) => {
|
|
862
|
+
const parsed = {};
|
|
863
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
864
|
+
parsed[k] = unwrapBlock(v, locale);
|
|
865
|
+
}
|
|
866
|
+
return parsed;
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
const isLocalized = block.type === "TEXT";
|
|
870
|
+
const isList = block.properties?.ui === "list" || (block.properties?.maxValues ?? 1) > 1 || block.value.length > 1;
|
|
871
|
+
if (isList) {
|
|
872
|
+
return isLocalized ? block.value.map((v) => v[locale] || v["en"]) : [...block.value];
|
|
873
|
+
}
|
|
874
|
+
return isLocalized ? block.value[0][locale] || block.value[0]["en"] : block.value[0];
|
|
875
|
+
}
|
|
876
|
+
var getBlockObjectValues = (entry, blockKey, locale = "en") => {
|
|
877
|
+
if (!entry) {
|
|
878
|
+
return [];
|
|
879
|
+
}
|
|
880
|
+
const values = getBlockValues(entry, blockKey);
|
|
881
|
+
const parsed = values.map((obj) => {
|
|
882
|
+
const res = obj.value.reduce((acc, current) => {
|
|
883
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
884
|
+
return acc;
|
|
885
|
+
}, {});
|
|
886
|
+
return res;
|
|
887
|
+
});
|
|
888
|
+
return parsed;
|
|
889
|
+
};
|
|
890
|
+
var getBlockFromArray = (entry, blockKey, locale = "en") => {
|
|
891
|
+
if (!entry) {
|
|
892
|
+
return [];
|
|
893
|
+
}
|
|
894
|
+
const values = getBlockValues(entry, blockKey);
|
|
895
|
+
return values.reduce((acc, current) => {
|
|
896
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
897
|
+
return acc;
|
|
898
|
+
});
|
|
899
|
+
};
|
|
900
|
+
var getImageUrl = (imageBlock, isBlock = true) => {
|
|
901
|
+
if (!imageBlock) return null;
|
|
902
|
+
const storageUrl = "https://storage.arky.io/dev";
|
|
903
|
+
const isExternalUrl = (url) => {
|
|
904
|
+
return url.startsWith("http://") || url.startsWith("https://");
|
|
905
|
+
};
|
|
906
|
+
if (imageBlock.type === "RELATIONSHIP" && Array.isArray(imageBlock.value)) {
|
|
907
|
+
const mediaValue = imageBlock.value[0];
|
|
908
|
+
if (mediaValue && mediaValue.mimeType) {
|
|
909
|
+
if (mediaValue.resolutions && mediaValue.resolutions.original && mediaValue.resolutions.original.url) {
|
|
910
|
+
const url = mediaValue.resolutions.original.url;
|
|
911
|
+
return isExternalUrl(url) ? url : `${storageUrl}/${url}`;
|
|
912
|
+
}
|
|
913
|
+
if (mediaValue.url) {
|
|
914
|
+
return isExternalUrl(mediaValue.url) ? mediaValue.url : `${storageUrl}/${mediaValue.url}`;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
if (isBlock) {
|
|
920
|
+
if (typeof imageBlock === "string") {
|
|
921
|
+
if (isExternalUrl(imageBlock)) {
|
|
922
|
+
return imageBlock;
|
|
923
|
+
}
|
|
924
|
+
return `${storageUrl}/${imageBlock}`;
|
|
925
|
+
}
|
|
926
|
+
if (imageBlock.url) {
|
|
927
|
+
if (isExternalUrl(imageBlock.url)) {
|
|
928
|
+
return imageBlock.url;
|
|
929
|
+
}
|
|
930
|
+
return `${storageUrl}/${imageBlock.url}`;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (imageBlock.resolutions && imageBlock.resolutions.original && imageBlock.resolutions.original.url) {
|
|
934
|
+
const url = imageBlock.resolutions.original.url;
|
|
935
|
+
if (isExternalUrl(url)) {
|
|
936
|
+
return url;
|
|
937
|
+
}
|
|
938
|
+
return `${storageUrl}/${url}`;
|
|
939
|
+
}
|
|
940
|
+
return null;
|
|
941
|
+
};
|
|
942
|
+
function getGalleryThumbnail(gallery) {
|
|
943
|
+
if (!gallery?.length) return null;
|
|
944
|
+
const item = gallery.find((g) => g.settings.isThumbnail) || gallery[0];
|
|
945
|
+
const res = item.media.resolutions.thumbnail || item.media.resolutions.original;
|
|
946
|
+
return res?.url || null;
|
|
947
|
+
}
|
|
948
|
+
function thumbnailUrl(service) {
|
|
949
|
+
const storageUrl = exports.STORAGE_URL || "";
|
|
950
|
+
const path = getGalleryThumbnail(service.gallery);
|
|
951
|
+
return path ? `${storageUrl}/${path}` : null;
|
|
952
|
+
}
|
|
953
|
+
var translateMap = (labels, lang, fallback = "unknown") => {
|
|
954
|
+
let parsedLang = "en";
|
|
955
|
+
if (lang === "sr") {
|
|
956
|
+
parsedLang = "bih";
|
|
957
|
+
}
|
|
958
|
+
if (!labels) {
|
|
959
|
+
return fallback;
|
|
960
|
+
}
|
|
961
|
+
const label = labels[parsedLang];
|
|
962
|
+
if (!label) {
|
|
963
|
+
return fallback;
|
|
964
|
+
}
|
|
965
|
+
return label;
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
// src/utils/errors.ts
|
|
969
|
+
var ERROR_CODES = {
|
|
970
|
+
// General errors
|
|
971
|
+
"GENERAL.001": "GENERAL.BAD_REQUEST",
|
|
972
|
+
"GENERAL.002": "GENERAL.VALIDATION_ERROR",
|
|
973
|
+
"GENERAL.003": "GENERAL.FORBIDDEN_ERROR",
|
|
974
|
+
"GENERAL.004": "GENERAL.INTERNAL_SERVER_ERROR",
|
|
975
|
+
"GENERAL.005": "GENERAL.UNAUTHORIZED",
|
|
976
|
+
"GENERAL.006": "GENERAL.UNAUTHENTICATED",
|
|
977
|
+
// Google/OAuth errors
|
|
978
|
+
"GOOGLE.001": "GOOGLE.INVALID_ORIGIN_URI",
|
|
979
|
+
"GOOGLE.002": "GOOGLE.INVALID_REDIRECT_URI",
|
|
980
|
+
"GOOGLE.003": "GOOGLE.FAILED_TO_CALL_API",
|
|
981
|
+
"GOOGLE.004": "GOOGLE.FAILED_LOGIN",
|
|
982
|
+
"GOOGLE.005": "GOOGLE.FAILED_LOGOUT",
|
|
983
|
+
"GOOGLE.006": "GOOGLE.FAILED_REFRESH_TOKEN",
|
|
984
|
+
"GOOGLE.007": "GOOGLE.INVALID_PROVIDER_PASSED",
|
|
985
|
+
// User errors
|
|
986
|
+
"USER.001": "USER.NOT_FOUND",
|
|
987
|
+
"USER.002": "USER.FAILED_TO_CREATE",
|
|
988
|
+
"USER.003": "USER.FAILED_TO_UPDATE",
|
|
989
|
+
"USER.004": "USER.FAILED_TO_DELETE",
|
|
990
|
+
"USER.005": "USER.EMAIL_EXISTS",
|
|
991
|
+
"USER.006": "USER.FAILED_TO_GET_UPLOAD_URL",
|
|
992
|
+
// Business errors
|
|
993
|
+
"BUSINESS.001": "BUSINESS.NOT_FOUND",
|
|
994
|
+
"BUSINESS.002": "BUSINESS.FAILED_TO_CREATE",
|
|
995
|
+
"BUSINESS.003": "BUSINESS.FAILED_TO_UPDATE",
|
|
996
|
+
"BUSINESS.004": "BUSINESS.FAILED_TO_DELETE",
|
|
997
|
+
"BUSINESS.005": "BUSINESS.FAILED_TO_GET_UPLOAD_URL",
|
|
998
|
+
"BUSINESS.006": "BUSINESS.NAME_REQUIRED",
|
|
999
|
+
"BUSINESS.007": "BUSINESS.BUSINESS_ID_REQUIRED",
|
|
1000
|
+
"BUSINESS.010": "BUSINESS.DESCRIPTION_REQUIRED",
|
|
1001
|
+
"BUSINESS.011": "BUSINESS.SLUG_INVALID",
|
|
1002
|
+
// Provider errors
|
|
1003
|
+
"PROVIDER.001": "PROVIDER.NOT_FOUND",
|
|
1004
|
+
"PROVIDER.002": "PROVIDER.FAILED_TO_CREATE",
|
|
1005
|
+
"PROVIDER.003": "PROVIDER.FAILED_TO_UPDATE",
|
|
1006
|
+
"PROVIDER.004": "PROVIDER.FAILED_TO_DELETE",
|
|
1007
|
+
"PROVIDER.005": "PROVIDER.FAILED_TO_GET_UPLOAD_URL",
|
|
1008
|
+
"PROVIDER.006": "PROVIDER.NAME_REQUIRED",
|
|
1009
|
+
"PROVIDER.007": "PROVIDER.BUSINESS_ID_REQUIRED",
|
|
1010
|
+
"PROVIDER.008": "PROVIDER.DESCRIPTION_REQUIRED"
|
|
1011
|
+
};
|
|
1012
|
+
var ERROR_CONSTANTS = {
|
|
1013
|
+
GENERAL: {
|
|
1014
|
+
BAD_REQUEST: "GENERAL.BAD_REQUEST",
|
|
1015
|
+
VALIDATION_ERROR: "GENERAL.VALIDATION_ERROR",
|
|
1016
|
+
FORBIDDEN_ERROR: "GENERAL.FORBIDDEN_ERROR",
|
|
1017
|
+
INTERNAL_SERVER_ERROR: "GENERAL.INTERNAL_SERVER_ERROR",
|
|
1018
|
+
UNAUTHORIZED: "GENERAL.UNAUTHORIZED",
|
|
1019
|
+
UNAUTHENTICATED: "GENERAL.UNAUTHENTICATED"
|
|
1020
|
+
},
|
|
1021
|
+
USER: {
|
|
1022
|
+
NOT_FOUND: "USER.NOT_FOUND",
|
|
1023
|
+
FAILED_TO_CREATE: "USER.FAILED_TO_CREATE",
|
|
1024
|
+
FAILED_TO_UPDATE: "USER.FAILED_TO_UPDATE",
|
|
1025
|
+
FAILED_TO_DELETE: "USER.FAILED_TO_DELETE",
|
|
1026
|
+
EMAIL_EXISTS: "USER.EMAIL_EXISTS",
|
|
1027
|
+
FAILED_TO_GET_UPLOAD_URL: "USER.FAILED_TO_GET_UPLOAD_URL"
|
|
1028
|
+
},
|
|
1029
|
+
BUSINESS: {
|
|
1030
|
+
NOT_FOUND: "BUSINESS.NOT_FOUND",
|
|
1031
|
+
FAILED_TO_CREATE: "BUSINESS.FAILED_TO_CREATE",
|
|
1032
|
+
FAILED_TO_UPDATE: "BUSINESS.FAILED_TO_UPDATE",
|
|
1033
|
+
FAILED_TO_DELETE: "BUSINESS.FAILED_TO_DELETE",
|
|
1034
|
+
FAILED_TO_GET_UPLOAD_URL: "BUSINESS.FAILED_TO_GET_UPLOAD_URL",
|
|
1035
|
+
NAME_REQUIRED: "BUSINESS.NAME_REQUIRED",
|
|
1036
|
+
BUSINESS_ID_REQUIRED: "BUSINESS.BUSINESS_ID_REQUIRED",
|
|
1037
|
+
DESCRIPTION_REQUIRED: "BUSINESS.DESCRIPTION_REQUIRED",
|
|
1038
|
+
SLUG_INVALID: "BUSINESS.SLUG_INVALID"
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
function getErrorMessage(code) {
|
|
1042
|
+
return ERROR_CODES[code] || code;
|
|
1043
|
+
}
|
|
1044
|
+
function isErrorCode(code) {
|
|
1045
|
+
return code in ERROR_CODES;
|
|
1046
|
+
}
|
|
1047
|
+
var transformErrors = (zodError) => {
|
|
1048
|
+
const customErrors = [];
|
|
1049
|
+
if (!zodError.issues) return customErrors;
|
|
1050
|
+
zodError.issues.forEach((issue) => {
|
|
1051
|
+
const field = issue.path.join(".");
|
|
1052
|
+
const message = issue.message;
|
|
1053
|
+
if (!customErrors.some(
|
|
1054
|
+
(customError) => customError.field === field && customError.message === message
|
|
1055
|
+
)) {
|
|
1056
|
+
customErrors.push({ field, message });
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
return customErrors;
|
|
1060
|
+
};
|
|
1061
|
+
var convertServerErrorToRequestError = (serverError, renameRules) => {
|
|
1062
|
+
return {
|
|
1063
|
+
...serverError,
|
|
1064
|
+
validationErrors: serverError.validationErrors.map((validationError) => {
|
|
1065
|
+
const field = renameRules && renameRules[validationError.field] ? renameRules[validationError.field] : validationError.field;
|
|
1066
|
+
return {
|
|
1067
|
+
field,
|
|
1068
|
+
message: ERROR_CODES[validationError.code] || "Unknown error"
|
|
1069
|
+
};
|
|
1070
|
+
})
|
|
1071
|
+
};
|
|
1072
|
+
};
|
|
1073
|
+
var errors = ERROR_CONSTANTS;
|
|
1074
|
+
|
|
1075
|
+
// src/utils/currency.ts
|
|
1076
|
+
function getCurrencySymbol(currency2) {
|
|
1077
|
+
const currencySymbols = {
|
|
1078
|
+
USD: "$",
|
|
1079
|
+
EUR: "\u20AC",
|
|
1080
|
+
GBP: "\xA3",
|
|
1081
|
+
CAD: "C$",
|
|
1082
|
+
AUD: "A$",
|
|
1083
|
+
JPY: "\xA5",
|
|
1084
|
+
CHF: "CHF",
|
|
1085
|
+
SEK: "kr",
|
|
1086
|
+
NOK: "kr",
|
|
1087
|
+
DKK: "kr",
|
|
1088
|
+
PLN: "z\u0142",
|
|
1089
|
+
CZK: "K\u010D",
|
|
1090
|
+
HUF: "Ft",
|
|
1091
|
+
RON: "lei",
|
|
1092
|
+
BGN: "\u043B\u0432",
|
|
1093
|
+
HRK: "kn",
|
|
1094
|
+
RSD: "\u0434\u0438\u043D",
|
|
1095
|
+
BAM: "KM",
|
|
1096
|
+
MKD: "\u0434\u0435\u043D",
|
|
1097
|
+
ALL: "L",
|
|
1098
|
+
TRY: "\u20BA",
|
|
1099
|
+
RUB: "\u20BD",
|
|
1100
|
+
UAH: "\u20B4",
|
|
1101
|
+
BYN: "Br",
|
|
1102
|
+
CNY: "\xA5",
|
|
1103
|
+
INR: "\u20B9",
|
|
1104
|
+
KRW: "\u20A9",
|
|
1105
|
+
THB: "\u0E3F",
|
|
1106
|
+
VND: "\u20AB",
|
|
1107
|
+
SGD: "S$",
|
|
1108
|
+
MYR: "RM",
|
|
1109
|
+
IDR: "Rp",
|
|
1110
|
+
PHP: "\u20B1",
|
|
1111
|
+
BRL: "R$",
|
|
1112
|
+
ARS: "$",
|
|
1113
|
+
CLP: "$",
|
|
1114
|
+
COP: "$",
|
|
1115
|
+
PEN: "S/",
|
|
1116
|
+
MXN: "$",
|
|
1117
|
+
ZAR: "R",
|
|
1118
|
+
EGP: "E\xA3",
|
|
1119
|
+
NGN: "\u20A6",
|
|
1120
|
+
KES: "KSh",
|
|
1121
|
+
GHS: "\u20B5",
|
|
1122
|
+
MAD: "DH",
|
|
1123
|
+
TND: "\u062F.\u062A",
|
|
1124
|
+
DZD: "\u062F.\u062C",
|
|
1125
|
+
LYD: "\u0644.\u062F",
|
|
1126
|
+
AED: "\u062F.\u0625",
|
|
1127
|
+
SAR: "\u0631.\u0633",
|
|
1128
|
+
QAR: "\u0631.\u0642",
|
|
1129
|
+
KWD: "\u062F.\u0643",
|
|
1130
|
+
BHD: "\u0628.\u062F",
|
|
1131
|
+
OMR: "\u0631.\u0639",
|
|
1132
|
+
JOD: "\u062F.\u0623",
|
|
1133
|
+
LBP: "\u0644.\u0644",
|
|
1134
|
+
SYP: "\u0644.\u0633",
|
|
1135
|
+
IQD: "\u0639.\u062F",
|
|
1136
|
+
IRR: "\uFDFC",
|
|
1137
|
+
AFN: "\u060B",
|
|
1138
|
+
PKR: "\u20A8",
|
|
1139
|
+
LKR: "\u20A8",
|
|
1140
|
+
NPR: "\u20A8",
|
|
1141
|
+
BDT: "\u09F3",
|
|
1142
|
+
MMK: "K",
|
|
1143
|
+
LAK: "\u20AD",
|
|
1144
|
+
KHR: "\u17DB",
|
|
1145
|
+
MNT: "\u20AE",
|
|
1146
|
+
KZT: "\u20B8",
|
|
1147
|
+
UZS: "\u043B\u0432",
|
|
1148
|
+
KGS: "\u043B\u0432",
|
|
1149
|
+
TJS: "SM",
|
|
1150
|
+
TMT: "T",
|
|
1151
|
+
AZN: "\u20BC",
|
|
1152
|
+
GEL: "\u20BE",
|
|
1153
|
+
AMD: "\u058F",
|
|
1154
|
+
BYR: "p.",
|
|
1155
|
+
MDL: "L"
|
|
1156
|
+
};
|
|
1157
|
+
return currencySymbols[currency2.toUpperCase()] || currency2;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// src/utils/price.ts
|
|
1161
|
+
var CURRENCY_SYMBOLS = {
|
|
1162
|
+
"USD": "$",
|
|
1163
|
+
"EUR": "\u20AC",
|
|
1164
|
+
"GBP": "\xA3",
|
|
1165
|
+
"CAD": "C$",
|
|
1166
|
+
"AUD": "A$"
|
|
1167
|
+
};
|
|
1168
|
+
var MARKET_CURRENCIES = {
|
|
1169
|
+
"US": "USD",
|
|
1170
|
+
"EU": "EUR",
|
|
1171
|
+
"UK": "GBP",
|
|
1172
|
+
"CA": "CAD",
|
|
1173
|
+
"AU": "AUD"
|
|
1174
|
+
};
|
|
1175
|
+
function convertToMajor(minorAmount) {
|
|
1176
|
+
return (minorAmount ?? 0) / 100;
|
|
1177
|
+
}
|
|
1178
|
+
function convertToMinor(majorAmount) {
|
|
1179
|
+
return Math.round((majorAmount ?? 0) * 100);
|
|
1180
|
+
}
|
|
1181
|
+
function getSymbol(currency2) {
|
|
1182
|
+
return CURRENCY_SYMBOLS[currency2] || "$";
|
|
1183
|
+
}
|
|
1184
|
+
function getCurrencyFromMarket(marketId) {
|
|
1185
|
+
return MARKET_CURRENCIES[marketId] || "USD";
|
|
1186
|
+
}
|
|
1187
|
+
function formatCurrencyAmount(amount, currency2, options = {}) {
|
|
1188
|
+
const { showSymbols = true, decimalPlaces = 2, customSymbol } = options;
|
|
1189
|
+
const roundedAmount = amount.toFixed(decimalPlaces);
|
|
1190
|
+
if (!showSymbols) {
|
|
1191
|
+
return `${roundedAmount} ${currency2}`;
|
|
1192
|
+
}
|
|
1193
|
+
const symbol = customSymbol || getSymbol(currency2);
|
|
1194
|
+
return `${symbol}${roundedAmount}`;
|
|
1195
|
+
}
|
|
1196
|
+
function formatMinor(amountMinor, currency2, options = {}) {
|
|
1197
|
+
const major = convertToMajor(amountMinor);
|
|
1198
|
+
return formatCurrencyAmount(major, currency2, options);
|
|
1199
|
+
}
|
|
1200
|
+
function formatPayment(payment, options = {}) {
|
|
1201
|
+
if (!payment) return "";
|
|
1202
|
+
const { showSymbols = true, decimalPlaces = 2, showBreakdown = false } = options;
|
|
1203
|
+
if (showBreakdown) {
|
|
1204
|
+
const subtotal = formatMinor(payment.subtotal, payment.currency, { showSymbols, decimalPlaces });
|
|
1205
|
+
const discount = (payment.discount ?? 0) > 0 ? formatMinor(payment.discount, payment.currency, { showSymbols, decimalPlaces }) : null;
|
|
1206
|
+
const tax = (payment.tax ?? 0) > 0 ? formatMinor(payment.tax, payment.currency, { showSymbols, decimalPlaces }) : null;
|
|
1207
|
+
const total = formatMinor(payment.total, payment.currency, { showSymbols, decimalPlaces });
|
|
1208
|
+
let result = `Subtotal: ${subtotal}`;
|
|
1209
|
+
if (discount) result += `, Discount: -${discount}`;
|
|
1210
|
+
if (tax) result += `, Tax: ${tax}`;
|
|
1211
|
+
result += `, Total: ${total}`;
|
|
1212
|
+
return result;
|
|
1213
|
+
}
|
|
1214
|
+
return formatMinor(payment.total, payment.currency, { showSymbols, decimalPlaces });
|
|
1215
|
+
}
|
|
1216
|
+
function getMarketPrice(prices, marketId, businessMarkets, options = {}) {
|
|
1217
|
+
if (!prices || prices.length === 0) return "";
|
|
1218
|
+
const {
|
|
1219
|
+
showSymbols = true,
|
|
1220
|
+
decimalPlaces = 2,
|
|
1221
|
+
showCompareAt = true,
|
|
1222
|
+
fallbackMarket = "US"
|
|
1223
|
+
} = options;
|
|
1224
|
+
let price = prices.find((p) => p.market === marketId);
|
|
1225
|
+
if (!price) {
|
|
1226
|
+
price = prices.find((p) => p.market === fallbackMarket) || prices[0];
|
|
1227
|
+
}
|
|
1228
|
+
if (!price) return "";
|
|
1229
|
+
let currency2;
|
|
1230
|
+
let symbol;
|
|
1231
|
+
if (businessMarkets) {
|
|
1232
|
+
const marketData = businessMarkets.find((m) => m.id === price.market || m.code === price.market);
|
|
1233
|
+
if (marketData?.currency) {
|
|
1234
|
+
currency2 = marketData.currency;
|
|
1235
|
+
symbol = getCurrencySymbol(currency2);
|
|
1236
|
+
} else {
|
|
1237
|
+
currency2 = getCurrencyFromMarket(price.market);
|
|
1238
|
+
symbol = getSymbol(currency2);
|
|
1239
|
+
}
|
|
1240
|
+
} else {
|
|
1241
|
+
currency2 = getCurrencyFromMarket(price.market);
|
|
1242
|
+
symbol = getSymbol(currency2);
|
|
1243
|
+
}
|
|
1244
|
+
const formattedPrice = formatMinor(price.amount ?? 0, currency2, {
|
|
1245
|
+
showSymbols,
|
|
1246
|
+
decimalPlaces,
|
|
1247
|
+
customSymbol: symbol
|
|
1248
|
+
});
|
|
1249
|
+
if (showCompareAt && price.compareAt && price.compareAt > (price.amount ?? 0)) {
|
|
1250
|
+
const formattedCompareAt = formatMinor(price.compareAt, currency2, {
|
|
1251
|
+
showSymbols,
|
|
1252
|
+
decimalPlaces,
|
|
1253
|
+
customSymbol: symbol
|
|
1254
|
+
});
|
|
1255
|
+
return `${formattedPrice} was ${formattedCompareAt}`;
|
|
1256
|
+
}
|
|
1257
|
+
return formattedPrice;
|
|
1258
|
+
}
|
|
1259
|
+
function getPriceAmount(prices, marketId, fallbackMarket = "US") {
|
|
1260
|
+
if (!prices || prices.length === 0) return 0;
|
|
1261
|
+
const price = prices.find((p) => p.market === marketId) || prices.find((p) => p.market === fallbackMarket) || prices[0];
|
|
1262
|
+
return price?.amount || 0;
|
|
1263
|
+
}
|
|
1264
|
+
function createPaymentForCheckout(subtotalMinor, marketId, currency2, paymentMethod, options = {}) {
|
|
1265
|
+
const { discount = 0, tax = 0, promoCodeId } = options;
|
|
1266
|
+
const total = subtotalMinor - discount + tax;
|
|
1267
|
+
return {
|
|
1268
|
+
currency: currency2,
|
|
1269
|
+
market: marketId,
|
|
1270
|
+
subtotal: subtotalMinor,
|
|
1271
|
+
shipping: 0,
|
|
1272
|
+
discount,
|
|
1273
|
+
tax,
|
|
1274
|
+
total,
|
|
1275
|
+
promoCodeId,
|
|
1276
|
+
method: paymentMethod
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
// src/utils/svg.ts
|
|
1281
|
+
async function fetchSvgContent(mediaObject) {
|
|
1282
|
+
if (!mediaObject) return null;
|
|
1283
|
+
const svgUrl = getImageUrl(mediaObject, false);
|
|
1284
|
+
try {
|
|
1285
|
+
const response = await fetch(svgUrl);
|
|
1286
|
+
if (!response.ok) {
|
|
1287
|
+
console.error(`Failed to fetch SVG: ${response.status} ${response.statusText}`);
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
const svgContent = await response.text();
|
|
1291
|
+
return svgContent;
|
|
1292
|
+
} catch (error) {
|
|
1293
|
+
console.error("Error fetching SVG:", error);
|
|
1294
|
+
return null;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
async function getSvgContentForAstro(mediaObject) {
|
|
1298
|
+
try {
|
|
1299
|
+
const svgContent = await fetchSvgContent(mediaObject);
|
|
1300
|
+
return svgContent || "";
|
|
1301
|
+
} catch (error) {
|
|
1302
|
+
console.error("Error getting SVG content for Astro:", error);
|
|
1303
|
+
return "";
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
async function injectSvgIntoElement(mediaObject, targetElement, className) {
|
|
1307
|
+
if (!targetElement) return;
|
|
1308
|
+
try {
|
|
1309
|
+
const svgContent = await fetchSvgContent(mediaObject);
|
|
1310
|
+
if (svgContent) {
|
|
1311
|
+
targetElement.innerHTML = svgContent;
|
|
1312
|
+
if (className) {
|
|
1313
|
+
const svgElement = targetElement.querySelector("svg");
|
|
1314
|
+
if (svgElement) {
|
|
1315
|
+
svgElement.classList.add(...className.split(" "));
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
console.error("Error injecting SVG:", error);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// src/utils/text.ts
|
|
1325
|
+
var locales = ["en", "sr-latn"];
|
|
1326
|
+
var localeMap = {
|
|
1327
|
+
"en": "en-US",
|
|
1328
|
+
"sr-latn": "sr-RS"
|
|
1329
|
+
};
|
|
1330
|
+
function slugify(text) {
|
|
1331
|
+
return text.toString().toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
1332
|
+
}
|
|
1333
|
+
function humanize(text) {
|
|
1334
|
+
const slugifiedText = slugify(text);
|
|
1335
|
+
return slugifiedText.replace(/-/g, " ").replace(
|
|
1336
|
+
// upper case first letter of every word, and lower case the rest
|
|
1337
|
+
/\w\S*/g,
|
|
1338
|
+
(w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
function categorify(text) {
|
|
1342
|
+
const slugifiedText = slugify(text);
|
|
1343
|
+
return slugifiedText.replace(/-/g, " ").toUpperCase();
|
|
1344
|
+
}
|
|
1345
|
+
function formatDate(date, locale) {
|
|
1346
|
+
let localeString = "en-US";
|
|
1347
|
+
if (locales.includes(locale)) {
|
|
1348
|
+
localeString = localeMap[locale];
|
|
1349
|
+
}
|
|
1350
|
+
return new Date(date).toLocaleDateString(localeString, {
|
|
1351
|
+
timeZone: "UTC",
|
|
1352
|
+
year: "numeric",
|
|
1353
|
+
month: "short",
|
|
1354
|
+
day: "numeric"
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// src/utils/timezone.ts
|
|
1359
|
+
var tzGroups = [
|
|
1360
|
+
{
|
|
1361
|
+
label: "US",
|
|
1362
|
+
zones: [
|
|
1363
|
+
{ label: "Eastern Time", value: "America/New_York" },
|
|
1364
|
+
{ label: "Central Time", value: "America/Chicago" },
|
|
1365
|
+
{ label: "Mountain Time", value: "America/Denver" },
|
|
1366
|
+
{ label: "Pacific Time", value: "America/Los_Angeles" }
|
|
1367
|
+
]
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
label: "Europe",
|
|
1371
|
+
zones: [
|
|
1372
|
+
{ label: "London", value: "Europe/London" },
|
|
1373
|
+
{ label: "Paris", value: "Europe/Paris" },
|
|
1374
|
+
{ label: "Berlin", value: "Europe/Berlin" },
|
|
1375
|
+
{ label: "Rome", value: "Europe/Rome" }
|
|
1376
|
+
]
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
label: "Asia",
|
|
1380
|
+
zones: [
|
|
1381
|
+
{ label: "Tokyo", value: "Asia/Tokyo" },
|
|
1382
|
+
{ label: "Shanghai", value: "Asia/Shanghai" },
|
|
1383
|
+
{ label: "Mumbai", value: "Asia/Kolkata" },
|
|
1384
|
+
{ label: "Dubai", value: "Asia/Dubai" }
|
|
1385
|
+
]
|
|
1386
|
+
}
|
|
1387
|
+
];
|
|
1388
|
+
function findTimeZone(groups) {
|
|
1389
|
+
try {
|
|
1390
|
+
const detected = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1391
|
+
for (const group of groups) {
|
|
1392
|
+
for (const zone of group.zones) {
|
|
1393
|
+
if (zone.value === detected) {
|
|
1394
|
+
return detected;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
return "UTC";
|
|
1399
|
+
} catch (e) {
|
|
1400
|
+
return "UTC";
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
// src/utils/validation.ts
|
|
1405
|
+
function validatePhoneNumber(phone) {
|
|
1406
|
+
if (!phone) {
|
|
1407
|
+
return { isValid: false, error: "Phone number is required" };
|
|
1408
|
+
}
|
|
1409
|
+
const cleaned = phone.replace(/\D/g, "");
|
|
1410
|
+
if (cleaned.length < 8) {
|
|
1411
|
+
return { isValid: false, error: "Phone number is too short" };
|
|
1412
|
+
}
|
|
1413
|
+
if (cleaned.length > 15) {
|
|
1414
|
+
return { isValid: false, error: "Phone number is too long" };
|
|
1415
|
+
}
|
|
1416
|
+
return { isValid: true };
|
|
1417
|
+
}
|
|
1418
|
+
function validateEmail(email) {
|
|
1419
|
+
if (!email) {
|
|
1420
|
+
return { isValid: false, error: "Email is required" };
|
|
1421
|
+
}
|
|
1422
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1423
|
+
if (!emailRegex.test(email)) {
|
|
1424
|
+
return { isValid: false, error: "Please enter a valid email address" };
|
|
1425
|
+
}
|
|
1426
|
+
return { isValid: true };
|
|
1427
|
+
}
|
|
1428
|
+
function validateVerificationCode(code) {
|
|
1429
|
+
if (!code) {
|
|
1430
|
+
return { isValid: false, error: "Verification code is required" };
|
|
1431
|
+
}
|
|
1432
|
+
const cleaned = code.replace(/\D/g, "");
|
|
1433
|
+
if (cleaned.length !== 4) {
|
|
1434
|
+
return { isValid: false, error: "Please enter a 4-digit verification code" };
|
|
1435
|
+
}
|
|
1436
|
+
return { isValid: true };
|
|
1437
|
+
}
|
|
1438
|
+
function validateRequired(value, fieldName = "This field") {
|
|
1439
|
+
if (value === null || value === void 0 || value === "") {
|
|
1440
|
+
return { isValid: false, error: `${fieldName} is required` };
|
|
1441
|
+
}
|
|
1442
|
+
return { isValid: true };
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
// src/index.ts
|
|
1446
|
+
init_config();
|
|
1447
|
+
|
|
1448
|
+
// src/stores/business.ts
|
|
1449
|
+
init_config();
|
|
1450
|
+
var businessStore = nanostores.deepMap({
|
|
1451
|
+
data: null,
|
|
1452
|
+
loading: false,
|
|
1453
|
+
error: null,
|
|
1454
|
+
initialized: false
|
|
1455
|
+
});
|
|
1456
|
+
var selectedMarket = nanostores.computed(businessStore, (state) => {
|
|
1457
|
+
if (!state.data?.configs?.markets) return null;
|
|
1458
|
+
const markets2 = state.data.configs.markets;
|
|
1459
|
+
return markets2.find((m) => m.id === "us") || markets2[0] || null;
|
|
1460
|
+
});
|
|
1461
|
+
nanostores.computed(selectedMarket, (market) => {
|
|
1462
|
+
return market?.currency || "USD";
|
|
1463
|
+
});
|
|
1464
|
+
nanostores.computed(selectedMarket, (market) => {
|
|
1465
|
+
return getCurrencySymbol(market?.currency || "USD");
|
|
1466
|
+
});
|
|
1467
|
+
nanostores.computed(businessStore, (state) => {
|
|
1468
|
+
if (!state.data?.configs?.markets) return [];
|
|
1469
|
+
return state.data.configs.markets;
|
|
1470
|
+
});
|
|
1471
|
+
nanostores.computed(businessStore, (state) => {
|
|
1472
|
+
if (!state.data?.configs?.zones) return [];
|
|
1473
|
+
return state.data.configs.zones;
|
|
1474
|
+
});
|
|
1475
|
+
var paymentMethods = nanostores.computed(selectedMarket, (market) => {
|
|
1476
|
+
if (!market) return ["CASH"];
|
|
1477
|
+
const methods = market.paymentMethods || [];
|
|
1478
|
+
return methods.map((pm) => pm.method || pm);
|
|
1479
|
+
});
|
|
1480
|
+
nanostores.computed(businessStore, (state) => {
|
|
1481
|
+
if (!state.data?.configs) return { provider: null, enabled: false };
|
|
1482
|
+
const provider = state.data.configs.paymentProvider || null;
|
|
1483
|
+
const hasCreditCard = paymentMethods.get().includes("CREDIT_CARD");
|
|
1484
|
+
return {
|
|
1485
|
+
provider,
|
|
1486
|
+
enabled: hasCreditCard && !!provider
|
|
1487
|
+
};
|
|
1488
|
+
});
|
|
1489
|
+
nanostores.computed(businessStore, (state) => {
|
|
1490
|
+
return state.data?.configs?.orderBlocks || [];
|
|
1491
|
+
});
|
|
1492
|
+
nanostores.computed(businessStore, (state) => {
|
|
1493
|
+
return state.data?.configs?.reservationBlocks || [];
|
|
1494
|
+
});
|
|
1495
|
+
var businessActions = {
|
|
1496
|
+
// Initialize business data - SINGLE API CALL for entire app
|
|
1497
|
+
async init() {
|
|
1498
|
+
const state = businessStore.get();
|
|
1499
|
+
if (state.initialized && state.data) {
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
try {
|
|
1503
|
+
businessStore.setKey("loading", true);
|
|
1504
|
+
businessStore.setKey("error", null);
|
|
1505
|
+
const result = await getBusinessConfig(exports.BUSINESS_ID);
|
|
1506
|
+
if (result.success) {
|
|
1507
|
+
businessStore.setKey("data", result.data);
|
|
1508
|
+
businessStore.setKey("initialized", true);
|
|
1509
|
+
} else {
|
|
1510
|
+
throw new Error(result.error || "Failed to load business configuration");
|
|
1511
|
+
}
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
businessStore.setKey("error", error.message);
|
|
1514
|
+
console.error("Business store initialization failed:", error);
|
|
1515
|
+
} finally {
|
|
1516
|
+
businessStore.setKey("loading", false);
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
// Reset store (useful for testing)
|
|
1520
|
+
reset() {
|
|
1521
|
+
businessStore.setKey("data", null);
|
|
1522
|
+
businessStore.setKey("loading", false);
|
|
1523
|
+
businessStore.setKey("error", null);
|
|
1524
|
+
businessStore.setKey("initialized", false);
|
|
1525
|
+
},
|
|
1526
|
+
// Get business data (with auto-init)
|
|
1527
|
+
async getBusiness() {
|
|
1528
|
+
const state = businessStore.get();
|
|
1529
|
+
if (!state.initialized || !state.data) {
|
|
1530
|
+
await this.init();
|
|
1531
|
+
}
|
|
1532
|
+
return businessStore.get().data;
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
if (typeof window !== "undefined" && exports.BUSINESS_ID) {
|
|
1536
|
+
businessActions.init().catch(console.error);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
// src/index.ts
|
|
1540
|
+
var SDK_VERSION = "0.1.2";
|
|
1541
|
+
var SUPPORTED_FRAMEWORKS = ["astro", "react", "vue", "svelte", "vanilla"];
|
|
1542
|
+
function initArky(config) {
|
|
1543
|
+
if (!config.apiUrl) {
|
|
1544
|
+
throw new Error("apiUrl is required");
|
|
1545
|
+
}
|
|
1546
|
+
if (!config.businessId) {
|
|
1547
|
+
throw new Error("businessId is required");
|
|
1548
|
+
}
|
|
1549
|
+
setGlobalConfig(config);
|
|
1550
|
+
if (typeof window !== "undefined") {
|
|
1551
|
+
businessActions.init().catch(console.error);
|
|
1552
|
+
}
|
|
1553
|
+
return config;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
exports.ERROR_CODES = ERROR_CODES;
|
|
1557
|
+
exports.ERROR_CONSTANTS = ERROR_CONSTANTS;
|
|
1558
|
+
exports.PaymentMethod = PaymentMethod;
|
|
1559
|
+
exports.SDK_VERSION = SDK_VERSION;
|
|
1560
|
+
exports.SUPPORTED_FRAMEWORKS = SUPPORTED_FRAMEWORKS;
|
|
1561
|
+
exports.categorify = categorify;
|
|
1562
|
+
exports.cmsApi = cmsApi;
|
|
1563
|
+
exports.convertServerErrorToRequestError = convertServerErrorToRequestError;
|
|
1564
|
+
exports.convertToMajor = convertToMajor;
|
|
1565
|
+
exports.convertToMinor = convertToMinor;
|
|
1566
|
+
exports.createPaymentForCheckout = createPaymentForCheckout;
|
|
1567
|
+
exports.errors = errors;
|
|
1568
|
+
exports.eshopApi = eshopApi;
|
|
1569
|
+
exports.extractBlockValues = extractBlockValues;
|
|
1570
|
+
exports.fetchSvgContent = fetchSvgContent;
|
|
1571
|
+
exports.findTimeZone = findTimeZone;
|
|
1572
|
+
exports.formatBlockValue = formatBlockValue;
|
|
1573
|
+
exports.formatCurrencyAmount = formatCurrencyAmount;
|
|
1574
|
+
exports.formatDate = formatDate;
|
|
1575
|
+
exports.formatMinor = formatMinor;
|
|
1576
|
+
exports.formatPayment = formatPayment;
|
|
1577
|
+
exports.getBlockFromArray = getBlockFromArray;
|
|
1578
|
+
exports.getBlockLabel = getBlockLabel;
|
|
1579
|
+
exports.getBlockObjectValues = getBlockObjectValues;
|
|
1580
|
+
exports.getBlockTextValue = getBlockTextValue;
|
|
1581
|
+
exports.getBlockValue = getBlockValue;
|
|
1582
|
+
exports.getBlockValues = getBlockValues;
|
|
1583
|
+
exports.getBusinessConfig = getBusinessConfig;
|
|
1584
|
+
exports.getCurrencyFromMarket = getCurrencyFromMarket;
|
|
1585
|
+
exports.getErrorMessage = getErrorMessage;
|
|
1586
|
+
exports.getGalleryThumbnail = getGalleryThumbnail;
|
|
1587
|
+
exports.getGlobalConfig = getGlobalConfig;
|
|
1588
|
+
exports.getGuestToken = getGuestToken;
|
|
1589
|
+
exports.getImageUrl = getImageUrl;
|
|
1590
|
+
exports.getMarketPrice = getMarketPrice;
|
|
1591
|
+
exports.getPriceAmount = getPriceAmount;
|
|
1592
|
+
exports.getSvgContentForAstro = getSvgContentForAstro;
|
|
1593
|
+
exports.getSymbol = getSymbol;
|
|
1594
|
+
exports.httpClient = http_default;
|
|
1595
|
+
exports.humanize = humanize;
|
|
1596
|
+
exports.initArky = initArky;
|
|
1597
|
+
exports.injectSvgIntoElement = injectSvgIntoElement;
|
|
1598
|
+
exports.isErrorCode = isErrorCode;
|
|
1599
|
+
exports.newsletterApi = newsletterApi;
|
|
1600
|
+
exports.prepareBlocksForSubmission = prepareBlocksForSubmission;
|
|
1601
|
+
exports.reservationApi = reservationApi;
|
|
1602
|
+
exports.setGlobalConfig = setGlobalConfig;
|
|
1603
|
+
exports.slugify = slugify;
|
|
1604
|
+
exports.thumbnailUrl = thumbnailUrl;
|
|
1605
|
+
exports.transformErrors = transformErrors;
|
|
1606
|
+
exports.translateMap = translateMap;
|
|
1607
|
+
exports.tzGroups = tzGroups;
|
|
1608
|
+
exports.updateProfilePhone = updateProfilePhone;
|
|
1609
|
+
exports.validateEmail = validateEmail;
|
|
1610
|
+
exports.validatePhoneNumber = validatePhoneNumber;
|
|
1611
|
+
exports.validateRequired = validateRequired;
|
|
1612
|
+
exports.validateVerificationCode = validateVerificationCode;
|
|
1613
|
+
exports.verifyPhoneCode = verifyPhoneCode;
|
|
1614
|
+
//# sourceMappingURL=index.cjs.map
|
|
1615
|
+
//# sourceMappingURL=index.cjs.map
|