@mohasinac/appkit 2.7.10 → 2.7.12
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/_internal/server/jobs/core/assignSpinPrize.js +8 -7
- package/dist/_internal/server/jobs/core/bundleStockSync.js +11 -6
- package/dist/_internal/server/jobs/core/countersReconcile.js +3 -2
- package/dist/_internal/server/jobs/core/onProductStockChange.js +12 -7
- package/dist/_internal/server/jobs/core/onProductWrite.js +3 -2
- package/dist/_internal/server/jobs/core/prizeRevealClose.js +7 -5
- package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +11 -6
- package/dist/_internal/server/jobs/core/prizeRevealOpen.js +13 -7
- package/dist/_internal/server/jobs/core/prizeRevealReminder.js +9 -4
- package/dist/_internal/server/jobs/core/triggerEventRaffle.js +3 -2
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
- package/dist/_internal/shared/features/events/schema.d.ts +4 -4
- package/dist/_internal/shared/features/products/schema.d.ts +20 -20
- package/dist/_internal/shared/features/promotions/schema.d.ts +2 -2
- package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
- package/dist/configs/next.js +17 -1
- package/dist/constants/field-names.d.ts +813 -0
- package/dist/constants/field-names.js +918 -0
- package/dist/constants/sort.d.ts +7 -0
- package/dist/constants/sort.js +5 -0
- package/dist/constants/table-keys.d.ts +48 -0
- package/dist/constants/table-keys.js +46 -0
- package/dist/features/account/components/AddressesIndexListing.js +9 -6
- package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -1
- package/dist/features/admin/components/AdminBidsView.js +4 -1
- package/dist/features/admin/components/AdminBlogView.js +9 -2
- package/dist/features/admin/components/AdminBrandsView.js +9 -2
- package/dist/features/admin/components/AdminCarouselView.js +4 -1
- package/dist/features/admin/components/AdminCartsView.js +4 -1
- package/dist/features/admin/components/AdminCategoriesView.js +9 -2
- package/dist/features/admin/components/AdminContactView.js +4 -1
- package/dist/features/admin/components/AdminCouponsView.js +4 -1
- package/dist/features/admin/components/AdminFaqsView.js +5 -1
- package/dist/features/admin/components/AdminFeaturesView.js +5 -2
- package/dist/features/admin/components/AdminHistoryView.js +5 -1
- package/dist/features/admin/components/AdminNewsletterView.js +4 -1
- package/dist/features/admin/components/AdminNotificationsView.js +4 -1
- package/dist/features/admin/components/AdminOrdersView.js +14 -12
- package/dist/features/admin/components/AdminPayoutsView.js +4 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -1
- package/dist/features/admin/components/AdminProductsView.js +14 -3
- package/dist/features/admin/components/AdminReturnRequestsView.js +4 -1
- package/dist/features/admin/components/AdminReviewsView.js +4 -1
- package/dist/features/admin/components/AdminScammersView.js +4 -1
- package/dist/features/admin/components/AdminSessionsView.js +4 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +5 -1
- package/dist/features/admin/components/AdminStoresView.js +10 -3
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +4 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +4 -1
- package/dist/features/admin/components/AdminTeamView.js +4 -1
- package/dist/features/admin/components/AdminUsersView.js +9 -12
- package/dist/features/admin/components/AdminViewCards.d.ts +12 -0
- package/dist/features/admin/components/AdminViewCards.js +53 -0
- package/dist/features/admin/components/AdminWishlistsView.js +4 -1
- package/dist/features/auctions/repository/bid.repository.js +1 -6
- package/dist/features/auctions/schemas/index.d.ts +4 -4
- package/dist/features/blog/actions/blog-actions.d.ts +16 -16
- package/dist/features/blog/components/BlogFilters.d.ts +28 -28
- package/dist/features/blog/components/BlogFilters.js +18 -15
- package/dist/features/blog/components/BlogIndexListing.js +24 -13
- package/dist/features/blog/schemas/index.d.ts +10 -10
- package/dist/features/categories/components/CategoriesIndexListing.js +30 -19
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/events/components/AdminEventsView.js +5 -1
- package/dist/features/events/components/EventFilters.d.ts +24 -24
- package/dist/features/events/components/EventFilters.js +16 -13
- package/dist/features/events/components/EventStatusBadge.js +1 -0
- package/dist/features/events/components/EventsIndexListing.js +36 -24
- package/dist/features/events/components/EventsListPageView.js +13 -10
- package/dist/features/events/schemas/firestore.d.ts +1 -0
- package/dist/features/events/schemas/firestore.js +1 -0
- package/dist/features/events/schemas/index.d.ts +1 -1
- package/dist/features/events/types/index.d.ts +1 -1
- package/dist/features/faq/actions/faq-actions.d.ts +10 -10
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/orders/components/OrderFilters.d.ts +20 -20
- package/dist/features/orders/components/OrderFilters.js +33 -30
- package/dist/features/orders/repository/orders.repository.js +1 -15
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +44 -36
- package/dist/features/pre-orders/schemas/index.d.ts +3 -3
- package/dist/features/products/components/AuctionsIndexListing.js +63 -30
- package/dist/features/products/components/BidHistory.d.ts +0 -1
- package/dist/features/products/components/BidHistory.js +1 -1
- package/dist/features/products/components/PrizeDrawsIndexListing.js +44 -37
- package/dist/features/products/components/ProductDetailPageView.js +1 -1
- package/dist/features/products/components/ProductFilters.d.ts +20 -20
- package/dist/features/products/components/ProductFilters.js +62 -59
- package/dist/features/products/components/ProductsIndexListing.js +37 -29
- package/dist/features/products/components/ProductsIndexPageView.js +18 -10
- package/dist/features/products/hooks/useProducts.js +2 -0
- package/dist/features/products/repository/products.repository.js +2 -22
- package/dist/features/products/schemas/index.d.ts +28 -28
- package/dist/features/products/schemas/product-features.validators.d.ts +12 -12
- package/dist/features/products/types/index.d.ts +2 -0
- package/dist/features/promotions/components/CouponsIndexListing.js +21 -17
- package/dist/features/promotions/schemas/index.d.ts +4 -4
- package/dist/features/reviews/components/ReviewDetailShell.js +6 -5
- package/dist/features/reviews/components/ReviewFilters.d.ts +16 -16
- package/dist/features/reviews/components/ReviewFilters.js +10 -7
- package/dist/features/reviews/components/ReviewsIndexListing.js +25 -14
- package/dist/features/reviews/components/ReviewsList.d.ts +5 -2
- package/dist/features/reviews/components/ReviewsList.js +11 -5
- package/dist/features/reviews/schemas/firestore.d.ts +1 -0
- package/dist/features/reviews/schemas/index.d.ts +8 -8
- package/dist/features/reviews/types/index.d.ts +1 -0
- package/dist/features/search/schemas/index.d.ts +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +5 -1
- package/dist/features/seller/components/SellerBidsView.js +4 -1
- package/dist/features/seller/components/SellerCouponsView.js +4 -1
- package/dist/features/seller/components/SellerOffersView.js +5 -1
- package/dist/features/seller/components/SellerOrdersView.js +4 -1
- package/dist/features/seller/components/SellerPayoutsView.js +5 -1
- package/dist/features/seller/components/SellerPreOrdersView.js +4 -1
- package/dist/features/seller/components/SellerPrizeDrawsView.js +4 -1
- package/dist/features/seller/components/SellerProductsView.js +4 -1
- package/dist/features/seller/schemas/index.d.ts +10 -10
- package/dist/features/stores/api/route.js +10 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
- package/dist/features/stores/components/StorePreOrdersListing.js +2 -1
- package/dist/features/stores/components/StoreReviewsListing.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +45 -27
- package/dist/features/stores/schemas/firestore.d.ts +1 -0
- package/dist/features/stores/schemas/index.d.ts +4 -4
- package/dist/index.d.ts +8 -1
- package/dist/index.js +12 -1
- package/dist/react/hooks/useUrlTable.js +2 -1
- package/dist/seed/bids-seed-data.js +45 -44
- package/dist/seed/categories-seed-data.js +41 -40
- package/dist/seed/coupons-seed-data.js +41 -40
- package/dist/seed/products-auctions-seed-data.js +54 -53
- package/dist/seed/products-preorders-seed-data.js +25 -24
- package/dist/seed/products-prize-draws-seed-data.js +24 -23
- package/dist/seed/products-standard-seed-data.js +294 -293
- package/dist/seed/reviews-seed-data.js +61 -60
- package/dist/seed/scammers-seed-data.js +3 -2
- package/dist/seed/stores-seed-data.js +9 -8
- package/dist/seed/support-tickets-seed-data.js +13 -12
- package/dist/seed/users-seed-data.js +28 -27
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/ListingToolbar.d.ts +7 -4
- package/dist/ui/components/ListingToolbar.js +4 -3
- package/dist/ui/components/SiteLogo.js +1 -1
- package/dist/utils/sieve-builder.d.ts +41 -0
- package/dist/utils/sieve-builder.js +66 -0
- package/package.json +1 -1
|
@@ -5,66 +5,66 @@ export type ProductFilterVariant = "admin" | "seller" | "public";
|
|
|
5
5
|
export declare const PRODUCT_FILTER_KEYS: {
|
|
6
6
|
readonly admin: readonly ["category", "condition", "minPrice", "maxPrice", "brand", "seller", "tags", "status"];
|
|
7
7
|
readonly seller: readonly ["category", "condition", "minPrice", "maxPrice", "brand", "tags", "status"];
|
|
8
|
-
readonly public: readonly ["category", "condition", "minPrice", "maxPrice", "brand", "
|
|
8
|
+
readonly public: readonly ["category", "condition", "minPrice", "maxPrice", "brand", "storeId", "tags"];
|
|
9
9
|
};
|
|
10
10
|
export declare const PRODUCT_ADMIN_SORT_OPTIONS: readonly [{
|
|
11
|
-
readonly value:
|
|
11
|
+
readonly value: string;
|
|
12
12
|
readonly label: "Newest First";
|
|
13
13
|
}, {
|
|
14
|
-
readonly value:
|
|
14
|
+
readonly value: string;
|
|
15
15
|
readonly label: "Oldest First";
|
|
16
16
|
}, {
|
|
17
|
-
readonly value:
|
|
17
|
+
readonly value: string;
|
|
18
18
|
readonly label: "Price: High to Low";
|
|
19
19
|
}, {
|
|
20
|
-
readonly value:
|
|
20
|
+
readonly value: string;
|
|
21
21
|
readonly label: "Price: Low to High";
|
|
22
22
|
}, {
|
|
23
|
-
readonly value:
|
|
23
|
+
readonly value: string;
|
|
24
24
|
readonly label: "Title A-Z";
|
|
25
25
|
}, {
|
|
26
|
-
readonly value:
|
|
26
|
+
readonly value: string;
|
|
27
27
|
readonly label: "Title Z-A";
|
|
28
28
|
}, {
|
|
29
|
-
readonly value:
|
|
29
|
+
readonly value: string;
|
|
30
30
|
readonly label: "Most Viewed";
|
|
31
31
|
}];
|
|
32
32
|
export declare const PRODUCT_SELLER_SORT_OPTIONS: readonly [{
|
|
33
|
-
readonly value:
|
|
33
|
+
readonly value: string;
|
|
34
34
|
readonly label: "Newest First";
|
|
35
35
|
}, {
|
|
36
|
-
readonly value:
|
|
36
|
+
readonly value: string;
|
|
37
37
|
readonly label: "Oldest First";
|
|
38
38
|
}, {
|
|
39
|
-
readonly value:
|
|
39
|
+
readonly value: string;
|
|
40
40
|
readonly label: "Price: High to Low";
|
|
41
41
|
}, {
|
|
42
|
-
readonly value:
|
|
42
|
+
readonly value: string;
|
|
43
43
|
readonly label: "Price: Low to High";
|
|
44
44
|
}, {
|
|
45
|
-
readonly value:
|
|
45
|
+
readonly value: string;
|
|
46
46
|
readonly label: "Title A-Z";
|
|
47
47
|
}];
|
|
48
48
|
export declare const PRODUCT_PUBLIC_SORT_OPTIONS: readonly [{
|
|
49
|
-
readonly value:
|
|
49
|
+
readonly value: string;
|
|
50
50
|
readonly label: "Newest First";
|
|
51
51
|
}, {
|
|
52
|
-
readonly value:
|
|
52
|
+
readonly value: string;
|
|
53
53
|
readonly label: "Oldest First";
|
|
54
54
|
}, {
|
|
55
|
-
readonly value:
|
|
55
|
+
readonly value: string;
|
|
56
56
|
readonly label: "Price: High to Low";
|
|
57
57
|
}, {
|
|
58
|
-
readonly value:
|
|
58
|
+
readonly value: string;
|
|
59
59
|
readonly label: "Price: Low to High";
|
|
60
60
|
}, {
|
|
61
|
-
readonly value:
|
|
61
|
+
readonly value: string;
|
|
62
62
|
readonly label: "Title A–Z";
|
|
63
63
|
}, {
|
|
64
|
-
readonly value:
|
|
64
|
+
readonly value: string;
|
|
65
65
|
readonly label: "Title Z–A";
|
|
66
66
|
}, {
|
|
67
|
-
readonly value:
|
|
67
|
+
readonly value: string;
|
|
68
68
|
readonly label: "Most Viewed";
|
|
69
69
|
}];
|
|
70
70
|
export declare function getProductFilterKeys(variant: ProductFilterVariant): readonly string[];
|
|
@@ -5,60 +5,63 @@ import { FilterFacetSection } from "../../filters/FilterFacetSection";
|
|
|
5
5
|
import { RangeFilter } from "../../filters/RangeFilter";
|
|
6
6
|
import { SwitchFilter } from "../../filters/SwitchFilter";
|
|
7
7
|
import { Div } from "../../../ui";
|
|
8
|
+
import { TABLE_KEYS } from "../../../constants/table-keys";
|
|
9
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
10
|
+
import { sortBy } from "../../../constants/sort";
|
|
8
11
|
export const PRODUCT_FILTER_KEYS = {
|
|
9
12
|
admin: [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
TABLE_KEYS.CATEGORY,
|
|
14
|
+
TABLE_KEYS.CONDITION,
|
|
15
|
+
TABLE_KEYS.MIN_PRICE,
|
|
16
|
+
TABLE_KEYS.MAX_PRICE,
|
|
17
|
+
TABLE_KEYS.BRAND,
|
|
18
|
+
TABLE_KEYS.SELLER,
|
|
19
|
+
TABLE_KEYS.TAGS,
|
|
20
|
+
TABLE_KEYS.STATUS,
|
|
18
21
|
],
|
|
19
22
|
seller: [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
TABLE_KEYS.CATEGORY,
|
|
24
|
+
TABLE_KEYS.CONDITION,
|
|
25
|
+
TABLE_KEYS.MIN_PRICE,
|
|
26
|
+
TABLE_KEYS.MAX_PRICE,
|
|
27
|
+
TABLE_KEYS.BRAND,
|
|
28
|
+
TABLE_KEYS.TAGS,
|
|
29
|
+
TABLE_KEYS.STATUS,
|
|
27
30
|
],
|
|
28
31
|
public: [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
TABLE_KEYS.CATEGORY,
|
|
33
|
+
TABLE_KEYS.CONDITION,
|
|
34
|
+
TABLE_KEYS.MIN_PRICE,
|
|
35
|
+
TABLE_KEYS.MAX_PRICE,
|
|
36
|
+
TABLE_KEYS.BRAND,
|
|
37
|
+
TABLE_KEYS.STORE_ID,
|
|
38
|
+
TABLE_KEYS.TAGS,
|
|
36
39
|
],
|
|
37
40
|
};
|
|
38
41
|
export const PRODUCT_ADMIN_SORT_OPTIONS = [
|
|
39
|
-
{ value:
|
|
40
|
-
{ value: "
|
|
41
|
-
{ value:
|
|
42
|
-
{ value: "
|
|
43
|
-
{ value: "
|
|
44
|
-
{ value:
|
|
45
|
-
{ value:
|
|
42
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
43
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
|
|
44
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE), label: "Price: High to Low" },
|
|
45
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Price: Low to High" },
|
|
46
|
+
{ value: sortBy(PRODUCT_FIELDS.TITLE, "ASC"), label: "Title A-Z" },
|
|
47
|
+
{ value: sortBy(PRODUCT_FIELDS.TITLE), label: "Title Z-A" },
|
|
48
|
+
{ value: sortBy(PRODUCT_FIELDS.VIEW_COUNT), label: "Most Viewed" },
|
|
46
49
|
];
|
|
47
50
|
export const PRODUCT_SELLER_SORT_OPTIONS = [
|
|
48
|
-
{ value:
|
|
49
|
-
{ value: "
|
|
50
|
-
{ value:
|
|
51
|
-
{ value: "
|
|
52
|
-
{ value: "
|
|
51
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
52
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
|
|
53
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE), label: "Price: High to Low" },
|
|
54
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Price: Low to High" },
|
|
55
|
+
{ value: sortBy(PRODUCT_FIELDS.TITLE, "ASC"), label: "Title A-Z" },
|
|
53
56
|
];
|
|
54
57
|
export const PRODUCT_PUBLIC_SORT_OPTIONS = [
|
|
55
|
-
{ value:
|
|
56
|
-
{ value: "
|
|
57
|
-
{ value:
|
|
58
|
-
{ value: "
|
|
59
|
-
{ value: "
|
|
60
|
-
{ value:
|
|
61
|
-
{ value:
|
|
58
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
59
|
+
{ value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
|
|
60
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE), label: "Price: High to Low" },
|
|
61
|
+
{ value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Price: Low to High" },
|
|
62
|
+
{ value: sortBy(PRODUCT_FIELDS.TITLE, "ASC"), label: "Title A–Z" },
|
|
63
|
+
{ value: sortBy(PRODUCT_FIELDS.TITLE), label: "Title Z–A" },
|
|
64
|
+
{ value: sortBy(PRODUCT_FIELDS.VIEW_COUNT), label: "Most Viewed" },
|
|
62
65
|
];
|
|
63
66
|
export function getProductFilterKeys(variant) {
|
|
64
67
|
return PRODUCT_FILTER_KEYS[variant];
|
|
@@ -79,31 +82,31 @@ export function ProductFilters({ table, categoryOptions = [], brandOptions = [],
|
|
|
79
82
|
const resolvedStoreOptions = storeOptions.length > 0 ? storeOptions : (sellerOptions ?? []);
|
|
80
83
|
const t = useTranslations("filters");
|
|
81
84
|
const conditionOptions = [
|
|
82
|
-
{ value:
|
|
83
|
-
{ value:
|
|
84
|
-
{ value:
|
|
85
|
-
{ value:
|
|
85
|
+
{ value: PRODUCT_FIELDS.CONDITION_VALUES.NEW, label: t("conditionNew") },
|
|
86
|
+
{ value: PRODUCT_FIELDS.CONDITION_VALUES.USED, label: t("conditionUsed") },
|
|
87
|
+
{ value: PRODUCT_FIELDS.CONDITION_VALUES.REFURBISHED, label: t("conditionRefurbished") },
|
|
88
|
+
{ value: PRODUCT_FIELDS.CONDITION_VALUES.BROKEN, label: t("conditionBroken") },
|
|
86
89
|
];
|
|
87
90
|
const defaultStatusOptions = [
|
|
88
|
-
{ value:
|
|
89
|
-
{ value:
|
|
90
|
-
{ value:
|
|
91
|
+
{ value: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED, label: t("statusPublished") },
|
|
92
|
+
{ value: PRODUCT_FIELDS.STATUS_VALUES.DRAFT, label: t("statusDraft") },
|
|
93
|
+
{ value: PRODUCT_FIELDS.STATUS_VALUES.OUT_OF_STOCK, label: t("statusOutOfStock") },
|
|
91
94
|
];
|
|
92
|
-
const selectedCategories = table.get(
|
|
93
|
-
? table.get(
|
|
95
|
+
const selectedCategories = table.get(TABLE_KEYS.CATEGORY)
|
|
96
|
+
? table.get(TABLE_KEYS.CATEGORY).split("|").filter(Boolean)
|
|
94
97
|
: [];
|
|
95
|
-
const selectedBrands = table.get(
|
|
96
|
-
const selectedSellers = table.get(
|
|
97
|
-
const selectedConditions = table.get(
|
|
98
|
-
? table.get(
|
|
98
|
+
const selectedBrands = table.get(TABLE_KEYS.BRAND) ? [table.get(TABLE_KEYS.BRAND)] : [];
|
|
99
|
+
const selectedSellers = table.get(TABLE_KEYS.STORE_ID) ? [table.get(TABLE_KEYS.STORE_ID)] : [];
|
|
100
|
+
const selectedConditions = table.get(TABLE_KEYS.CONDITION)
|
|
101
|
+
? table.get(TABLE_KEYS.CONDITION).split("|").filter(Boolean)
|
|
99
102
|
: [];
|
|
100
|
-
const selectedTags = table.get(
|
|
101
|
-
? table.get(
|
|
103
|
+
const selectedTags = table.get(TABLE_KEYS.TAGS)
|
|
104
|
+
? table.get(TABLE_KEYS.TAGS).split("|").filter(Boolean)
|
|
102
105
|
: [];
|
|
103
|
-
const selectedStatuses = table.get(
|
|
104
|
-
? table.get(
|
|
106
|
+
const selectedStatuses = table.get(TABLE_KEYS.STATUS)
|
|
107
|
+
? table.get(TABLE_KEYS.STATUS).split("|").filter(Boolean)
|
|
105
108
|
: [];
|
|
106
109
|
const resolvedVariant = variant ?? (showStatus ? "admin" : "public");
|
|
107
110
|
const shouldShowStatus = resolvedVariant !== "public" || showStatus;
|
|
108
|
-
return (_jsxs(Div, { children: [categoryOptions.length > 0 && (_jsx(FilterFacetSection, { title: t("category"), options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set(
|
|
111
|
+
return (_jsxs(Div, { children: [categoryOptions.length > 0 && (_jsx(FilterFacetSection, { title: t("category"), options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set(TABLE_KEYS.CATEGORY, vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })), _jsx(FilterFacetSection, { title: t("condition"), options: conditionOptions, selected: selectedConditions, onChange: (vals) => table.set(TABLE_KEYS.CONDITION, vals.join("|")), searchable: false, defaultCollapsed: false }), _jsx(RangeFilter, { title: t("priceRange"), minValue: table.get(TABLE_KEYS.MIN_PRICE), maxValue: table.get(TABLE_KEYS.MAX_PRICE), onMinChange: (v) => table.set(TABLE_KEYS.MIN_PRICE, v), onMaxChange: (v) => table.set(TABLE_KEYS.MAX_PRICE, v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 500000, step: 500, minPlaceholder: t("minPrice"), maxPlaceholder: t("maxPrice"), defaultCollapsed: false }), brandOptions.length > 0 && (_jsx(FilterFacetSection, { title: t("brand"), options: brandOptions, selected: selectedBrands, onChange: (vals) => table.set(TABLE_KEYS.BRAND, vals[0] ?? ""), searchable: brandOptions.length > 4, defaultCollapsed: brandOptions.length > 6 })), resolvedStoreOptions.length > 0 && (_jsx(FilterFacetSection, { title: t("store"), options: resolvedStoreOptions, selected: selectedSellers, onChange: (vals) => table.set(TABLE_KEYS.STORE_ID, vals[0] ?? ""), searchable: resolvedStoreOptions.length > 4, defaultCollapsed: resolvedStoreOptions.length > 6 })), showShipping && (_jsx(SwitchFilter, { title: t("shipping"), label: t("freeShippingOnly"), checked: table.get(TABLE_KEYS.FREE_SHIPPING) === "true", onChange: (v) => table.set(TABLE_KEYS.FREE_SHIPPING, v ? "true" : ""), defaultCollapsed: false })), tagOptions.length > 0 && (_jsx(FilterFacetSection, { title: t("tags"), options: tagOptions, selected: selectedTags, onChange: (vals) => table.set(TABLE_KEYS.TAGS, vals.join("|")), searchable: tagOptions.length > 4, defaultCollapsed: tagOptions.length > 6 })), shouldShowStatus && (_jsx(FilterFacetSection, { title: t("status"), options: statusOptions ?? defaultStatusOptions, selected: selectedStatuses, onChange: (vals) => table.set(TABLE_KEYS.STATUS, vals.join("|")), searchable: false, defaultCollapsed: false }))] }));
|
|
109
112
|
}
|
|
@@ -5,7 +5,7 @@ import { X, ShoppingCart, Heart, SlidersHorizontal, Columns } from "lucide-react
|
|
|
5
5
|
import { useRouter } from "next/navigation";
|
|
6
6
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
7
7
|
import { useProducts } from "../hooks/useProducts";
|
|
8
|
-
import { Pagination, useToast,
|
|
8
|
+
import { Pagination, useToast, BulkActionBar, ListingToolbar } from "../../../ui";
|
|
9
9
|
import { ACTION_ID, ACTION_META, COMPARE_MAX_ITEMS } from "../constants/action-defs";
|
|
10
10
|
import { CompareOverlay } from "./CompareOverlay";
|
|
11
11
|
import { ROUTES } from "../../../next";
|
|
@@ -15,16 +15,20 @@ import { useGuestWishlist } from "../../wishlist/hooks/useGuestWishlist";
|
|
|
15
15
|
import { pushCartOp, pushWishlistOp } from "../../cart/utils/pending-ops";
|
|
16
16
|
import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
|
|
17
17
|
import { useCategoryTree, categoriesToFacetOptions } from "../../categories/hooks/useCategoryTree";
|
|
18
|
-
|
|
18
|
+
import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
|
|
19
|
+
import { sortBy } from "../../../constants/sort";
|
|
20
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
21
|
+
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
22
|
+
const FILTER_KEYS = [TABLE_KEYS.CATEGORY, TABLE_KEYS.CONDITION, TABLE_KEYS.MIN_PRICE, TABLE_KEYS.MAX_PRICE, TABLE_KEYS.BRAND, TABLE_KEYS.STORE_ID, TABLE_KEYS.FREE_SHIPPING, TABLE_KEYS.TAGS];
|
|
19
23
|
export function ProductsIndexListing({ initialData }) {
|
|
20
24
|
const router = useRouter();
|
|
21
|
-
const table = useUrlTable({ defaults: { pageSize: "24", sort:
|
|
25
|
+
const table = useUrlTable({ defaults: { pageSize: "24", sort: DEFAULT_SORT } });
|
|
22
26
|
const { showToast } = useToast();
|
|
23
|
-
const [searchInput, setSearchInput] = useState(table.get(
|
|
27
|
+
const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
|
|
24
28
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
25
29
|
const [compareIds, setCompareIds] = useState([]);
|
|
26
|
-
const showSold = table.get(
|
|
27
|
-
const [view, setView] = useState(table.get(
|
|
30
|
+
const showSold = table.get(TABLE_KEYS.SHOW_SOLD) === "true";
|
|
31
|
+
const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
|
|
28
32
|
// Pending filter state — buffered until "Apply Filters" clicked
|
|
29
33
|
const [pendingFilters, setPendingFilters] = useState(() => Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
|
|
30
34
|
const pendingTable = useMemo(() => ({
|
|
@@ -68,16 +72,16 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
68
72
|
setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, ""])));
|
|
69
73
|
}, []);
|
|
70
74
|
const resetAll = useCallback(() => {
|
|
71
|
-
const updates = {
|
|
75
|
+
const updates = { [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "", [TABLE_KEYS.SHOW_SOLD]: "" };
|
|
72
76
|
for (const k of FILTER_KEYS)
|
|
73
77
|
updates[k] = "";
|
|
74
78
|
table.setMany(updates);
|
|
75
79
|
setSearchInput("");
|
|
76
80
|
}, [table]);
|
|
77
81
|
const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
|
|
78
|
-
const hasActiveState = !!table.get(
|
|
79
|
-
table.get(
|
|
80
|
-
table.get(
|
|
82
|
+
const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
|
|
83
|
+
table.get(TABLE_KEYS.SHOW_SOLD) === "true" ||
|
|
84
|
+
table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
|
|
81
85
|
activeFilterCount > 0;
|
|
82
86
|
const localCart = useGuestCart();
|
|
83
87
|
const localWishlist = useGuestWishlist();
|
|
@@ -85,32 +89,36 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
85
89
|
const { categories } = useCategoryTree();
|
|
86
90
|
const categoryOptions = categoriesToFacetOptions(categories);
|
|
87
91
|
const params = {
|
|
88
|
-
q: table.get(
|
|
89
|
-
category: table.get(
|
|
90
|
-
minPrice: table.get(
|
|
91
|
-
maxPrice: table.get(
|
|
92
|
-
condition: table.get(
|
|
93
|
-
brand: table.get(
|
|
94
|
-
storeId: table.get(
|
|
95
|
-
freeShipping: table.get(
|
|
96
|
-
sort: table.get(
|
|
97
|
-
page: table.getNumber(
|
|
98
|
-
perPage: table.getNumber(
|
|
92
|
+
q: table.get(TABLE_KEYS.QUERY) || undefined,
|
|
93
|
+
category: table.get(TABLE_KEYS.CATEGORY) || undefined,
|
|
94
|
+
minPrice: table.get(TABLE_KEYS.MIN_PRICE) ? Number(table.get(TABLE_KEYS.MIN_PRICE)) : undefined,
|
|
95
|
+
maxPrice: table.get(TABLE_KEYS.MAX_PRICE) ? Number(table.get(TABLE_KEYS.MAX_PRICE)) : undefined,
|
|
96
|
+
condition: table.get(TABLE_KEYS.CONDITION) || undefined,
|
|
97
|
+
brand: table.get(TABLE_KEYS.BRAND) || undefined,
|
|
98
|
+
storeId: table.get(TABLE_KEYS.STORE_ID) || undefined,
|
|
99
|
+
freeShipping: table.get(TABLE_KEYS.FREE_SHIPPING) === "true" ? true : undefined,
|
|
100
|
+
sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
|
|
101
|
+
page: table.getNumber(TABLE_KEYS.PAGE, 1),
|
|
102
|
+
perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
|
|
99
103
|
listingType: "standard",
|
|
100
|
-
|
|
104
|
+
// Hide sold-out items by default. Uses stockQuantity>0 (always-present field)
|
|
105
|
+
// instead of status=="published" because sellers don't actively transition status.
|
|
106
|
+
inStock: showSold ? undefined : true,
|
|
101
107
|
};
|
|
102
108
|
const { products, totalPages, page, isLoading } = useProducts(params, { initialData });
|
|
103
109
|
const selection = useBulkSelection({ items: products, keyExtractor: (p) => p.id });
|
|
104
110
|
const commitSearch = useCallback(() => {
|
|
105
|
-
table.set(
|
|
111
|
+
table.set(TABLE_KEYS.QUERY, searchInput.trim());
|
|
106
112
|
}, [searchInput, table]);
|
|
107
113
|
const handleSearchKeyDown = (e) => {
|
|
108
114
|
if (e.key === "Enter")
|
|
109
115
|
commitSearch();
|
|
110
116
|
};
|
|
111
117
|
const handleViewToggle = (next) => {
|
|
118
|
+
if (next === VIEW_MODE.TABLE)
|
|
119
|
+
return;
|
|
112
120
|
setView(next);
|
|
113
|
-
table.set(
|
|
121
|
+
table.set(TABLE_KEYS.VIEW, next);
|
|
114
122
|
};
|
|
115
123
|
const handleWishlistToggle = useCallback((productId) => {
|
|
116
124
|
const isWishlisted = wishlistedIds.has(productId);
|
|
@@ -143,9 +151,9 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
143
151
|
pushCartOp({ op: "add", productId: product.id, quantity: 1, productTitle: product.title, productImage: product.mainImage, price: product.price });
|
|
144
152
|
router.push(String(ROUTES.USER.CART));
|
|
145
153
|
}, [localCart, router]);
|
|
146
|
-
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(
|
|
154
|
+
return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PRODUCT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection, extra: _jsxs("label", { className: "flex items-center gap-1.5 cursor-pointer select-none shrink-0", children: [_jsx("span", { className: "hidden sm:inline text-xs text-zinc-600 dark:text-zinc-300 whitespace-nowrap", children: "Show sold" }), _jsx("button", { type: "button", role: "switch", "aria-checked": showSold, onClick: () => table.set(TABLE_KEYS.SHOW_SOLD, showSold ? "" : "true"), className: `relative inline-flex h-5 w-9 flex-shrink-0 items-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1 ${showSold ? "bg-primary" : "bg-zinc-300 dark:bg-slate-600"}`, children: _jsx("span", { className: `inline-block h-3.5 w-3.5 transform rounded-full bg-white shadow-sm transition-transform duration-200 ${showSold ? "translate-x-[19px]" : "translate-x-[3px]"}` }) })] }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
147
155
|
{
|
|
148
|
-
|
|
156
|
+
id: ACTION_ID.ADD_TO_CART,
|
|
149
157
|
label: ACTION_META[ACTION_ID.ADD_TO_CART].label,
|
|
150
158
|
icon: _jsx(ShoppingCart, { className: "h-3.5 w-3.5" }),
|
|
151
159
|
variant: "primary",
|
|
@@ -160,7 +168,7 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
160
168
|
},
|
|
161
169
|
},
|
|
162
170
|
{
|
|
163
|
-
|
|
171
|
+
id: ACTION_ID.ADD_TO_WISHLIST,
|
|
164
172
|
label: ACTION_META[ACTION_ID.ADD_TO_WISHLIST].label,
|
|
165
173
|
icon: _jsx(Heart, { className: "h-3.5 w-3.5" }),
|
|
166
174
|
variant: "secondary",
|
|
@@ -175,7 +183,7 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
175
183
|
},
|
|
176
184
|
},
|
|
177
185
|
{
|
|
178
|
-
|
|
186
|
+
id: ACTION_ID.COMPARE,
|
|
179
187
|
label: ACTION_META[ACTION_ID.COMPARE].label,
|
|
180
188
|
icon: _jsx(Columns, { className: "h-3.5 w-3.5" }),
|
|
181
189
|
variant: "secondary",
|
|
@@ -185,7 +193,7 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
185
193
|
setCompareIds(ids);
|
|
186
194
|
},
|
|
187
195
|
},
|
|
188
|
-
] }), _jsx(CompareOverlay, { isOpen: compareIds.length > 0, productIds: compareIds, productType: "product", onClose: () => {
|
|
196
|
+
] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4", children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : (_jsx(ProductGrid, { products: products, getProductHref: (p) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(p.slug || p.id)), view: view === "grid" ? "card" : "list", onWishlistToggle: handleWishlistToggle, wishlistedIds: wishlistedIds, onAddToCart: handleAddToCart, onBuyNow: handleBuyNow, selectionMode: selection.isSelecting, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle })) }), _jsx(CompareOverlay, { isOpen: compareIds.length > 0, productIds: compareIds, productType: "product", onClose: () => {
|
|
189
197
|
setCompareIds([]);
|
|
190
198
|
selection.clearSelection();
|
|
191
199
|
}, onRemove: (id) => setCompareIds((ids) => ids.filter((i) => i !== id)) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(ProductFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }))] }));
|
|
@@ -5,36 +5,44 @@ import { Container, Heading, Main, Section } from "../../../ui";
|
|
|
5
5
|
import { AdSlot } from "../../homepage/components/AdSlot";
|
|
6
6
|
import { parseListingSearchParams } from "../../../utils/listing-params";
|
|
7
7
|
import { ProductsIndexListing } from "./ProductsIndexListing";
|
|
8
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
9
|
+
import { sieveFilter, sieveMultiEq, sieveAnd, SIEVE_OP } from "../../../utils/sieve-builder";
|
|
10
|
+
import { sortBy } from "../../../constants/sort";
|
|
8
11
|
const DEFAULT_PAGE = 1;
|
|
9
12
|
const DEFAULT_PAGE_SIZE = 24;
|
|
10
|
-
const DEFAULT_SORT =
|
|
13
|
+
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
11
14
|
function sp(params, key) {
|
|
12
15
|
const v = params[key];
|
|
13
16
|
return Array.isArray(v) ? v[0] ?? "" : v ?? "";
|
|
14
17
|
}
|
|
15
18
|
function buildProductFilters(params) {
|
|
16
|
-
const parts = [
|
|
19
|
+
const parts = [
|
|
20
|
+
sieveFilter(PRODUCT_FIELDS.STATUS, SIEVE_OP.EQ, PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED),
|
|
21
|
+
sieveFilter(PRODUCT_FIELDS.LISTING_TYPE, SIEVE_OP.EQ, "standard"),
|
|
22
|
+
];
|
|
17
23
|
const condition = sp(params, "condition");
|
|
18
24
|
if (condition) {
|
|
19
25
|
const values = condition.split("|").filter(Boolean);
|
|
20
26
|
if (values.length === 1)
|
|
21
|
-
parts.push(
|
|
27
|
+
parts.push(sieveFilter(PRODUCT_FIELDS.CONDITION, SIEVE_OP.EQ, values[0]));
|
|
28
|
+
// BUG FIX: pipe is invalid for ==; expand to multiple AND clauses
|
|
22
29
|
else if (values.length > 1)
|
|
23
|
-
parts.push(
|
|
30
|
+
parts.push(sieveMultiEq(PRODUCT_FIELDS.CONDITION, values));
|
|
24
31
|
}
|
|
25
32
|
const minPrice = sp(params, "minPrice");
|
|
26
33
|
const maxPrice = sp(params, "maxPrice");
|
|
27
34
|
if (minPrice)
|
|
28
|
-
parts.push(
|
|
35
|
+
parts.push(sieveFilter(PRODUCT_FIELDS.PRICE, SIEVE_OP.GTE, minPrice));
|
|
29
36
|
if (maxPrice)
|
|
30
|
-
parts.push(
|
|
37
|
+
parts.push(sieveFilter(PRODUCT_FIELDS.PRICE, SIEVE_OP.LTE, maxPrice));
|
|
31
38
|
const storeId = sp(params, "seller");
|
|
32
39
|
if (storeId)
|
|
33
|
-
parts.push(
|
|
40
|
+
parts.push(sieveFilter(PRODUCT_FIELDS.STORE_ID, SIEVE_OP.EQ, storeId));
|
|
34
41
|
const freeShipping = sp(params, "freeShipping");
|
|
35
|
-
if (freeShipping === "true")
|
|
36
|
-
parts.push(
|
|
37
|
-
|
|
42
|
+
if (freeShipping === "true") {
|
|
43
|
+
parts.push(sieveFilter(PRODUCT_FIELDS.SHIPPING_PAID_BY, SIEVE_OP.EQ, PRODUCT_FIELDS.SHIPPING_PAID_BY_VALUES.SELLER));
|
|
44
|
+
}
|
|
45
|
+
return sieveAnd(...parts);
|
|
38
46
|
}
|
|
39
47
|
export async function ProductsIndexPageView({ searchParams = {} }) {
|
|
40
48
|
const std = parseListingSearchParams(searchParams);
|
|
@@ -46,6 +46,8 @@ export function useProducts(params = {}, opts) {
|
|
|
46
46
|
sp.set("dateTo", params.dateTo);
|
|
47
47
|
if (params.preOrderProductionStatus)
|
|
48
48
|
sp.set("preOrderProductionStatus", params.preOrderProductionStatus);
|
|
49
|
+
if (params.prizeRevealStatus)
|
|
50
|
+
sp.set("prizeRevealStatus", params.prizeRevealStatus);
|
|
49
51
|
if (params.brand)
|
|
50
52
|
sp.set("brand", params.brand);
|
|
51
53
|
if (params.freeShipping !== undefined)
|
|
@@ -4,33 +4,13 @@ import { BaseRepository, prepareForFirestore, } from "../../../providers/db-fire
|
|
|
4
4
|
import { cacheManager } from "../../../core";
|
|
5
5
|
import { generateUniqueId, slugify } from "../../../utils";
|
|
6
6
|
import { PRODUCT_COLLECTION, ProductStatusValues, } from "../schemas";
|
|
7
|
-
|
|
8
|
-
STORE_ID: "storeId",
|
|
9
|
-
STATUS: "status",
|
|
10
|
-
FEATURED: "featured",
|
|
11
|
-
CATEGORY: "category",
|
|
12
|
-
SLUG: "slug",
|
|
13
|
-
// SB1-G (S3 2026-05-13) — canonical discriminator. Legacy `isAuction` /
|
|
14
|
-
// `isPreOrder` boolean fields were removed in this session.
|
|
15
|
-
LISTING_TYPE: "listingType",
|
|
16
|
-
PRE_ORDER_DELIVERY_DATE: "preOrderDeliveryDate",
|
|
17
|
-
IS_PROMOTED: "isPromoted",
|
|
18
|
-
AUCTION_END_DATE: "auctionEndDate",
|
|
19
|
-
AVAILABLE_QUANTITY: "availableQuantity",
|
|
20
|
-
VIEW_COUNT: "viewCount",
|
|
21
|
-
};
|
|
7
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
22
8
|
/**
|
|
23
9
|
* Canonical listing-kind tokens used in `listingType`. Note: the public Sieve
|
|
24
10
|
* alias accepts the legacy "preorder" / "product" spelling; we normalise to
|
|
25
11
|
* the Firestore-stored value here.
|
|
26
12
|
*/
|
|
27
|
-
const LISTING_TYPE_VALUES =
|
|
28
|
-
AUCTION: "auction",
|
|
29
|
-
PRE_ORDER: "pre-order",
|
|
30
|
-
STANDARD: "standard",
|
|
31
|
-
PRIZE_DRAW: "prize-draw",
|
|
32
|
-
BUNDLE: "bundle",
|
|
33
|
-
};
|
|
13
|
+
const LISTING_TYPE_VALUES = PRODUCT_FIELDS.LISTING_TYPE_VALUES;
|
|
34
14
|
// Reused Sieve clauses for FILTER_ALIASES. SB1-G replaced the boolean-combo
|
|
35
15
|
// clauses with single-field `listingType==X` clauses now that every doc
|
|
36
16
|
// carries the discriminator.
|