arky-sdk 0.7.133 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -211
- package/dist/{admin-id0wkGff.d.ts → admin-CEVBErl_.d.ts} +60 -1
- package/dist/{admin-DlDViCdY.d.cts → admin-DCe3PEOB.d.cts} +60 -1
- package/dist/admin.cjs +9 -1
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +1 -1
- package/dist/admin.d.ts +1 -1
- package/dist/admin.js +9 -1
- package/dist/admin.js.map +1 -1
- package/dist/index.cjs +9 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/storefront-store.cjs +250 -205
- package/dist/storefront-store.cjs.map +1 -1
- package/dist/storefront-store.d.cts +2 -2
- package/dist/storefront-store.d.ts +2 -2
- package/dist/storefront-store.js +250 -205
- package/dist/storefront-store.js.map +1 -1
- package/dist/storefront.cjs +250 -205
- package/dist/storefront.cjs.map +1 -1
- package/dist/storefront.d.cts +103 -96
- package/dist/storefront.d.ts +103 -96
- package/dist/storefront.js +250 -205
- package/dist/storefront.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +16 -12
- package/dist/types.d.ts +16 -12
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/scripts/smoke-store.mjs +21 -5
|
@@ -1606,15 +1606,15 @@ function formSchemaToBlock(field) {
|
|
|
1606
1606
|
value: getFormBlockValue(field)
|
|
1607
1607
|
};
|
|
1608
1608
|
}
|
|
1609
|
-
function
|
|
1609
|
+
function formatServiceTime(ts, tz) {
|
|
1610
1610
|
return new Date(ts * 1e3).toLocaleTimeString([], {
|
|
1611
1611
|
hour: "2-digit",
|
|
1612
1612
|
minute: "2-digit",
|
|
1613
1613
|
timeZone: tz
|
|
1614
1614
|
});
|
|
1615
1615
|
}
|
|
1616
|
-
function
|
|
1617
|
-
return `${
|
|
1616
|
+
function formatServiceSlotTime(from, to, tz) {
|
|
1617
|
+
return `${formatServiceTime(from, tz)} - ${formatServiceTime(to, tz)}`;
|
|
1618
1618
|
}
|
|
1619
1619
|
function getSlotsForDate(availability, dateStr, providerId) {
|
|
1620
1620
|
if (!availability) return [];
|
|
@@ -1637,8 +1637,8 @@ function hasAvailableSlotsForDate(availability, dateStr, providerId) {
|
|
|
1637
1637
|
return !!day?.slots.some((slot) => slot.spots > 0);
|
|
1638
1638
|
});
|
|
1639
1639
|
}
|
|
1640
|
-
var
|
|
1641
|
-
function
|
|
1640
|
+
var SERVICE_WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
1641
|
+
function createServiceInitialState() {
|
|
1642
1642
|
return {
|
|
1643
1643
|
service: null,
|
|
1644
1644
|
availability: null,
|
|
@@ -1655,7 +1655,7 @@ function createServiceOrderInitialState() {
|
|
|
1655
1655
|
timezone: typeof window !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : "UTC",
|
|
1656
1656
|
tzGroups: {},
|
|
1657
1657
|
loading: false,
|
|
1658
|
-
weekdays:
|
|
1658
|
+
weekdays: SERVICE_WEEKDAYS,
|
|
1659
1659
|
quote: null,
|
|
1660
1660
|
fetchingQuote: false,
|
|
1661
1661
|
quoteError: null,
|
|
@@ -1722,7 +1722,6 @@ function createArkyStore(config) {
|
|
|
1722
1722
|
item_count: count
|
|
1723
1723
|
}));
|
|
1724
1724
|
const cms_state = nanostores.map({
|
|
1725
|
-
website_node: null,
|
|
1726
1725
|
nodes: {},
|
|
1727
1726
|
forms: {},
|
|
1728
1727
|
loading: false,
|
|
@@ -1742,16 +1741,15 @@ function createArkyStore(config) {
|
|
|
1742
1741
|
loading_availability: false,
|
|
1743
1742
|
error: null
|
|
1744
1743
|
});
|
|
1745
|
-
const
|
|
1746
|
-
const
|
|
1747
|
-
const
|
|
1744
|
+
const service_state = nanostores.map(createServiceInitialState());
|
|
1745
|
+
const service_form_node = nanostores.atom(null);
|
|
1746
|
+
const service_form_blocks = nanostores.computed(service_form_node, (node) => node?.blocks || []);
|
|
1748
1747
|
client.onAuthStateChanged((value) => session.set(value));
|
|
1749
|
-
|
|
1750
|
-
currency.subscribe((value) => service_order_state.setKey("currency", value));
|
|
1748
|
+
currency.subscribe((value) => service_state.setKey("currency", value));
|
|
1751
1749
|
session.subscribe((value) => {
|
|
1752
1750
|
const methods = value?.market?.payment_methods || [];
|
|
1753
|
-
if (methods.length &&
|
|
1754
|
-
|
|
1751
|
+
if (methods.length && service_state.get().availablePaymentMethods.length === 0) {
|
|
1752
|
+
service_state.setKey("availablePaymentMethods", methods);
|
|
1755
1753
|
}
|
|
1756
1754
|
});
|
|
1757
1755
|
function currentMarketKey() {
|
|
@@ -1763,6 +1761,15 @@ function createArkyStore(config) {
|
|
|
1763
1761
|
function currentCurrency() {
|
|
1764
1762
|
return currency.get() || market.get()?.currency || null;
|
|
1765
1763
|
}
|
|
1764
|
+
function marketForLocale(value) {
|
|
1765
|
+
return config.marketForLocale?.(value) || null;
|
|
1766
|
+
}
|
|
1767
|
+
async function ensureSession() {
|
|
1768
|
+
const current = session.get();
|
|
1769
|
+
const marketKey = currentMarketKey();
|
|
1770
|
+
if (current && (!marketKey || current.market?.key === marketKey)) return current;
|
|
1771
|
+
return identify({ market: marketKey });
|
|
1772
|
+
}
|
|
1766
1773
|
async function identify(params = {}) {
|
|
1767
1774
|
if (params.market) setMarket(params.market);
|
|
1768
1775
|
const result = await client.identify({ ...params, market: params.market || currentMarketKey() });
|
|
@@ -1773,15 +1780,24 @@ function createArkyStore(config) {
|
|
|
1773
1780
|
market_key.set(key);
|
|
1774
1781
|
client.setMarket(key);
|
|
1775
1782
|
}
|
|
1776
|
-
function setLocale(value) {
|
|
1783
|
+
function setLocale(value, options = {}) {
|
|
1777
1784
|
locale.set(value);
|
|
1778
1785
|
client.setLocale(value);
|
|
1786
|
+
const nextMarket = options.market || marketForLocale(value);
|
|
1787
|
+
if (nextMarket) setMarket(nextMarket);
|
|
1788
|
+
}
|
|
1789
|
+
function setContext(context) {
|
|
1790
|
+
if (context.locale) {
|
|
1791
|
+
setLocale(context.locale, { market: context.market });
|
|
1792
|
+
return;
|
|
1793
|
+
}
|
|
1794
|
+
if (context.market) setMarket(context.market);
|
|
1779
1795
|
}
|
|
1780
1796
|
async function ensureCart() {
|
|
1781
1797
|
cart_status.setKey("loading", true);
|
|
1782
1798
|
cart_status.setKey("error", null);
|
|
1783
1799
|
try {
|
|
1784
|
-
await
|
|
1800
|
+
await ensureSession();
|
|
1785
1801
|
const response = await client.cart.refresh({ market: currentMarketKey() });
|
|
1786
1802
|
await hydrateCart(response);
|
|
1787
1803
|
return response;
|
|
@@ -2023,8 +2039,8 @@ function createArkyStore(config) {
|
|
|
2023
2039
|
cart_status.setKey("processing_checkout", false);
|
|
2024
2040
|
}
|
|
2025
2041
|
}
|
|
2026
|
-
function
|
|
2027
|
-
const state =
|
|
2042
|
+
function serviceCalendar() {
|
|
2043
|
+
const state = service_state.get();
|
|
2028
2044
|
const { currentMonth, selectedDate, startDate, endDate, availability, selectedProviderId } = state;
|
|
2029
2045
|
const year = currentMonth.getFullYear();
|
|
2030
2046
|
const monthIndex = currentMonth.getMonth();
|
|
@@ -2078,8 +2094,8 @@ function createArkyStore(config) {
|
|
|
2078
2094
|
}
|
|
2079
2095
|
return cells;
|
|
2080
2096
|
}
|
|
2081
|
-
function
|
|
2082
|
-
const state =
|
|
2097
|
+
function computeServiceSlots(dateStr) {
|
|
2098
|
+
const state = service_state.get();
|
|
2083
2099
|
const { availability, selectedProviderId, timezone, service } = state;
|
|
2084
2100
|
return getSlotsForDate(availability, dateStr, selectedProviderId).map((slot, index) => ({
|
|
2085
2101
|
id: `${service?.id || "service"}-${slot.from}-${index}`,
|
|
@@ -2087,7 +2103,7 @@ function createArkyStore(config) {
|
|
|
2087
2103
|
providerId: slot.providerId,
|
|
2088
2104
|
from: slot.from,
|
|
2089
2105
|
to: slot.to,
|
|
2090
|
-
timeText:
|
|
2106
|
+
timeText: formatServiceSlotTime(slot.from, slot.to, timezone),
|
|
2091
2107
|
dateText: new Date(slot.from * 1e3).toLocaleDateString([], {
|
|
2092
2108
|
weekday: "short",
|
|
2093
2109
|
month: "short",
|
|
@@ -2120,63 +2136,63 @@ function createArkyStore(config) {
|
|
|
2120
2136
|
serviceName: item.service_name || "",
|
|
2121
2137
|
date: item.date_text || "",
|
|
2122
2138
|
dateText: item.date_text || "",
|
|
2123
|
-
timeText: item.time_text ||
|
|
2139
|
+
timeText: item.time_text || formatServiceSlotTime(item.from, item.to, service_state.get().timezone),
|
|
2124
2140
|
isMultiDay: item.is_multi_day
|
|
2125
2141
|
};
|
|
2126
2142
|
}
|
|
2127
|
-
function
|
|
2143
|
+
function setServiceCartFromServiceItems(items) {
|
|
2128
2144
|
const next = items.map(fromServiceCartItem);
|
|
2129
|
-
const current =
|
|
2145
|
+
const current = service_state.get().cart;
|
|
2130
2146
|
if (JSON.stringify(current) !== JSON.stringify(next)) {
|
|
2131
|
-
|
|
2147
|
+
service_state.setKey("cart", next);
|
|
2132
2148
|
}
|
|
2133
2149
|
}
|
|
2134
|
-
async function
|
|
2150
|
+
async function syncServiceCart(slots) {
|
|
2135
2151
|
try {
|
|
2136
2152
|
return await syncCart({
|
|
2137
2153
|
product_items: product_items.get(),
|
|
2138
2154
|
service_items: slots.map(toServiceCartItem)
|
|
2139
2155
|
});
|
|
2140
2156
|
} catch (error) {
|
|
2141
|
-
|
|
2157
|
+
service_state.setKey("quoteError", readErrorMessage(error, "Failed to sync service cart."));
|
|
2142
2158
|
throw error;
|
|
2143
2159
|
}
|
|
2144
2160
|
}
|
|
2145
|
-
function
|
|
2146
|
-
const state =
|
|
2161
|
+
function serviceCurrentStepName() {
|
|
2162
|
+
const state = service_state.get();
|
|
2147
2163
|
if (!state.service) return "";
|
|
2148
2164
|
if (!state.selectedSlot || !state.dateTimeConfirmed) return "datetime";
|
|
2149
2165
|
return "review";
|
|
2150
2166
|
}
|
|
2151
|
-
const
|
|
2152
|
-
const
|
|
2153
|
-
const step =
|
|
2167
|
+
const service_current_step_name = nanostores.computed(service_state, serviceCurrentStepName);
|
|
2168
|
+
const service_can_proceed = nanostores.computed(service_state, (state) => {
|
|
2169
|
+
const step = serviceCurrentStepName();
|
|
2154
2170
|
if (step === "datetime") {
|
|
2155
2171
|
return state.isMultiDay ? !!(state.startDate && state.endDate && state.selectedSlot) : !!(state.selectedDate && state.selectedSlot);
|
|
2156
2172
|
}
|
|
2157
2173
|
if (step === "review") return true;
|
|
2158
2174
|
return false;
|
|
2159
2175
|
});
|
|
2160
|
-
const
|
|
2161
|
-
|
|
2176
|
+
const service_month_year = nanostores.computed(
|
|
2177
|
+
service_state,
|
|
2162
2178
|
(state) => state.currentMonth.toLocaleString(void 0, { month: "long", year: "numeric" })
|
|
2163
2179
|
);
|
|
2164
|
-
const
|
|
2180
|
+
const service_chain_start = nanostores.computed(service_state, (state) => {
|
|
2165
2181
|
if (!state.cart.length) return null;
|
|
2166
2182
|
return Math.max(...state.cart.map((slot) => slot.to));
|
|
2167
2183
|
});
|
|
2168
|
-
const
|
|
2169
|
-
const
|
|
2184
|
+
const service_total_steps = nanostores.computed(service_state, (state) => state.service ? 2 : 0);
|
|
2185
|
+
const service_steps = nanostores.computed(service_state, () => ({
|
|
2170
2186
|
1: { name: "datetime" },
|
|
2171
2187
|
2: { name: "review" }
|
|
2172
2188
|
}));
|
|
2173
|
-
const
|
|
2189
|
+
const service_current_step = nanostores.computed([service_current_step_name, service_steps], (name, steps) => {
|
|
2174
2190
|
for (const [idx, step] of Object.entries(steps)) {
|
|
2175
2191
|
if (step.name === name) return Number(idx);
|
|
2176
2192
|
}
|
|
2177
2193
|
return 1;
|
|
2178
2194
|
});
|
|
2179
|
-
function
|
|
2195
|
+
function formatServiceDateDisplay(value) {
|
|
2180
2196
|
if (!value) return "";
|
|
2181
2197
|
return new Date(value).toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2182
2198
|
}
|
|
@@ -2193,37 +2209,37 @@ function createArkyStore(config) {
|
|
|
2193
2209
|
}
|
|
2194
2210
|
return providers[0];
|
|
2195
2211
|
}
|
|
2196
|
-
async function
|
|
2212
|
+
async function loadServiceForm() {
|
|
2197
2213
|
try {
|
|
2198
2214
|
const form = await loadForm({ key: "order-form" });
|
|
2199
2215
|
const blocks = (form.schema || []).map(formSchemaToBlock);
|
|
2200
|
-
|
|
2216
|
+
service_form_node.set({ blocks });
|
|
2201
2217
|
return blocks;
|
|
2202
2218
|
} catch {
|
|
2203
|
-
|
|
2219
|
+
service_form_node.set({ blocks: [] });
|
|
2204
2220
|
return [];
|
|
2205
2221
|
}
|
|
2206
2222
|
}
|
|
2207
|
-
const
|
|
2223
|
+
const service_controller = {
|
|
2208
2224
|
async initialize() {
|
|
2209
|
-
|
|
2225
|
+
service_state.setKey("tzGroups", normalizeTimezoneGroups(client.utils.tzGroups));
|
|
2210
2226
|
await ensureCart();
|
|
2211
|
-
|
|
2227
|
+
setServiceCartFromServiceItems(service_items.get());
|
|
2212
2228
|
const methods = session.get()?.market?.payment_methods || [];
|
|
2213
|
-
if (methods.length)
|
|
2214
|
-
await
|
|
2229
|
+
if (methods.length) service_state.setKey("availablePaymentMethods", methods);
|
|
2230
|
+
await loadServiceForm();
|
|
2215
2231
|
},
|
|
2216
2232
|
setTimezone(tz) {
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
const state =
|
|
2233
|
+
service_state.setKey("timezone", tz);
|
|
2234
|
+
service_state.setKey("calendar", serviceCalendar());
|
|
2235
|
+
const state = service_state.get();
|
|
2220
2236
|
if (state.selectedDate) {
|
|
2221
|
-
|
|
2222
|
-
|
|
2237
|
+
service_state.setKey("slots", computeServiceSlots(state.selectedDate));
|
|
2238
|
+
service_state.setKey("selectedSlot", null);
|
|
2223
2239
|
}
|
|
2224
2240
|
},
|
|
2225
|
-
async
|
|
2226
|
-
|
|
2241
|
+
async select(service) {
|
|
2242
|
+
service_state.setKey("loading", true);
|
|
2227
2243
|
try {
|
|
2228
2244
|
const isMultiDayBlock = service.blocks?.find((block) => block.key === "isMultiDay");
|
|
2229
2245
|
const blockValue = isMultiDayBlock?.value;
|
|
@@ -2236,8 +2252,8 @@ function createArkyStore(config) {
|
|
|
2236
2252
|
const providerResults = await Promise.all(
|
|
2237
2253
|
providerIds.map((id) => client.eshop.provider.get({ id }).catch(() => null))
|
|
2238
2254
|
);
|
|
2239
|
-
|
|
2240
|
-
...
|
|
2255
|
+
service_state.set({
|
|
2256
|
+
...service_state.get(),
|
|
2241
2257
|
service: fullService,
|
|
2242
2258
|
providers: providerResults.filter((provider) => provider !== null),
|
|
2243
2259
|
selectedProviderId: null,
|
|
@@ -2251,18 +2267,18 @@ function createArkyStore(config) {
|
|
|
2251
2267
|
loading: false,
|
|
2252
2268
|
isMultiDay
|
|
2253
2269
|
});
|
|
2254
|
-
await
|
|
2270
|
+
await service_controller.loadMonth();
|
|
2255
2271
|
} catch (error) {
|
|
2256
|
-
|
|
2272
|
+
service_state.setKey("loading", false);
|
|
2257
2273
|
throw error;
|
|
2258
2274
|
}
|
|
2259
2275
|
},
|
|
2260
2276
|
async loadMonth() {
|
|
2261
|
-
const state =
|
|
2277
|
+
const state = service_state.get();
|
|
2262
2278
|
if (!state.service) return;
|
|
2263
|
-
|
|
2279
|
+
service_state.setKey("loading", true);
|
|
2264
2280
|
try {
|
|
2265
|
-
const chainedStart =
|
|
2281
|
+
const chainedStart = service_chain_start.get();
|
|
2266
2282
|
let from;
|
|
2267
2283
|
let to;
|
|
2268
2284
|
if (chainedStart) {
|
|
@@ -2278,25 +2294,25 @@ function createArkyStore(config) {
|
|
|
2278
2294
|
from,
|
|
2279
2295
|
to
|
|
2280
2296
|
});
|
|
2281
|
-
|
|
2282
|
-
|
|
2297
|
+
service_state.setKey("availability", availability);
|
|
2298
|
+
service_state.setKey("calendar", serviceCalendar());
|
|
2283
2299
|
} finally {
|
|
2284
|
-
|
|
2300
|
+
service_state.setKey("loading", false);
|
|
2285
2301
|
}
|
|
2286
2302
|
},
|
|
2287
2303
|
prevMonth() {
|
|
2288
|
-
const { currentMonth } =
|
|
2289
|
-
|
|
2290
|
-
void
|
|
2304
|
+
const { currentMonth } = service_state.get();
|
|
2305
|
+
service_state.setKey("currentMonth", new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1));
|
|
2306
|
+
void service_controller.loadMonth();
|
|
2291
2307
|
},
|
|
2292
2308
|
nextMonth() {
|
|
2293
|
-
const { currentMonth } =
|
|
2294
|
-
|
|
2295
|
-
void
|
|
2309
|
+
const { currentMonth } = service_state.get();
|
|
2310
|
+
service_state.setKey("currentMonth", new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1));
|
|
2311
|
+
void service_controller.loadMonth();
|
|
2296
2312
|
},
|
|
2297
2313
|
selectProvider(providerId) {
|
|
2298
|
-
|
|
2299
|
-
...
|
|
2314
|
+
service_state.set({
|
|
2315
|
+
...service_state.get(),
|
|
2300
2316
|
selectedProviderId: providerId,
|
|
2301
2317
|
selectedDate: null,
|
|
2302
2318
|
startDate: null,
|
|
@@ -2304,45 +2320,45 @@ function createArkyStore(config) {
|
|
|
2304
2320
|
slots: [],
|
|
2305
2321
|
selectedSlot: null
|
|
2306
2322
|
});
|
|
2307
|
-
void
|
|
2323
|
+
void service_controller.loadMonth();
|
|
2308
2324
|
},
|
|
2309
2325
|
selectDate(cell) {
|
|
2310
2326
|
if (cell.blank || !cell.available) return;
|
|
2311
|
-
|
|
2312
|
-
const state =
|
|
2327
|
+
service_state.setKey("dateTimeConfirmed", false);
|
|
2328
|
+
const state = service_state.get();
|
|
2313
2329
|
if (state.isMultiDay) {
|
|
2314
2330
|
if (!state.startDate) {
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2331
|
+
service_state.setKey("startDate", cell.iso);
|
|
2332
|
+
service_state.setKey("selectedDate", cell.iso);
|
|
2333
|
+
service_state.setKey("endDate", null);
|
|
2334
|
+
service_state.setKey("selectedSlot", null);
|
|
2319
2335
|
} else if (!state.endDate) {
|
|
2320
2336
|
if (cell.date.getTime() < new Date(state.startDate).getTime()) {
|
|
2321
|
-
|
|
2322
|
-
|
|
2337
|
+
service_state.setKey("startDate", cell.iso);
|
|
2338
|
+
service_state.setKey("endDate", state.startDate);
|
|
2323
2339
|
} else {
|
|
2324
|
-
|
|
2340
|
+
service_state.setKey("endDate", cell.iso);
|
|
2325
2341
|
}
|
|
2326
|
-
|
|
2342
|
+
service_controller.createMultiDaySlots();
|
|
2327
2343
|
} else {
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2344
|
+
service_state.setKey("startDate", cell.iso);
|
|
2345
|
+
service_state.setKey("selectedDate", cell.iso);
|
|
2346
|
+
service_state.setKey("endDate", null);
|
|
2347
|
+
service_state.setKey("selectedSlot", null);
|
|
2332
2348
|
}
|
|
2333
|
-
|
|
2349
|
+
service_controller.updateCalendar();
|
|
2334
2350
|
} else {
|
|
2335
|
-
|
|
2351
|
+
service_state.set({
|
|
2336
2352
|
...state,
|
|
2337
2353
|
selectedDate: cell.iso,
|
|
2338
|
-
slots:
|
|
2354
|
+
slots: computeServiceSlots(cell.iso),
|
|
2339
2355
|
selectedSlot: null
|
|
2340
2356
|
});
|
|
2341
|
-
|
|
2357
|
+
service_state.setKey("calendar", serviceCalendar());
|
|
2342
2358
|
}
|
|
2343
2359
|
},
|
|
2344
2360
|
createMultiDaySlots() {
|
|
2345
|
-
const state =
|
|
2361
|
+
const state = service_state.get();
|
|
2346
2362
|
if (!state.startDate || !state.endDate || !state.availability) return;
|
|
2347
2363
|
const slots = [];
|
|
2348
2364
|
for (let day = new Date(state.startDate); day <= new Date(state.endDate); day.setDate(day.getDate() + 1)) {
|
|
@@ -2354,7 +2370,7 @@ function createArkyStore(config) {
|
|
|
2354
2370
|
providerId: slot.providerId,
|
|
2355
2371
|
from: slot.from,
|
|
2356
2372
|
to: slot.to,
|
|
2357
|
-
timeText:
|
|
2373
|
+
timeText: formatServiceSlotTime(slot.from, slot.to, state.timezone),
|
|
2358
2374
|
dateText: new Date(slot.from * 1e3).toLocaleDateString([], {
|
|
2359
2375
|
weekday: "short",
|
|
2360
2376
|
month: "short",
|
|
@@ -2365,34 +2381,34 @@ function createArkyStore(config) {
|
|
|
2365
2381
|
});
|
|
2366
2382
|
}
|
|
2367
2383
|
}
|
|
2368
|
-
|
|
2369
|
-
|
|
2384
|
+
service_state.setKey("slots", slots);
|
|
2385
|
+
service_state.setKey("selectedSlot", slots.length === 1 ? slots[0] : null);
|
|
2370
2386
|
},
|
|
2371
2387
|
selectTimeSlot(slot) {
|
|
2372
|
-
|
|
2373
|
-
|
|
2388
|
+
service_state.setKey("dateTimeConfirmed", false);
|
|
2389
|
+
service_state.setKey("selectedSlot", slot);
|
|
2374
2390
|
},
|
|
2375
2391
|
resetDateSelection() {
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2392
|
+
service_state.setKey("selectedDate", null);
|
|
2393
|
+
service_state.setKey("startDate", null);
|
|
2394
|
+
service_state.setKey("endDate", null);
|
|
2395
|
+
service_state.setKey("slots", []);
|
|
2396
|
+
service_state.setKey("selectedSlot", null);
|
|
2397
|
+
service_state.setKey("dateTimeConfirmed", false);
|
|
2382
2398
|
},
|
|
2383
2399
|
updateCalendar() {
|
|
2384
|
-
|
|
2400
|
+
service_state.setKey("calendar", serviceCalendar());
|
|
2385
2401
|
},
|
|
2386
2402
|
findFirstAvailable() {
|
|
2387
|
-
for (const day of
|
|
2403
|
+
for (const day of service_state.get().calendar) {
|
|
2388
2404
|
if (!day.blank && day.available) {
|
|
2389
|
-
|
|
2405
|
+
service_controller.selectDate(day);
|
|
2390
2406
|
return;
|
|
2391
2407
|
}
|
|
2392
2408
|
}
|
|
2393
2409
|
},
|
|
2394
2410
|
async addToCart() {
|
|
2395
|
-
const state =
|
|
2411
|
+
const state = service_state.get();
|
|
2396
2412
|
const serviceBlocks = state.service?.forms || [];
|
|
2397
2413
|
const enrich = (slot) => ({
|
|
2398
2414
|
...slot,
|
|
@@ -2403,7 +2419,7 @@ function createArkyStore(config) {
|
|
|
2403
2419
|
const selected = state.isMultiDay && state.slots.length > 0 ? state.slots.map(enrich) : state.selectedSlot ? [enrich(state.selectedSlot)] : [];
|
|
2404
2420
|
if (!selected.length) return;
|
|
2405
2421
|
const nextCart = [...state.cart, ...selected];
|
|
2406
|
-
|
|
2422
|
+
service_state.set({
|
|
2407
2423
|
...state,
|
|
2408
2424
|
cart: nextCart,
|
|
2409
2425
|
selectedDate: null,
|
|
@@ -2412,22 +2428,22 @@ function createArkyStore(config) {
|
|
|
2412
2428
|
slots: [],
|
|
2413
2429
|
selectedSlot: null
|
|
2414
2430
|
});
|
|
2415
|
-
await
|
|
2416
|
-
|
|
2431
|
+
await syncServiceCart(nextCart);
|
|
2432
|
+
service_state.setKey("calendar", serviceCalendar());
|
|
2417
2433
|
},
|
|
2418
2434
|
async removeFromCart(slotId) {
|
|
2419
|
-
const nextCart =
|
|
2420
|
-
|
|
2421
|
-
await
|
|
2435
|
+
const nextCart = service_state.get().cart.filter((slot) => slot.id !== slotId);
|
|
2436
|
+
service_state.setKey("cart", nextCart);
|
|
2437
|
+
await syncServiceCart(nextCart);
|
|
2422
2438
|
},
|
|
2423
2439
|
async clearCart() {
|
|
2424
|
-
|
|
2425
|
-
await
|
|
2440
|
+
service_state.setKey("cart", []);
|
|
2441
|
+
await syncServiceCart([]);
|
|
2426
2442
|
},
|
|
2427
2443
|
async checkout(paymentMethodId, forms = []) {
|
|
2428
|
-
const state =
|
|
2444
|
+
const state = service_state.get();
|
|
2429
2445
|
if (!state.cart.length) return { success: false, error: "Cart is empty" };
|
|
2430
|
-
|
|
2446
|
+
service_state.setKey("loading", true);
|
|
2431
2447
|
try {
|
|
2432
2448
|
const result = await checkout({
|
|
2433
2449
|
service_items: state.cart.map((slot) => ({
|
|
@@ -2438,76 +2454,78 @@ function createArkyStore(config) {
|
|
|
2438
2454
|
promo_code: state.promoCode || void 0,
|
|
2439
2455
|
forms
|
|
2440
2456
|
});
|
|
2441
|
-
|
|
2457
|
+
service_state.setKey("cartId", cart.get()?.id || null);
|
|
2442
2458
|
return { success: true, data: result };
|
|
2443
2459
|
} catch (error) {
|
|
2444
2460
|
return { success: false, error: readErrorMessage(error, "Checkout failed.") };
|
|
2445
2461
|
} finally {
|
|
2446
|
-
|
|
2462
|
+
service_state.setKey("loading", false);
|
|
2447
2463
|
}
|
|
2448
2464
|
},
|
|
2449
2465
|
async fetchQuote(paymentMethodId, promoCode) {
|
|
2450
|
-
const state =
|
|
2466
|
+
const state = service_state.get();
|
|
2451
2467
|
if (!state.cart.length) return null;
|
|
2452
|
-
|
|
2453
|
-
|
|
2468
|
+
service_state.setKey("fetchingQuote", true);
|
|
2469
|
+
service_state.setKey("quoteError", null);
|
|
2454
2470
|
try {
|
|
2455
|
-
|
|
2471
|
+
service_state.setKey("promoCode", promoCode || null);
|
|
2456
2472
|
const response = await fetchQuote({
|
|
2457
2473
|
service_items: state.cart.map(toServiceCartItem),
|
|
2458
2474
|
payment_method_id: paymentMethodId,
|
|
2459
2475
|
promo_code: promoCode || void 0
|
|
2460
2476
|
});
|
|
2461
|
-
|
|
2462
|
-
|
|
2477
|
+
service_state.setKey("cartId", cart.get()?.id || null);
|
|
2478
|
+
service_state.setKey("quote", response);
|
|
2463
2479
|
const methods = response?.payment_methods || session.get()?.market?.payment_methods || [];
|
|
2464
|
-
if (methods.length)
|
|
2480
|
+
if (methods.length) service_state.setKey("availablePaymentMethods", methods);
|
|
2465
2481
|
return response;
|
|
2466
2482
|
} catch (error) {
|
|
2467
|
-
|
|
2483
|
+
service_state.setKey("quoteError", readErrorMessage(error, "Failed to fetch quote."));
|
|
2468
2484
|
return null;
|
|
2469
2485
|
} finally {
|
|
2470
|
-
|
|
2486
|
+
service_state.setKey("fetchingQuote", false);
|
|
2471
2487
|
}
|
|
2472
2488
|
},
|
|
2473
2489
|
getProvidersList() {
|
|
2474
|
-
return
|
|
2490
|
+
return service_state.get().providers;
|
|
2475
2491
|
},
|
|
2476
2492
|
prevStep() {
|
|
2477
|
-
const current =
|
|
2493
|
+
const current = serviceCurrentStepName();
|
|
2478
2494
|
if (current === "review") {
|
|
2479
|
-
|
|
2495
|
+
service_state.setKey("dateTimeConfirmed", false);
|
|
2480
2496
|
return;
|
|
2481
2497
|
}
|
|
2482
2498
|
if (current === "datetime") {
|
|
2483
|
-
|
|
2484
|
-
|
|
2499
|
+
service_state.setKey("selectedSlot", null);
|
|
2500
|
+
service_state.setKey("dateTimeConfirmed", false);
|
|
2485
2501
|
}
|
|
2486
2502
|
},
|
|
2487
2503
|
nextStep() {
|
|
2488
|
-
if (
|
|
2489
|
-
|
|
2504
|
+
if (serviceCurrentStepName() === "datetime" && service_can_proceed.get()) {
|
|
2505
|
+
service_state.setKey("dateTimeConfirmed", true);
|
|
2490
2506
|
}
|
|
2491
2507
|
},
|
|
2492
2508
|
getServicePrice() {
|
|
2493
|
-
const state =
|
|
2509
|
+
const state = service_state.get();
|
|
2494
2510
|
if (state.quote?.total !== void 0) return String(state.quote.total);
|
|
2495
2511
|
const provider = getFirstServiceProviderEntry(state);
|
|
2496
2512
|
if (!provider?.prices) return "";
|
|
2497
2513
|
return client.utils.formatPrice(provider.prices) || "0";
|
|
2498
2514
|
},
|
|
2499
|
-
formatDateDisplay:
|
|
2515
|
+
formatDateDisplay: formatServiceDateDisplay,
|
|
2500
2516
|
serviceItemsFromSlots(slots) {
|
|
2501
2517
|
return slots.map(toServiceCartItem);
|
|
2502
2518
|
}
|
|
2503
2519
|
};
|
|
2504
|
-
service_items.subscribe((items) =>
|
|
2520
|
+
service_items.subscribe((items) => setServiceCartFromServiceItems(items));
|
|
2505
2521
|
async function loadNode(params, options) {
|
|
2506
2522
|
cms_state.setKey("loading", true);
|
|
2507
2523
|
cms_state.setKey("error", null);
|
|
2508
2524
|
try {
|
|
2509
|
-
const
|
|
2510
|
-
|
|
2525
|
+
const { locale: nextLocale, market: nextMarket, ...nodeParams } = params;
|
|
2526
|
+
setContext({ locale: nextLocale, market: nextMarket });
|
|
2527
|
+
const node = await client.cms.node.get(nodeParams, options);
|
|
2528
|
+
const key = nodeParams.key || nodeParams.id || nodeParams.slug || node.id;
|
|
2511
2529
|
cms_state.setKey("nodes", { ...cms_state.get().nodes, [key]: node });
|
|
2512
2530
|
return node;
|
|
2513
2531
|
} catch (error) {
|
|
@@ -2517,11 +2535,6 @@ function createArkyStore(config) {
|
|
|
2517
2535
|
cms_state.setKey("loading", false);
|
|
2518
2536
|
}
|
|
2519
2537
|
}
|
|
2520
|
-
async function loadWebsiteNode(options) {
|
|
2521
|
-
const node = await loadNode({ key: "website" }, options);
|
|
2522
|
-
cms_state.setKey("website_node", node);
|
|
2523
|
-
return node;
|
|
2524
|
-
}
|
|
2525
2538
|
async function loadForm(params, options) {
|
|
2526
2539
|
cms_state.setKey("loading", true);
|
|
2527
2540
|
cms_state.setKey("error", null);
|
|
@@ -2603,22 +2616,25 @@ function createArkyStore(config) {
|
|
|
2603
2616
|
eshop_state.setKey("loading_availability", false);
|
|
2604
2617
|
}
|
|
2605
2618
|
}
|
|
2606
|
-
async function
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
await identify({ market: currentMarketKey() });
|
|
2619
|
+
async function setup(options = {}) {
|
|
2620
|
+
setContext(options);
|
|
2621
|
+
const shouldIdentify = options.identify === true || !!options.hydrateCart || !!options.track;
|
|
2610
2622
|
const results = {
|
|
2611
2623
|
session: session.get()
|
|
2612
2624
|
};
|
|
2613
|
-
if (
|
|
2614
|
-
if (options.
|
|
2625
|
+
if (shouldIdentify) results.session = await ensureSession();
|
|
2626
|
+
if (options.hydrateCart) results.cart = await ensureCart();
|
|
2627
|
+
if (options.track) await client.activity.track(options.track);
|
|
2615
2628
|
return results;
|
|
2616
2629
|
}
|
|
2630
|
+
async function initialize(options = {}) {
|
|
2631
|
+
return setup(options);
|
|
2632
|
+
}
|
|
2617
2633
|
const cart_store = {
|
|
2618
2634
|
cart,
|
|
2619
2635
|
product_items,
|
|
2620
2636
|
service_items,
|
|
2621
|
-
quote,
|
|
2637
|
+
quote_result: quote,
|
|
2622
2638
|
promo_code,
|
|
2623
2639
|
last_order,
|
|
2624
2640
|
status: cart_status,
|
|
@@ -2626,46 +2642,80 @@ function createArkyStore(config) {
|
|
|
2626
2642
|
service_item_count,
|
|
2627
2643
|
item_count,
|
|
2628
2644
|
snapshot,
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2645
|
+
ensure: ensureCart,
|
|
2646
|
+
hydrate: hydrateCart,
|
|
2647
|
+
sync: syncCart,
|
|
2648
|
+
addProduct,
|
|
2649
|
+
setProductQuantity,
|
|
2650
|
+
removeProduct,
|
|
2651
|
+
addServiceItem,
|
|
2652
|
+
removeServiceItem,
|
|
2653
|
+
clear: clearCart,
|
|
2654
|
+
quote: fetchQuote,
|
|
2655
|
+
checkout,
|
|
2656
|
+
applyPromoCode(code, input = {}) {
|
|
2657
|
+
promo_code.set(code);
|
|
2658
|
+
return fetchQuote({ ...input, promo_code: code });
|
|
2659
|
+
},
|
|
2660
|
+
removePromoCode(input = {}) {
|
|
2661
|
+
promo_code.set(null);
|
|
2662
|
+
return fetchQuote({ ...input, promo_code: null });
|
|
2663
|
+
},
|
|
2664
|
+
selectShippingMethod(id) {
|
|
2665
|
+
cart_status.setKey("selected_shipping_method_id", id);
|
|
2666
|
+
},
|
|
2667
|
+
locationToAddress,
|
|
2668
|
+
buildItems: checkoutItems,
|
|
2669
|
+
buildProductItems: toProductCheckoutItems,
|
|
2670
|
+
buildServiceItems: toServiceCheckoutItems
|
|
2671
|
+
};
|
|
2672
|
+
const product_store = {
|
|
2673
|
+
get: (params, options) => client.eshop.product.get(params, options),
|
|
2674
|
+
find: loadProducts,
|
|
2675
|
+
list: loadProducts,
|
|
2676
|
+
loadListing: loadProducts,
|
|
2677
|
+
loadDetail: (params, options) => client.eshop.product.get(params, options)
|
|
2657
2678
|
};
|
|
2658
|
-
const
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2679
|
+
const service_store = {
|
|
2680
|
+
get: (params, options) => client.eshop.service.get(params, options),
|
|
2681
|
+
find: loadServices,
|
|
2682
|
+
list: loadServices,
|
|
2683
|
+
loadListing: loadServices,
|
|
2684
|
+
loadDetail: (params, options) => client.eshop.service.get(params, options),
|
|
2685
|
+
listProviders: (params, options) => client.eshop.service.findProviders(params, options),
|
|
2686
|
+
findProviders: (params, options) => client.eshop.service.findProviders(params, options),
|
|
2687
|
+
getAvailability: loadAvailability,
|
|
2688
|
+
state: service_state,
|
|
2689
|
+
form_blocks: service_form_blocks,
|
|
2690
|
+
current_step_name: service_current_step_name,
|
|
2691
|
+
can_proceed: service_can_proceed,
|
|
2692
|
+
month_year: service_month_year,
|
|
2693
|
+
chain_start: service_chain_start,
|
|
2694
|
+
total_steps: service_total_steps,
|
|
2695
|
+
steps: service_steps,
|
|
2696
|
+
current_step: service_current_step,
|
|
2697
|
+
initialize: service_controller.initialize,
|
|
2698
|
+
select: service_controller.select,
|
|
2699
|
+
setTimezone: service_controller.setTimezone,
|
|
2700
|
+
loadMonth: service_controller.loadMonth,
|
|
2701
|
+
prevMonth: service_controller.prevMonth,
|
|
2702
|
+
nextMonth: service_controller.nextMonth,
|
|
2703
|
+
selectProvider: service_controller.selectProvider,
|
|
2704
|
+
selectDate: service_controller.selectDate,
|
|
2705
|
+
createMultiDaySlots: service_controller.createMultiDaySlots,
|
|
2706
|
+
selectTimeSlot: service_controller.selectTimeSlot,
|
|
2707
|
+
resetDateSelection: service_controller.resetDateSelection,
|
|
2708
|
+
updateCalendar: service_controller.updateCalendar,
|
|
2709
|
+
findFirstAvailable: service_controller.findFirstAvailable,
|
|
2710
|
+
addToCart: service_controller.addToCart,
|
|
2711
|
+
removeFromCart: service_controller.removeFromCart,
|
|
2712
|
+
clearCart: service_controller.clearCart,
|
|
2713
|
+
getProvidersList: service_controller.getProvidersList,
|
|
2714
|
+
prevStep: service_controller.prevStep,
|
|
2715
|
+
nextStep: service_controller.nextStep,
|
|
2716
|
+
getServicePrice: service_controller.getServicePrice,
|
|
2717
|
+
formatDateDisplay: service_controller.formatDateDisplay,
|
|
2718
|
+
serviceItemsFromSlots: service_controller.serviceItemsFromSlots
|
|
2669
2719
|
};
|
|
2670
2720
|
return {
|
|
2671
2721
|
client,
|
|
@@ -2676,6 +2726,7 @@ function createArkyStore(config) {
|
|
|
2676
2726
|
currency,
|
|
2677
2727
|
allowed_payment_methods,
|
|
2678
2728
|
payment_config,
|
|
2729
|
+
setup,
|
|
2679
2730
|
initialize,
|
|
2680
2731
|
identify,
|
|
2681
2732
|
verify: client.verify,
|
|
@@ -2690,6 +2741,7 @@ function createArkyStore(config) {
|
|
|
2690
2741
|
},
|
|
2691
2742
|
setMarket,
|
|
2692
2743
|
setLocale,
|
|
2744
|
+
setContext,
|
|
2693
2745
|
getMarket: currentMarketKey,
|
|
2694
2746
|
getLocale: currentLocale,
|
|
2695
2747
|
cms: {
|
|
@@ -2697,8 +2749,7 @@ function createArkyStore(config) {
|
|
|
2697
2749
|
node: {
|
|
2698
2750
|
get: loadNode,
|
|
2699
2751
|
find: (params, options) => client.cms.node.find(params, options),
|
|
2700
|
-
getChildren: (params, options) => client.cms.node.getChildren(params, options)
|
|
2701
|
-
loadWebsite: loadWebsiteNode
|
|
2752
|
+
getChildren: (params, options) => client.cms.node.getChildren(params, options)
|
|
2702
2753
|
},
|
|
2703
2754
|
form: {
|
|
2704
2755
|
get: loadForm,
|
|
@@ -2709,29 +2760,23 @@ function createArkyStore(config) {
|
|
|
2709
2760
|
},
|
|
2710
2761
|
eshop: {
|
|
2711
2762
|
state: eshop_state,
|
|
2712
|
-
product:
|
|
2713
|
-
|
|
2714
|
-
find: loadProducts
|
|
2715
|
-
},
|
|
2716
|
-
service: {
|
|
2717
|
-
get: (params, options) => client.eshop.service.get(params, options),
|
|
2718
|
-
find: loadServices,
|
|
2719
|
-
findProviders: (params, options) => client.eshop.service.findProviders(params, options),
|
|
2720
|
-
getAvailability: loadAvailability
|
|
2721
|
-
},
|
|
2763
|
+
product: product_store,
|
|
2764
|
+
service: service_store,
|
|
2722
2765
|
provider: {
|
|
2723
2766
|
get: (params, options) => client.eshop.provider.get(params, options),
|
|
2724
2767
|
find: loadProviders
|
|
2725
2768
|
},
|
|
2726
2769
|
order: client.eshop.order,
|
|
2727
|
-
cart: cart_store
|
|
2728
|
-
serviceOrder: service_order_store
|
|
2770
|
+
cart: cart_store
|
|
2729
2771
|
},
|
|
2730
2772
|
crm: client.crm,
|
|
2731
2773
|
activity: {
|
|
2732
2774
|
track(params) {
|
|
2733
2775
|
return client.activity.track(params);
|
|
2734
2776
|
},
|
|
2777
|
+
pageView(payload = {}) {
|
|
2778
|
+
return client.activity.track({ type: "page_view", payload });
|
|
2779
|
+
},
|
|
2735
2780
|
state: nanostores.atom(null)
|
|
2736
2781
|
},
|
|
2737
2782
|
store: client.store,
|