@scayle/storefront-product-listing 1.8.1 → 2.0.1
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/CHANGELOG.md +87 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/composables/useAppliedFilters.js +7 -5
- package/dist/runtime/composables/useFiltersForListing.d.ts +1 -2
- package/dist/runtime/composables/useProductListSort.d.ts +15 -29
- package/dist/runtime/composables/useProductListSort.js +33 -38
- package/dist/runtime/composables/useProductListingSeoData.d.ts +2 -1
- package/dist/runtime/composables/useProductListingSeoData.js +2 -4
- package/dist/runtime/composables/useProductsForListing.d.ts +1 -2
- package/dist/runtime/rpc/methods/categories.js +4 -3
- package/dist/runtime/types/sort.d.ts +9 -0
- package/dist/runtime/types/sort.js +0 -0
- package/dist/runtime/utils/category.d.ts +7 -0
- package/dist/runtime/utils/category.js +12 -0
- package/dist/runtime/utils/filters.d.ts +3 -3
- package/dist/runtime/utils/filters.js +3 -3
- package/package.json +13 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,92 @@
|
|
|
1
1
|
# @scayle/storefront-product-listing
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Resolved an issue where the `appliedFilter` in `useAppliedFilters` was updated on every route change even if the query didn't change.
|
|
8
|
+
|
|
9
|
+
This caused unnecessary updates in places where there is a reactive dependency on the `appliedFilter`.
|
|
10
|
+
The `appliedFilter` is now only updated when the query actually changes.
|
|
11
|
+
|
|
12
|
+
## 2.0.0
|
|
13
|
+
|
|
14
|
+
### Major Changes
|
|
15
|
+
|
|
16
|
+
- **BREAKING**: Removed the `defaultSortingOptions` export. It is now expected to explicitly pass the `sortingOptions` to `useProductListSort`.
|
|
17
|
+
|
|
18
|
+
**Before**
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { defaultSortingOptions } from '#storefront-product-listing'
|
|
22
|
+
const { sortLinks } = useProductListSort(useRoute(), {
|
|
23
|
+
sortingOptions: defaultSortingOptions,
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
const { sortLinks } = useProductListSort(useRoute())
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
(Both before approaches are equivalent.)
|
|
32
|
+
|
|
33
|
+
**After**
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { SORT_PRICE_ASC, SORT_PRICE_DESC } from '#storefront-product-listing'
|
|
37
|
+
const { sortLinks } = useProductListSort(useRoute(), {
|
|
38
|
+
sortingOptions: [
|
|
39
|
+
{
|
|
40
|
+
...SORT_PRICE_ASC,
|
|
41
|
+
label: 'Price Ascending',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
...SORT_PRICE_DESC,
|
|
45
|
+
label: 'Price Descending',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- **BREAKING**: `useProductListingSeoData` now expects `isDefaultSortSelected` to be passed as the final parameter. This removes the internal dependency on `useProductListSort`. It is typed as `MaybeRefOrGetter<Boolean>` to support reactive usage.
|
|
52
|
+
|
|
53
|
+
**Before**
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const route = useRoute()
|
|
57
|
+
const { title, robots, canonicalLink, categoryBreadcrumbSchema } =
|
|
58
|
+
useProductListingSeoData(breadcrumbs, route, {
|
|
59
|
+
baseUrl: baseUrl,
|
|
60
|
+
fullPath: fullPath,
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**After**
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const route = useRoute()
|
|
68
|
+
const { isDefaultSortSelected } = useProductListSort(...)
|
|
69
|
+
const { title, robots, canonicalLink, categoryBreadcrumbSchema } = useProductListingSeoData(
|
|
70
|
+
breadcrumbs,
|
|
71
|
+
route,
|
|
72
|
+
{
|
|
73
|
+
baseUrl: baseUrl,
|
|
74
|
+
fullPath: fullPath,
|
|
75
|
+
},
|
|
76
|
+
isDefaultSortSelected,
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Minor Changes
|
|
81
|
+
|
|
82
|
+
- Added exports for individual sort configs. `SORT_TOP_SELLER`, `SORT_DATE_NEWEST`, `SORT_PRICE_DESC`, `SORT_PRICE_ASC`, and `SORT_REDUCTION_DESC`. These can be used to easily construct a list of sort configs to pass to `useProductListSort`.
|
|
83
|
+
- Added new type exports `SelectedSort` and `SortLink`. This improves the experience of using `useProductListSort` by making the parameter and return types of this composable more accessible.
|
|
84
|
+
- The `sortingKey` for the default Topseller sort has changed from `scayle:v1:recommended` to `scayle:v1:balanced-offerings`.
|
|
85
|
+
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- In `useProductListSort`, the `sortingOptions` option now accepts `MaybeRefOrGetter<SelectedSort[]>`. This allows for reactive usage of the composable.
|
|
89
|
+
|
|
3
90
|
## 1.8.1
|
|
4
91
|
|
|
5
92
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
export * from '../dist/runtime/types/sort.js';
|
|
2
|
+
import { BreadcrumbItem, FilterItemWithValues } from '@scayle/storefront-nuxt';
|
|
2
3
|
import { Factory } from 'fishery';
|
|
3
|
-
import { FilterItemWithValues } from '@scayle/storefront-api';
|
|
4
4
|
|
|
5
5
|
type RangeTuple = [start: number, end: number];
|
|
6
6
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export * from '../dist/runtime/types/sort.js';
|
|
1
2
|
import { Factory } from 'fishery';
|
|
2
|
-
import { FilterTypes } from '@scayle/storefront-
|
|
3
|
+
import { FilterTypes } from '@scayle/storefront-nuxt';
|
|
3
4
|
|
|
4
5
|
const breadcrumbsFactory = Factory.define(() => [
|
|
5
6
|
{ to: "/de/c/women/clothing/shirts-2045", value: "shirts" },
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineNuxtModule, createResolver, addImportsDir } from '@nuxt/kit';
|
|
2
2
|
|
|
3
3
|
const PACKAGE_NAME = "@scayle/storefront-product-listing";
|
|
4
|
-
const PACKAGE_VERSION = "
|
|
4
|
+
const PACKAGE_VERSION = "2.0.1";
|
|
5
5
|
const module = defineNuxtModule({
|
|
6
6
|
meta: {
|
|
7
7
|
name: PACKAGE_NAME,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
1
|
+
import { computed, ref, watch } from "vue";
|
|
2
2
|
import { parseFilterDataFromRoute } from "../utils/filters.js";
|
|
3
3
|
export function useAppliedFilters(route, { filtersPrefix } = { filtersPrefix: "filters" }) {
|
|
4
|
-
const appliedFilter =
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const appliedFilter = ref({ attributes: [] });
|
|
5
|
+
const routeQueryString = computed(() => JSON.stringify(route.query));
|
|
6
|
+
watch(routeQueryString, () => {
|
|
7
|
+
appliedFilter.value = parseFilterDataFromRoute(route.query, filtersPrefix);
|
|
8
|
+
}, { immediate: true });
|
|
7
9
|
const appliedFiltersCount = computed(() => {
|
|
8
10
|
let count = 0;
|
|
9
11
|
count += appliedFilter.value.attributes?.length ?? 0;
|
|
@@ -39,7 +41,7 @@ export function useAppliedFilters(route, { filtersPrefix } = { filtersPrefix: "f
|
|
|
39
41
|
return appliedFiltersCount.value > 0;
|
|
40
42
|
});
|
|
41
43
|
return {
|
|
42
|
-
appliedFilter,
|
|
44
|
+
appliedFilter: computed(() => appliedFilter.value),
|
|
43
45
|
appliedFiltersCount,
|
|
44
46
|
appliedAttributeValues,
|
|
45
47
|
appliedBooleanValues,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { FetchFiltersParams } from '@scayle/storefront-nuxt';
|
|
1
|
+
import type { FetchFiltersParams, FilterItemWithValues } from '@scayle/storefront-nuxt';
|
|
2
2
|
import { useFilters } from '@scayle/storefront-nuxt/composables';
|
|
3
3
|
import type { ComputedRef, Ref } from 'vue';
|
|
4
|
-
import type { FilterItemWithValues } from '@scayle/storefront-api';
|
|
5
4
|
export type FiltersForListingOptions = Partial<{
|
|
6
5
|
params: Ref<Omit<FetchFiltersParams, 'category'>>;
|
|
7
6
|
fetchingOptions: Partial<{
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
type SelectedSort = ProductSortConfig & {
|
|
5
|
-
key: string;
|
|
6
|
-
label: string;
|
|
7
|
-
};
|
|
8
|
-
type SortLink = SelectedSort & {
|
|
9
|
-
to: RouteLocationRaw;
|
|
10
|
-
};
|
|
1
|
+
import type { ComputedRef, MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router';
|
|
3
|
+
import type { SelectedSort, SortLink } from '../types/sort.js';
|
|
11
4
|
export interface UseProductListSortReturn {
|
|
12
5
|
/** The currently selected sorting option. */
|
|
13
6
|
selectedSort: ComputedRef<SelectedSort | undefined>;
|
|
@@ -17,40 +10,34 @@ export interface UseProductListSortReturn {
|
|
|
17
10
|
isDefaultSortSelected: ComputedRef<boolean>;
|
|
18
11
|
}
|
|
19
12
|
export interface ProductListSortOptions {
|
|
20
|
-
sortingOptions
|
|
13
|
+
sortingOptions: MaybeRefOrGetter<SelectedSort[]>;
|
|
21
14
|
defaultSortingKey?: string;
|
|
22
15
|
}
|
|
23
|
-
export declare const
|
|
16
|
+
export declare const SORT_TOP_SELLER: {
|
|
24
17
|
key: string;
|
|
25
18
|
sortingKey: string;
|
|
26
19
|
direction: "desc";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} | {
|
|
20
|
+
};
|
|
21
|
+
export declare const SORT_DATE_NEWEST: {
|
|
30
22
|
key: string;
|
|
31
23
|
by: "new";
|
|
32
24
|
direction: "desc";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} | {
|
|
25
|
+
};
|
|
26
|
+
export declare const SORT_PRICE_DESC: {
|
|
36
27
|
key: string;
|
|
37
28
|
by: "price";
|
|
38
29
|
direction: "desc";
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
} | {
|
|
30
|
+
};
|
|
31
|
+
export declare const SORT_PRICE_ASC: {
|
|
42
32
|
key: string;
|
|
43
33
|
by: "price";
|
|
44
34
|
direction: "asc";
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} | {
|
|
35
|
+
};
|
|
36
|
+
export declare const SORT_REDUCTION_DESC: {
|
|
48
37
|
key: string;
|
|
49
38
|
by: "reduction";
|
|
50
39
|
direction: "desc";
|
|
51
|
-
|
|
52
|
-
sortingKey?: undefined;
|
|
53
|
-
})[];
|
|
40
|
+
};
|
|
54
41
|
export declare const DEFAULT_SORTING_KEY = "top_seller";
|
|
55
42
|
/**
|
|
56
43
|
* Custom composable to handle product list sorting.
|
|
@@ -62,5 +49,4 @@ export declare const DEFAULT_SORTING_KEY = "top_seller";
|
|
|
62
49
|
*
|
|
63
50
|
* @returns Computed properties and methods related to sorting
|
|
64
51
|
*/
|
|
65
|
-
export declare function useProductListSort(route: RouteLocationNormalizedLoadedGeneric, { sortingOptions, defaultSortingKey, }
|
|
66
|
-
export {};
|
|
52
|
+
export declare function useProductListSort(route: RouteLocationNormalizedLoadedGeneric, { sortingOptions, defaultSortingKey, }: ProductListSortOptions): UseProductListSortReturn;
|
|
@@ -1,52 +1,47 @@
|
|
|
1
1
|
import { APISortOption, APISortOrder } from "@scayle/storefront-nuxt";
|
|
2
|
-
import { computed } from "vue";
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
key: "reduction_desc",
|
|
30
|
-
by: APISortOption.REDUCTION,
|
|
31
|
-
direction: APISortOrder.DESCENDING,
|
|
32
|
-
label: "sorting_select.reduction_desc"
|
|
33
|
-
}
|
|
34
|
-
];
|
|
2
|
+
import { computed, toValue } from "vue";
|
|
3
|
+
export const SORT_TOP_SELLER = {
|
|
4
|
+
key: "top_seller",
|
|
5
|
+
sortingKey: "scayle:v1:balanced-offerings",
|
|
6
|
+
direction: APISortOrder.DESCENDING
|
|
7
|
+
};
|
|
8
|
+
export const SORT_DATE_NEWEST = {
|
|
9
|
+
key: "date_newest",
|
|
10
|
+
by: APISortOption.DATE_ADDED,
|
|
11
|
+
direction: APISortOrder.DESCENDING
|
|
12
|
+
};
|
|
13
|
+
export const SORT_PRICE_DESC = {
|
|
14
|
+
key: "price_desc",
|
|
15
|
+
by: APISortOption.PRICE,
|
|
16
|
+
direction: APISortOrder.DESCENDING
|
|
17
|
+
};
|
|
18
|
+
export const SORT_PRICE_ASC = {
|
|
19
|
+
key: "price_asc",
|
|
20
|
+
by: APISortOption.PRICE,
|
|
21
|
+
direction: APISortOrder.ASCENDING
|
|
22
|
+
};
|
|
23
|
+
export const SORT_REDUCTION_DESC = {
|
|
24
|
+
key: "reduction_desc",
|
|
25
|
+
by: APISortOption.REDUCTION,
|
|
26
|
+
direction: APISortOrder.DESCENDING
|
|
27
|
+
};
|
|
35
28
|
export const DEFAULT_SORTING_KEY = "top_seller";
|
|
36
29
|
export function useProductListSort(route, {
|
|
37
|
-
sortingOptions
|
|
30
|
+
sortingOptions,
|
|
38
31
|
defaultSortingKey = DEFAULT_SORTING_KEY
|
|
39
|
-
}
|
|
32
|
+
}) {
|
|
40
33
|
const selectedSort = computed(() => {
|
|
41
|
-
const
|
|
34
|
+
const options = toValue(sortingOptions);
|
|
35
|
+
const sort = options.find(({ key }) => key === route.query.sort);
|
|
42
36
|
if (!sort) {
|
|
43
|
-
return
|
|
37
|
+
return options?.find(({ key }) => key === defaultSortingKey);
|
|
44
38
|
}
|
|
45
39
|
return sort;
|
|
46
40
|
});
|
|
47
41
|
const sortLinks = computed(() => {
|
|
48
42
|
const { page, ...query } = route.query;
|
|
49
|
-
|
|
43
|
+
const options = toValue(sortingOptions);
|
|
44
|
+
return options?.map((option) => ({
|
|
50
45
|
...option,
|
|
51
46
|
to: {
|
|
52
47
|
path: route.path,
|
|
@@ -22,8 +22,9 @@ export interface UseProductListingSeoDataReturn {
|
|
|
22
22
|
* @param params - URL data for constructing the canonical link.
|
|
23
23
|
* @param params.baseUrl The base URL of the application.
|
|
24
24
|
* @param params.fullPath - The full path of the current route.
|
|
25
|
+
* @param isDefaultSortSelected - If the default sort is applied on the listing.
|
|
25
26
|
*
|
|
26
27
|
* @returns An object containing reactive data and computed properties for managing SEO data.
|
|
27
28
|
*/
|
|
28
|
-
export declare function useProductListingSeoData(breadcrumbs: MaybeRefOrGetter<BreadcrumbItem[]>, route: RouteLocationNormalizedLoadedGeneric, { baseUrl, fullPath }: UrlParams): UseProductListingSeoDataReturn;
|
|
29
|
+
export declare function useProductListingSeoData(breadcrumbs: MaybeRefOrGetter<BreadcrumbItem[]>, route: RouteLocationNormalizedLoadedGeneric, { baseUrl, fullPath }: UrlParams, isDefaultSortSelected: MaybeRefOrGetter<boolean>): UseProductListingSeoDataReturn;
|
|
29
30
|
export {};
|
|
@@ -4,12 +4,10 @@ import {
|
|
|
4
4
|
sanitizeCanonicalURL
|
|
5
5
|
} from "@scayle/storefront-nuxt";
|
|
6
6
|
import { useAppliedFilters } from "./useAppliedFilters.js";
|
|
7
|
-
|
|
8
|
-
export function useProductListingSeoData(breadcrumbs, route, { baseUrl, fullPath }) {
|
|
7
|
+
export function useProductListingSeoData(breadcrumbs, route, { baseUrl, fullPath }, isDefaultSortSelected) {
|
|
9
8
|
const { areFiltersApplied } = useAppliedFilters(route);
|
|
10
|
-
const { isDefaultSortSelected } = useProductListSort(route);
|
|
11
9
|
const robots = computed(() => {
|
|
12
|
-
return !areFiltersApplied.value && isDefaultSortSelected
|
|
10
|
+
return !areFiltersApplied.value && toValue(isDefaultSortSelected) ? "index,follow" : "noindex,follow";
|
|
13
11
|
});
|
|
14
12
|
const canonicalLink = computed(
|
|
15
13
|
() => robots.value.includes("noindex") ? [] : [{
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { FetchProductsByCategoryParams, Product } from '@scayle/storefront-nuxt';
|
|
1
|
+
import type { FetchProductsByCategoryParams, Product, Pagination } from '@scayle/storefront-nuxt';
|
|
2
2
|
import type { Ref, ComputedRef } from 'vue';
|
|
3
3
|
import { useProducts } from '@scayle/storefront-nuxt/composables';
|
|
4
|
-
import type { Pagination } from '@scayle/storefront-api';
|
|
5
4
|
export type UseProductsForListingReturn = Pick<Awaited<ReturnType<typeof useProducts>>, 'error' | 'status'> & {
|
|
6
5
|
/** A computed array of products in the specified category. */
|
|
7
6
|
products: ComputedRef<Product[]>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ErrorResponse,
|
|
3
3
|
HttpStatusCode,
|
|
4
|
-
HttpStatusMessage
|
|
4
|
+
HttpStatusMessage,
|
|
5
|
+
defineRpcHandler
|
|
5
6
|
} from "@scayle/storefront-nuxt";
|
|
6
|
-
export const getAllShopCategoriesForId = async
|
|
7
|
+
export const getAllShopCategoriesForId = defineRpcHandler(async ({ id, properties }, context) => {
|
|
7
8
|
if (typeof id !== "number" || isNaN(id)) {
|
|
8
9
|
return new ErrorResponse(
|
|
9
10
|
HttpStatusCode.BAD_REQUEST,
|
|
@@ -43,4 +44,4 @@ export const getAllShopCategoriesForId = async function getAllShopCategoriesForI
|
|
|
43
44
|
// 12 hours
|
|
44
45
|
})();
|
|
45
46
|
return result;
|
|
46
|
-
};
|
|
47
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProductSortConfig } from '@scayle/storefront-nuxt';
|
|
2
|
+
import type { RouteLocationRaw } from 'vue-router';
|
|
3
|
+
export type SelectedSort = ProductSortConfig & {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
};
|
|
7
|
+
export type SortLink = SelectedSort & {
|
|
8
|
+
to: RouteLocationRaw;
|
|
9
|
+
};
|
|
File without changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Category } from '@scayle/storefront-nuxt';
|
|
2
|
+
import type { SelectedSort } from '../types/sort.js';
|
|
2
3
|
/**
|
|
3
4
|
* Get all ancestors of a category.
|
|
4
5
|
* @param category - The category to get the ancestors of.
|
|
@@ -17,3 +18,9 @@ export declare const isSaleCategory: (category: Category) => boolean;
|
|
|
17
18
|
* @returns A flattened array of all categories in the tree.
|
|
18
19
|
*/
|
|
19
20
|
export declare const flattenCategoryTree: (categoryTree: Category[]) => Category[];
|
|
21
|
+
/**
|
|
22
|
+
* Create a default sorting config based on the current category
|
|
23
|
+
* @param category - The category to use for smart and custom sorting keys
|
|
24
|
+
* @returns The correct default sort config for the category
|
|
25
|
+
*/
|
|
26
|
+
export declare function createDefaultSortingOption(category?: Category): Omit<SelectedSort, 'label'>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SORT_TOP_SELLER } from "../composables/useProductListSort.js";
|
|
1
2
|
export const getCategoryAncestors = (category) => {
|
|
2
3
|
if (!category?.parent) {
|
|
3
4
|
return [];
|
|
@@ -21,3 +22,14 @@ export const flattenCategoryTree = (categoryTree) => {
|
|
|
21
22
|
).values()
|
|
22
23
|
];
|
|
23
24
|
};
|
|
25
|
+
export function createDefaultSortingOption(category) {
|
|
26
|
+
const smartSortingKey = category?.productSorting?.smartSortingKey;
|
|
27
|
+
const customSortingKey = category?.productSorting?.customSortingKey;
|
|
28
|
+
if (!smartSortingKey && !customSortingKey) {
|
|
29
|
+
return SORT_TOP_SELLER;
|
|
30
|
+
}
|
|
31
|
+
const sortingKey = [customSortingKey, smartSortingKey].filter(
|
|
32
|
+
(item) => !!item
|
|
33
|
+
);
|
|
34
|
+
return { ...SORT_TOP_SELLER, sortingKey };
|
|
35
|
+
}
|
|
@@ -2,14 +2,14 @@ import type { LocationQuery, RouteLocationNormalizedLoadedGeneric } from 'vue-ro
|
|
|
2
2
|
import type { CategoryFilter, ProductSearchQuery } from '@scayle/storefront-nuxt';
|
|
3
3
|
import type { RangeTuple } from '../..//index.js';
|
|
4
4
|
/**
|
|
5
|
-
* Parses filter data from a Vue Router
|
|
5
|
+
* Parses filter data from a Vue Router query object.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
7
|
+
* @param query The query object.
|
|
8
8
|
* @param filtersPrefix The prefix used for filter query parameters.
|
|
9
9
|
*
|
|
10
10
|
* @returns An object representing the parsed product search query.
|
|
11
11
|
*/
|
|
12
|
-
export declare const parseFilterDataFromRoute: (
|
|
12
|
+
export declare const parseFilterDataFromRoute: (query: LocationQuery, filtersPrefix: string) => ProductSearchQuery;
|
|
13
13
|
/**
|
|
14
14
|
* Creates a new attribute filter query object.
|
|
15
15
|
*
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const getAttributeValues = (value) => {
|
|
2
2
|
return value.split(",").filter((v) => v !== "").map(Number).filter((v) => !isNaN(v));
|
|
3
3
|
};
|
|
4
|
-
export const parseFilterDataFromRoute = (
|
|
5
|
-
const queryKeys = Object.keys(
|
|
4
|
+
export const parseFilterDataFromRoute = (query, filtersPrefix) => {
|
|
5
|
+
const queryKeys = Object.keys(query);
|
|
6
6
|
const productSearchQuery = { attributes: [] };
|
|
7
7
|
queryKeys.forEach((queryKey) => {
|
|
8
|
-
const value =
|
|
8
|
+
const value = query[queryKey];
|
|
9
9
|
if (!queryKey.includes(filtersPrefix)) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scayle/storefront-product-listing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Collection of essential composables and utilities to work with product listing",
|
|
5
5
|
"author": "SCAYLE Commerce Engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,9 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@nuxt/kit": ">=3.13.0",
|
|
36
|
-
"@scayle/storefront-core": "^8.0.0",
|
|
37
36
|
"@scayle/storefront-nuxt": "^8.0.0",
|
|
38
|
-
"@vue/test-utils": "^2.4.6",
|
|
39
37
|
"@vueuse/core": "^12.8.2 || ^13.0.0",
|
|
40
38
|
"fishery": "^2.2.3",
|
|
41
39
|
"vue-router": "^4.5.0",
|
|
@@ -43,31 +41,29 @@
|
|
|
43
41
|
},
|
|
44
42
|
"devDependencies": {
|
|
45
43
|
"@arethetypeswrong/cli": "0.18.2",
|
|
46
|
-
"@nuxt/kit": "3.
|
|
44
|
+
"@nuxt/kit": "3.17.7",
|
|
47
45
|
"@nuxt/module-builder": "1.0.1",
|
|
48
|
-
"@nuxt/schema": "3.
|
|
49
|
-
"@nuxt/test-utils": "3.
|
|
50
|
-
"@
|
|
51
|
-
"@scayle/storefront-api": "18.9.0",
|
|
52
|
-
"@scayle/storefront-nuxt": "8.31.0",
|
|
53
|
-
"@types/node": "22.15.33",
|
|
46
|
+
"@nuxt/schema": "3.17.7",
|
|
47
|
+
"@nuxt/test-utils": "3.19.2",
|
|
48
|
+
"@types/node": "22.16.4",
|
|
54
49
|
"@vitest/coverage-v8": "3.2.4",
|
|
55
|
-
"@
|
|
56
|
-
"
|
|
57
|
-
"dprint": "0.50.0",
|
|
50
|
+
"@vueuse/core": "13.5.0",
|
|
51
|
+
"dprint": "0.50.1",
|
|
58
52
|
"eslint-formatter-gitlab": "6.0.1",
|
|
59
|
-
"eslint": "9.
|
|
53
|
+
"eslint": "9.31.0",
|
|
60
54
|
"fishery": "2.3.1",
|
|
61
55
|
"happy-dom": "18.0.1",
|
|
62
|
-
"nuxt": "3.
|
|
56
|
+
"nuxt": "3.17.7",
|
|
63
57
|
"publint": "0.3.12",
|
|
64
58
|
"schema-dts": "1.1.5",
|
|
65
59
|
"typescript": "5.8.3",
|
|
66
60
|
"unbuild": "3.5.0",
|
|
67
61
|
"vitest": "3.2.4",
|
|
68
62
|
"vue-router": "4.5.1",
|
|
69
|
-
"vue-tsc": "
|
|
70
|
-
"vue": "3.5.17"
|
|
63
|
+
"vue-tsc": "3.0.1",
|
|
64
|
+
"vue": "3.5.17",
|
|
65
|
+
"@scayle/eslint-config-storefront": "4.6.1",
|
|
66
|
+
"@scayle/storefront-nuxt": "8.34.1"
|
|
71
67
|
},
|
|
72
68
|
"scripts": {
|
|
73
69
|
"build": "nuxt-module-build build",
|