@jay-framework/wix-stores 0.15.1 → 0.15.5
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 +157 -96
- package/dist/actions/get-variant-stock.jay-action +7 -0
- package/dist/actions/search-products.jay-action +12 -0
- package/dist/contracts/category-page.jay-contract.d.ts +10 -1
- package/dist/contracts/product-card.jay-contract +8 -2
- package/dist/contracts/product-card.jay-contract.d.ts +17 -4
- package/dist/contracts/product-options.jay-contract +0 -5
- package/dist/contracts/product-options.jay-contract.d.ts +1 -2
- package/dist/contracts/product-search.jay-contract +134 -1
- package/dist/contracts/product-search.jay-contract.d.ts +92 -4
- package/dist/index.client.js +276 -24
- package/dist/index.d.ts +230 -149
- package/dist/index.js +613 -156
- package/package.json +18 -16
- package/plugin.yaml +2 -0
package/dist/index.client.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { WIX_CART_CONTEXT
|
|
1
|
+
import { WIX_CART_CONTEXT } from "@jay-framework/wix-cart/client";
|
|
2
|
+
import { WIX_CART_CONTEXT as WIX_CART_CONTEXT2, cartIndicator, cartPage } from "@jay-framework/wix-cart/client";
|
|
2
3
|
import { makeJayStackComponent, makeJayInit } from "@jay-framework/fullstack-component";
|
|
3
4
|
import { registerReactiveGlobalContext, createSignal, createMemo, createEffect } from "@jay-framework/component";
|
|
4
5
|
import { patch, REPLACE } from "@jay-framework/json-patch";
|
|
5
6
|
import { createJayContext, useGlobalContext } from "@jay-framework/runtime";
|
|
6
7
|
import { WIX_CLIENT_CONTEXT } from "@jay-framework/wix-server-client/client";
|
|
7
|
-
import { WIX_CART_CONTEXT as WIX_CART_CONTEXT2 } from "@jay-framework/wix-cart";
|
|
8
8
|
import { productsV3 } from "@wix/stores";
|
|
9
9
|
import "@wix/categories";
|
|
10
10
|
import { createActionCaller } from "@jay-framework/stack-client-runtime";
|
|
@@ -31,7 +31,7 @@ const WIX_STORES_CONTEXT = createJayContext();
|
|
|
31
31
|
function provideWixStoresContext() {
|
|
32
32
|
const wixClientContext = useGlobalContext(WIX_CLIENT_CONTEXT);
|
|
33
33
|
const wixClient = wixClientContext.client;
|
|
34
|
-
const cartContext = useGlobalContext(
|
|
34
|
+
const cartContext = useGlobalContext(WIX_CART_CONTEXT);
|
|
35
35
|
const catalogClient = getProductsV3Client(wixClient);
|
|
36
36
|
const storesContext = registerReactiveGlobalContext(WIX_STORES_CONTEXT, () => {
|
|
37
37
|
async function addToCart(productId, quantity = 1, selections) {
|
|
@@ -313,6 +313,11 @@ function ProductPageInteractive(props, refs, viewStateSignals, fastCarryForward,
|
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
315
|
const productPage = makeJayStackComponent().withProps().withContexts(WIX_STORES_CONTEXT).withInteractive(ProductPageInteractive);
|
|
316
|
+
var OptionRenderType = /* @__PURE__ */ ((OptionRenderType2) => {
|
|
317
|
+
OptionRenderType2[OptionRenderType2["TEXT_CHOICES"] = 0] = "TEXT_CHOICES";
|
|
318
|
+
OptionRenderType2[OptionRenderType2["SWATCH_CHOICES"] = 1] = "SWATCH_CHOICES";
|
|
319
|
+
return OptionRenderType2;
|
|
320
|
+
})(OptionRenderType || {});
|
|
316
321
|
var CurrentSort = /* @__PURE__ */ ((CurrentSort2) => {
|
|
317
322
|
CurrentSort2[CurrentSort2["relevance"] = 0] = "relevance";
|
|
318
323
|
CurrentSort2[CurrentSort2["priceAsc"] = 1] = "priceAsc";
|
|
@@ -324,10 +329,102 @@ var CurrentSort = /* @__PURE__ */ ((CurrentSort2) => {
|
|
|
324
329
|
})(CurrentSort || {});
|
|
325
330
|
const searchProducts = createActionCaller("wixStores.searchProducts", "GET");
|
|
326
331
|
createActionCaller("wixStores.getProductBySlug", "GET");
|
|
332
|
+
const getVariantStock = createActionCaller("wixStores.getVariantStock", "GET");
|
|
327
333
|
createActionCaller("wixStores.getCategories", "GET");
|
|
334
|
+
var QuickAddType = /* @__PURE__ */ ((QuickAddType2) => {
|
|
335
|
+
QuickAddType2[QuickAddType2["SIMPLE"] = 0] = "SIMPLE";
|
|
336
|
+
QuickAddType2[QuickAddType2["SINGLE_OPTION"] = 1] = "SINGLE_OPTION";
|
|
337
|
+
QuickAddType2[QuickAddType2["COLOR_AND_TEXT_OPTIONS"] = 2] = "COLOR_AND_TEXT_OPTIONS";
|
|
338
|
+
QuickAddType2[QuickAddType2["NEEDS_CONFIGURATION"] = 3] = "NEEDS_CONFIGURATION";
|
|
339
|
+
return QuickAddType2;
|
|
340
|
+
})(QuickAddType || {});
|
|
328
341
|
const PAGE_SIZE = 12;
|
|
342
|
+
function mapSortToAction(sort) {
|
|
343
|
+
switch (sort) {
|
|
344
|
+
case CurrentSort.priceAsc:
|
|
345
|
+
return "price_asc";
|
|
346
|
+
case CurrentSort.priceDesc:
|
|
347
|
+
return "price_desc";
|
|
348
|
+
case CurrentSort.newest:
|
|
349
|
+
return "newest";
|
|
350
|
+
case CurrentSort.nameAsc:
|
|
351
|
+
return "name_asc";
|
|
352
|
+
case CurrentSort.nameDesc:
|
|
353
|
+
return "name_desc";
|
|
354
|
+
default:
|
|
355
|
+
return "relevance";
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function updateUrlFilters(searchTerm, filters, sort, categories) {
|
|
359
|
+
if (typeof window === "undefined")
|
|
360
|
+
return;
|
|
361
|
+
const params = new URLSearchParams();
|
|
362
|
+
if (searchTerm)
|
|
363
|
+
params.set("q", searchTerm);
|
|
364
|
+
const selectedSlugs = filters.categoryFilter.categories.filter((c) => c.isSelected).map((c) => {
|
|
365
|
+
const info = categories.find((cat) => cat.categoryId === c.categoryId);
|
|
366
|
+
return info?.categorySlug;
|
|
367
|
+
}).filter(Boolean);
|
|
368
|
+
if (selectedSlugs.length)
|
|
369
|
+
params.set("cat", selectedSlugs.join(","));
|
|
370
|
+
if (filters.priceRange.minPrice > 0)
|
|
371
|
+
params.set("min", String(filters.priceRange.minPrice));
|
|
372
|
+
if (filters.priceRange.maxPrice > 0 && filters.priceRange.maxPrice < filters.priceRange.maxBound) {
|
|
373
|
+
params.set("max", String(filters.priceRange.maxPrice));
|
|
374
|
+
}
|
|
375
|
+
if (filters.inStockOnly)
|
|
376
|
+
params.set("inStock", "1");
|
|
377
|
+
const optSegments = [];
|
|
378
|
+
for (const opt of filters.optionFilters || []) {
|
|
379
|
+
const selected = opt.choices.filter((c) => c.isSelected).map((c) => encodeURIComponent(c.choiceName));
|
|
380
|
+
if (selected.length > 0) {
|
|
381
|
+
optSegments.push(`${encodeURIComponent(opt.optionName)}:${selected.join(",")}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (optSegments.length > 0)
|
|
385
|
+
params.set("opt", optSegments.join(";"));
|
|
386
|
+
if (sort !== CurrentSort.relevance) {
|
|
387
|
+
const sortNames = {
|
|
388
|
+
[CurrentSort.priceAsc]: "priceAsc",
|
|
389
|
+
[CurrentSort.priceDesc]: "priceDesc",
|
|
390
|
+
[CurrentSort.newest]: "newest",
|
|
391
|
+
[CurrentSort.nameAsc]: "nameAsc",
|
|
392
|
+
[CurrentSort.nameDesc]: "nameDesc"
|
|
393
|
+
};
|
|
394
|
+
const sortName = sortNames[sort];
|
|
395
|
+
if (sortName)
|
|
396
|
+
params.set("sort", sortName);
|
|
397
|
+
}
|
|
398
|
+
const query = params.toString();
|
|
399
|
+
window.history.replaceState(null, "", query ? `?${query}` : window.location.pathname);
|
|
400
|
+
}
|
|
401
|
+
function buildOptionFiltersViewState(baseOptionFilters, filteredResult, optionSelections) {
|
|
402
|
+
const filteredChoiceCounts = /* @__PURE__ */ new Map();
|
|
403
|
+
for (const opt of filteredResult.optionFilters || []) {
|
|
404
|
+
for (const ch of opt.choices) {
|
|
405
|
+
filteredChoiceCounts.set(ch.choiceName.toLowerCase(), ch.productCount);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return baseOptionFilters.map((opt) => ({
|
|
409
|
+
optionId: opt.optionId,
|
|
410
|
+
optionName: opt.optionName,
|
|
411
|
+
optionRenderType: opt.optionRenderType === "SWATCH_CHOICES" ? OptionRenderType.SWATCH_CHOICES : OptionRenderType.TEXT_CHOICES,
|
|
412
|
+
choices: opt.choices.map((ch) => {
|
|
413
|
+
const count = filteredChoiceCounts.get(ch.choiceName.toLowerCase()) ?? 0;
|
|
414
|
+
return {
|
|
415
|
+
choiceId: ch.choiceId,
|
|
416
|
+
choiceName: ch.choiceName,
|
|
417
|
+
colorCode: ch.colorCode,
|
|
418
|
+
productCount: count,
|
|
419
|
+
isSelected: optionSelections.get(opt.optionName)?.has(ch.choiceName) ?? false,
|
|
420
|
+
isDisabled: count === 0
|
|
421
|
+
};
|
|
422
|
+
})
|
|
423
|
+
}));
|
|
424
|
+
}
|
|
329
425
|
function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForward, storesContext) {
|
|
330
426
|
const baseCategoryId = fastCarryForward.baseCategoryId;
|
|
427
|
+
const variantStockCache = {};
|
|
331
428
|
const { searchExpression: [searchExpression, setSearchExpression], isSearching: [isSearching, setIsSearching], hasSearched: [hasSearched, setHasSearched], searchResults: [searchResults, setSearchResults], resultCount: [resultCount, setResultCount], hasResults: [hasResults, setHasResults], hasSuggestions: [hasSuggestions, setHasSuggestions], suggestions: [suggestions, setSuggestions], filters: [filters, setFilters], sortBy: [sortBy, setSortBy], hasMore: [hasMore, setHasMore], loadedCount: [loadedCount, setLoadedCount], totalCount: [totalCount, setTotalCount] } = viewStateSignals;
|
|
332
429
|
const [submittedSearchTerm, setSubmittedSearchTerm] = createSignal(null);
|
|
333
430
|
let currentCursor = null;
|
|
@@ -335,35 +432,41 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
335
432
|
let debounceTimeout = null;
|
|
336
433
|
let searchVersion = 0;
|
|
337
434
|
const DEBOUNCE_MS = 300;
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return "name_desc";
|
|
350
|
-
default:
|
|
351
|
-
return "relevance";
|
|
435
|
+
const [latestSearchResult, setLatestSearchResult] = createSignal(null);
|
|
436
|
+
const mergedFilters = createMemo(() => {
|
|
437
|
+
const f = filters();
|
|
438
|
+
const result = latestSearchResult();
|
|
439
|
+
if (!result)
|
|
440
|
+
return f;
|
|
441
|
+
const selections = /* @__PURE__ */ new Map();
|
|
442
|
+
for (const opt of f.optionFilters || []) {
|
|
443
|
+
const selected = opt.choices.filter((c) => c.isSelected).map((c) => c.choiceName);
|
|
444
|
+
if (selected.length > 0)
|
|
445
|
+
selections.set(opt.optionName, new Set(selected));
|
|
352
446
|
}
|
|
353
|
-
|
|
447
|
+
return {
|
|
448
|
+
...f,
|
|
449
|
+
optionFilters: buildOptionFiltersViewState(fastCarryForward.baseOptionFilters, result, selections)
|
|
450
|
+
};
|
|
451
|
+
});
|
|
354
452
|
const performSearch = async (version, searchTerm, currentFilters, currentSort) => {
|
|
355
453
|
setIsSearching(true);
|
|
356
454
|
setHasSearched(true);
|
|
357
455
|
try {
|
|
358
456
|
const userSelectedCategoryIds = currentFilters.categoryFilter.categories.filter((c) => c.isSelected).map((c) => c.categoryId);
|
|
359
457
|
const categoryIds = baseCategoryId ? [baseCategoryId, ...userSelectedCategoryIds] : userSelectedCategoryIds;
|
|
458
|
+
const activeOptionFilters = (currentFilters.optionFilters || []).map((opt) => ({
|
|
459
|
+
optionName: opt.optionName,
|
|
460
|
+
choiceNames: opt.choices.filter((c) => c.isSelected).map((c) => c.choiceName)
|
|
461
|
+
})).filter((o) => o.choiceNames.length > 0);
|
|
360
462
|
const result = await searchProducts({
|
|
361
463
|
query: searchTerm || "",
|
|
362
464
|
filters: {
|
|
363
465
|
minPrice: currentFilters.priceRange.minPrice || void 0,
|
|
364
466
|
maxPrice: currentFilters.priceRange.maxPrice || void 0,
|
|
365
467
|
categoryIds,
|
|
366
|
-
inStockOnly: currentFilters.inStockOnly
|
|
468
|
+
inStockOnly: currentFilters.inStockOnly,
|
|
469
|
+
optionFilters: activeOptionFilters.length > 0 ? activeOptionFilters : void 0
|
|
367
470
|
},
|
|
368
471
|
sortBy: mapSortToAction(currentSort),
|
|
369
472
|
// No cursor = start from beginning
|
|
@@ -378,7 +481,9 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
378
481
|
setLoadedCount(result.products.length);
|
|
379
482
|
setHasMore(result.hasMore);
|
|
380
483
|
setHasResults(result.products.length > 0);
|
|
484
|
+
setLatestSearchResult(result);
|
|
381
485
|
currentCursor = result.nextCursor;
|
|
486
|
+
updateUrlFilters(searchTerm, currentFilters, currentSort, fastCarryForward.categories);
|
|
382
487
|
} catch (error) {
|
|
383
488
|
if (version === searchVersion) {
|
|
384
489
|
console.error("Search failed:", error);
|
|
@@ -399,13 +504,18 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
399
504
|
const searchTerm = submittedSearchTerm();
|
|
400
505
|
const userSelectedCategoryIds = currentFilters.categoryFilter.categories.filter((c) => c.isSelected).map((c) => c.categoryId);
|
|
401
506
|
const categoryIds = baseCategoryId ? [baseCategoryId, ...userSelectedCategoryIds] : userSelectedCategoryIds;
|
|
507
|
+
const activeOptionFilters = (currentFilters.optionFilters || []).map((opt) => ({
|
|
508
|
+
optionName: opt.optionName,
|
|
509
|
+
choiceNames: opt.choices.filter((c) => c.isSelected).map((c) => c.choiceName)
|
|
510
|
+
})).filter((o) => o.choiceNames.length > 0);
|
|
402
511
|
const result = await searchProducts({
|
|
403
512
|
query: searchTerm || "",
|
|
404
513
|
filters: {
|
|
405
514
|
minPrice: currentFilters.priceRange.minPrice || void 0,
|
|
406
515
|
maxPrice: currentFilters.priceRange.maxPrice || void 0,
|
|
407
516
|
categoryIds,
|
|
408
|
-
inStockOnly: currentFilters.inStockOnly
|
|
517
|
+
inStockOnly: currentFilters.inStockOnly,
|
|
518
|
+
optionFilters: activeOptionFilters.length > 0 ? activeOptionFilters : void 0
|
|
409
519
|
},
|
|
410
520
|
sortBy: mapSortToAction(currentSort),
|
|
411
521
|
cursor: currentCursor,
|
|
@@ -520,6 +630,24 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
520
630
|
const isChecked = event.target.checked;
|
|
521
631
|
setFilters(patch(filters(), [{ op: REPLACE, path: ["inStockOnly"], value: isChecked }]));
|
|
522
632
|
});
|
|
633
|
+
refs.filters.optionFilters.choices.isSelected.oninput(({ event, coordinate }) => {
|
|
634
|
+
const [optionId, choiceId] = coordinate;
|
|
635
|
+
const currentFilters = filters();
|
|
636
|
+
const optionIndex = currentFilters.optionFilters.findIndex((o) => o.optionId === optionId);
|
|
637
|
+
if (optionIndex === -1)
|
|
638
|
+
return;
|
|
639
|
+
const choiceIndex = currentFilters.optionFilters[optionIndex].choices.findIndex((c) => c.choiceId === choiceId);
|
|
640
|
+
if (choiceIndex === -1)
|
|
641
|
+
return;
|
|
642
|
+
const isChecked = event.target.checked;
|
|
643
|
+
setFilters(patch(currentFilters, [
|
|
644
|
+
{
|
|
645
|
+
op: REPLACE,
|
|
646
|
+
path: ["optionFilters", optionIndex, "choices", choiceIndex, "isSelected"],
|
|
647
|
+
value: isChecked
|
|
648
|
+
}
|
|
649
|
+
]));
|
|
650
|
+
});
|
|
523
651
|
refs.filters.clearFilters.onclick(() => {
|
|
524
652
|
const currentFilters = filters();
|
|
525
653
|
const clearedCategories = currentFilters.categoryFilter.categories.map((cat) => ({
|
|
@@ -531,6 +659,10 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
531
659
|
isSelected: i === 0
|
|
532
660
|
// First one is "Show all"
|
|
533
661
|
}));
|
|
662
|
+
const clearedOptionFilters = (currentFilters.optionFilters || []).map((opt) => ({
|
|
663
|
+
...opt,
|
|
664
|
+
choices: opt.choices.map((ch) => ({ ...ch, isSelected: false }))
|
|
665
|
+
}));
|
|
534
666
|
setFilters({
|
|
535
667
|
priceRange: {
|
|
536
668
|
minPrice: 0,
|
|
@@ -540,7 +672,8 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
540
672
|
ranges: clearedRanges
|
|
541
673
|
},
|
|
542
674
|
categoryFilter: { categories: clearedCategories },
|
|
543
|
-
inStockOnly: false
|
|
675
|
+
inStockOnly: false,
|
|
676
|
+
optionFilters: clearedOptionFilters
|
|
544
677
|
});
|
|
545
678
|
});
|
|
546
679
|
refs.loadMoreButton.onclick(() => {
|
|
@@ -573,6 +706,49 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
573
706
|
]));
|
|
574
707
|
}
|
|
575
708
|
});
|
|
709
|
+
const variantStockLoading = /* @__PURE__ */ new Set();
|
|
710
|
+
const loadVariantStock = async (productId) => {
|
|
711
|
+
if (variantStockCache[productId] || variantStockLoading.has(productId))
|
|
712
|
+
return;
|
|
713
|
+
variantStockLoading.add(productId);
|
|
714
|
+
try {
|
|
715
|
+
const currentResults = searchResults();
|
|
716
|
+
const productIndex = currentResults.findIndex((p) => p._id === productId);
|
|
717
|
+
if (productIndex === -1)
|
|
718
|
+
return;
|
|
719
|
+
const product = currentResults[productIndex];
|
|
720
|
+
if (product?.quickAddType !== QuickAddType.COLOR_AND_TEXT_OPTIONS)
|
|
721
|
+
return;
|
|
722
|
+
const stockMap = await getVariantStock({ productId });
|
|
723
|
+
variantStockCache[productId] = stockMap;
|
|
724
|
+
const selectedColor = product.quickOption?.choices?.find((c) => c.isSelected);
|
|
725
|
+
const textChoices = product.secondQuickOption?.choices;
|
|
726
|
+
if (!selectedColor || !textChoices)
|
|
727
|
+
return;
|
|
728
|
+
const colorStock = stockMap[selectedColor.choiceId];
|
|
729
|
+
const updatedTextChoices = textChoices.map((c) => ({
|
|
730
|
+
...c,
|
|
731
|
+
inStock: colorStock?.[c.choiceId] ?? false
|
|
732
|
+
}));
|
|
733
|
+
setSearchResults(patch(searchResults(), [
|
|
734
|
+
{
|
|
735
|
+
op: REPLACE,
|
|
736
|
+
path: [productIndex, "secondQuickOption", "choices"],
|
|
737
|
+
value: updatedTextChoices
|
|
738
|
+
}
|
|
739
|
+
]));
|
|
740
|
+
} finally {
|
|
741
|
+
variantStockLoading.delete(productId);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
refs.searchResults.productLink.onmouseenter(({ coordinate }) => {
|
|
745
|
+
const [productId] = coordinate;
|
|
746
|
+
loadVariantStock(productId);
|
|
747
|
+
});
|
|
748
|
+
refs.searchResults.quickOption.choices.choiceButton.onmouseenter(({ coordinate }) => {
|
|
749
|
+
const [productId] = coordinate;
|
|
750
|
+
loadVariantStock(productId);
|
|
751
|
+
});
|
|
576
752
|
refs.searchResults.quickOption.choices.choiceButton.onclick(async ({ coordinate }) => {
|
|
577
753
|
const [productId, choiceId] = coordinate;
|
|
578
754
|
const currentResults = searchResults();
|
|
@@ -580,6 +756,44 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
580
756
|
if (productIndex === -1)
|
|
581
757
|
return;
|
|
582
758
|
const product = currentResults[productIndex];
|
|
759
|
+
if (product.quickAddType === QuickAddType.COLOR_AND_TEXT_OPTIONS) {
|
|
760
|
+
const choices = product.quickOption?.choices;
|
|
761
|
+
if (!choices)
|
|
762
|
+
return;
|
|
763
|
+
const updatedChoices = choices.map((c) => ({
|
|
764
|
+
...c,
|
|
765
|
+
isSelected: c.choiceId === choiceId
|
|
766
|
+
}));
|
|
767
|
+
let updated = patch(currentResults, [
|
|
768
|
+
{
|
|
769
|
+
op: REPLACE,
|
|
770
|
+
path: [productIndex, "quickOption", "choices"],
|
|
771
|
+
value: updatedChoices
|
|
772
|
+
}
|
|
773
|
+
]);
|
|
774
|
+
const stockMap = variantStockCache[productId];
|
|
775
|
+
if (stockMap) {
|
|
776
|
+
const colorStock = stockMap[choiceId];
|
|
777
|
+
const textChoices = product.secondQuickOption?.choices;
|
|
778
|
+
if (textChoices) {
|
|
779
|
+
const updatedTextChoices = textChoices.map((c) => ({
|
|
780
|
+
...c,
|
|
781
|
+
inStock: colorStock?.[c.choiceId] ?? false
|
|
782
|
+
}));
|
|
783
|
+
updated = patch(updated, [
|
|
784
|
+
{
|
|
785
|
+
op: REPLACE,
|
|
786
|
+
path: [productIndex, "secondQuickOption", "choices"],
|
|
787
|
+
value: updatedTextChoices
|
|
788
|
+
}
|
|
789
|
+
]);
|
|
790
|
+
}
|
|
791
|
+
} else {
|
|
792
|
+
loadVariantStock(productId);
|
|
793
|
+
}
|
|
794
|
+
setSearchResults(updated);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
583
797
|
const choice = product.quickOption?.choices?.find((c) => c.choiceId === choiceId);
|
|
584
798
|
if (!choice || !choice.inStock) {
|
|
585
799
|
console.warn("Choice not available or out of stock");
|
|
@@ -603,6 +817,45 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
603
817
|
]));
|
|
604
818
|
}
|
|
605
819
|
});
|
|
820
|
+
refs.searchResults.secondQuickOption.choices.choiceButton.onclick(async ({ coordinate }) => {
|
|
821
|
+
const [productId, choiceId] = coordinate;
|
|
822
|
+
const currentResults = searchResults();
|
|
823
|
+
const productIndex = currentResults.findIndex((p) => p._id === productId);
|
|
824
|
+
if (productIndex === -1)
|
|
825
|
+
return;
|
|
826
|
+
const product = currentResults[productIndex];
|
|
827
|
+
const textChoice = product.secondQuickOption?.choices?.find((c) => c.choiceId === choiceId);
|
|
828
|
+
const selectedColor = product.quickOption?.choices?.find((c) => c.isSelected);
|
|
829
|
+
if (!textChoice || !textChoice.inStock) {
|
|
830
|
+
console.warn("Text choice not available or out of stock");
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
setSearchResults(patch(currentResults, [
|
|
834
|
+
{ op: REPLACE, path: [productIndex, "isAddingToCart"], value: true }
|
|
835
|
+
]));
|
|
836
|
+
try {
|
|
837
|
+
const colorOptionId = product.quickOption?._id || "";
|
|
838
|
+
const textOptionId = product.secondQuickOption?._id || "";
|
|
839
|
+
await storesContext.addToCart(productId, 1, {
|
|
840
|
+
options: {
|
|
841
|
+
[colorOptionId]: selectedColor?.choiceId || "",
|
|
842
|
+
[textOptionId]: textChoice.choiceId
|
|
843
|
+
},
|
|
844
|
+
modifiers: {},
|
|
845
|
+
customTextFields: {}
|
|
846
|
+
});
|
|
847
|
+
} catch (error) {
|
|
848
|
+
console.error("Failed to add to cart:", error);
|
|
849
|
+
} finally {
|
|
850
|
+
setSearchResults(patch(searchResults(), [
|
|
851
|
+
{ op: REPLACE, path: [productIndex, "isAddingToCart"], value: false }
|
|
852
|
+
]));
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
refs.searchResults.secondQuickOption.choices.choiceButton.onmouseenter(({ coordinate }) => {
|
|
856
|
+
const [productId] = coordinate;
|
|
857
|
+
loadVariantStock(productId);
|
|
858
|
+
});
|
|
606
859
|
refs.searchResults.viewOptionsButton.onclick(({ coordinate }) => {
|
|
607
860
|
const [productId] = coordinate;
|
|
608
861
|
const product = searchResults().find((p) => p._id === productId);
|
|
@@ -620,7 +873,7 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
620
873
|
hasResults: hasResults(),
|
|
621
874
|
hasSuggestions: hasSuggestions(),
|
|
622
875
|
suggestions: suggestions(),
|
|
623
|
-
filters:
|
|
876
|
+
filters: mergedFilters(),
|
|
624
877
|
sortBy: sortBy(),
|
|
625
878
|
hasMore: hasMore(),
|
|
626
879
|
loadedCount: loadedCount(),
|
|
@@ -634,10 +887,9 @@ const init = makeJayInit().withClient(async (data) => {
|
|
|
634
887
|
console.log("[wix-stores] Initializing client-side stores context...");
|
|
635
888
|
provideWixStoresContext();
|
|
636
889
|
console.log("[wix-stores] Client initialization complete");
|
|
637
|
-
console.log(`[wix-stores] Search enabled: ${data.enableClientSearch}`);
|
|
638
890
|
});
|
|
639
891
|
export {
|
|
640
|
-
WIX_CART_CONTEXT,
|
|
892
|
+
WIX_CART_CONTEXT2 as WIX_CART_CONTEXT,
|
|
641
893
|
WIX_STORES_CONTEXT,
|
|
642
894
|
cartIndicator,
|
|
643
895
|
cartPage,
|