@mohasinac/appkit 2.8.3 → 2.8.4
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/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/core/hooks/useSiteSettings.d.ts +1 -1
- package/dist/features/account/hooks/useAccount.d.ts +2 -2
- package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
- package/dist/features/account/hooks/useAddresses.d.ts +2 -2
- package/dist/features/account/hooks/useNotifications.d.ts +1 -1
- package/dist/features/account/hooks/useProfile.d.ts +1 -1
- package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
- package/dist/features/admin/components/AdminAllEventEntriesView.js +5 -3
- package/dist/features/admin/components/AdminBidsView.js +6 -4
- package/dist/features/admin/components/AdminBlogView.js +6 -4
- package/dist/features/admin/components/AdminBrandsView.js +8 -6
- package/dist/features/admin/components/AdminBundlesView.js +10 -8
- package/dist/features/admin/components/AdminCartsView.js +6 -4
- package/dist/features/admin/components/AdminCategoriesView.js +7 -5
- package/dist/features/admin/components/AdminClassifiedView.js +4 -3
- package/dist/features/admin/components/AdminContactView.js +6 -4
- package/dist/features/admin/components/AdminCouponsView.js +6 -4
- package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
- package/dist/features/admin/components/AdminFaqsView.js +5 -3
- package/dist/features/admin/components/AdminFeaturesView.js +5 -4
- package/dist/features/admin/components/AdminGroupedListingsView.js +4 -3
- package/dist/features/admin/components/AdminHistoryView.js +4 -3
- package/dist/features/admin/components/AdminLiveView.js +4 -3
- package/dist/features/admin/components/AdminNewsletterView.js +5 -3
- package/dist/features/admin/components/AdminNotificationsView.js +6 -4
- package/dist/features/admin/components/AdminOrdersView.js +6 -4
- package/dist/features/admin/components/AdminPayoutsView.js +7 -5
- package/dist/features/admin/components/AdminPrizeDrawsView.js +6 -4
- package/dist/features/admin/components/AdminProductsView.js +7 -5
- package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
- package/dist/features/admin/components/AdminReviewsView.js +8 -6
- package/dist/features/admin/components/AdminScammersView.js +8 -6
- package/dist/features/admin/components/AdminSessionsView.js +6 -4
- package/dist/features/admin/components/AdminStoreAddressesView.js +2 -1
- package/dist/features/admin/components/AdminStoresView.js +6 -4
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -5
- package/dist/features/admin/components/AdminSupportTicketsView.js +8 -6
- package/dist/features/admin/components/AdminTeamView.js +6 -4
- package/dist/features/admin/components/AdminUsersView.js +6 -4
- package/dist/features/admin/components/AdminWishlistsView.js +4 -3
- package/dist/features/admin/constants/filter-tabs.d.ts +1 -1
- package/dist/features/admin/constants/filter-tabs.js +0 -11
- package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
- package/dist/features/admin/hooks/useChat.d.ts +1 -1
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.js +4 -2
- package/dist/features/auctions/components/AuctionsListView.js +7 -6
- package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
- package/dist/features/auth/hooks/useAuth.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.js +3 -2
- package/dist/features/cart/hooks/useCart.d.ts +1 -1
- package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
- package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
- package/dist/features/cart/hooks/useOrder.d.ts +2 -2
- package/dist/features/categories/components/BrandDetailPageView.js +10 -8
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
- package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
- package/dist/features/categories/components/CategoryBundlesListing.js +5 -4
- package/dist/features/categories/components/CategoryDetailPageView.js +12 -10
- package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
- package/dist/features/categories/components/CategoryFilters.js +13 -12
- package/dist/features/categories/components/CategoryTree.d.ts +1 -1
- package/dist/features/categories/components/CategoryTree.js +1 -1
- package/dist/features/categories/hooks/useCategories.d.ts +3 -3
- package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
- package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
- package/dist/features/categories/schemas/firestore.d.ts +2 -2
- package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
- package/dist/features/checkout/actions/checkout-actions.js +1 -1
- package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
- package/dist/features/classified/components/ClassifiedListView.js +6 -5
- package/dist/features/collections/hooks/useCollections.d.ts +2 -2
- package/dist/features/cron/jobs/auction-expiry.job.d.ts +2 -2
- package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
- package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
- package/dist/features/events/actions/event-actions.js +6 -4
- package/dist/features/events/components/AdminEventEditorView.js +1 -1
- package/dist/features/events/components/AdminEventsView.js +7 -5
- package/dist/features/events/components/EventFilters.d.ts +4 -4
- package/dist/features/events/components/EventFilters.js +2 -2
- package/dist/features/events/components/EventRafflesSection.js +4 -2
- package/dist/features/events/hooks/useEvent.d.ts +3 -3
- package/dist/features/events/hooks/useEvents.d.ts +1 -1
- package/dist/features/faq/actions/faq-actions.js +4 -2
- package/dist/features/faq/components/FAQPageContent.js +2 -1
- package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
- package/dist/features/faq/hooks/useFaqList.d.ts +15 -15
- package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -2
- package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
- package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
- package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
- package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
- package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
- package/dist/features/layout/BottomActions.js +0 -27
- package/dist/features/layout/BottomActionsContext.d.ts +0 -36
- package/dist/features/layout/BottomActionsContext.js +0 -36
- package/dist/features/live/components/LiveItemsListView.js +6 -5
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
- package/dist/features/orders/hooks/useOrders.d.ts +2 -2
- package/dist/features/payments/hooks/usePayments.d.ts +1 -1
- package/dist/features/pre-orders/components/PreOrdersListView.js +5 -4
- package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
- package/dist/features/products/actions/product-actions.js +17 -15
- package/dist/features/products/columns/index.d.ts +1 -1
- package/dist/features/products/columns/index.js +1 -1
- package/dist/features/products/components/PrizeDrawCollage.js +0 -14
- package/dist/features/products/components/PrizeDrawsListingView.js +5 -4
- package/dist/features/products/components/PrizeDrawsSection.js +4 -2
- package/dist/features/products/constants/sieve.d.ts +2 -2
- package/dist/features/products/constants/sieve.js +2 -2
- package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
- package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
- package/dist/features/products/hooks/useRelatedProducts.js +5 -4
- package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
- package/dist/features/reviews/actions/review-actions.js +2 -1
- package/dist/features/reviews/components/ReviewsIndexPageView.js +7 -6
- package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
- package/dist/features/scams/actions/scam-actions.js +3 -2
- package/dist/features/scams/components/ScamRegistryView.js +5 -4
- package/dist/features/search/actions/search-actions.js +7 -6
- package/dist/features/search/hooks/useSearch.d.ts +2 -2
- package/dist/features/seller/components/CouponInlineSelect.js +2 -1
- package/dist/features/seller/components/SellerAuctionsView.js +7 -5
- package/dist/features/seller/components/SellerBidsView.js +5 -3
- package/dist/features/seller/components/SellerBundlesView.js +7 -6
- package/dist/features/seller/components/SellerClassifiedView.js +6 -5
- package/dist/features/seller/components/SellerCouponsView.js +6 -4
- package/dist/features/seller/components/SellerDigitalCodesView.js +5 -4
- package/dist/features/seller/components/SellerGroupedListingsView.js +5 -4
- package/dist/features/seller/components/SellerLiveView.js +6 -5
- package/dist/features/seller/components/SellerOffersView.js +6 -4
- package/dist/features/seller/components/SellerOrdersView.js +5 -3
- package/dist/features/seller/components/SellerPayoutMethodsView.js +3 -2
- package/dist/features/seller/components/SellerPayoutsView.js +6 -4
- package/dist/features/seller/components/SellerPreOrdersView.js +6 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +6 -4
- package/dist/features/seller/components/SellerProductsView.js +9 -7
- package/dist/features/seller/components/SellerShippingConfigsView.js +3 -2
- package/dist/features/seller/components/SellerStoreCategoriesView.js +4 -3
- package/dist/features/seller/components/SellerTemplatesView.js +4 -3
- package/dist/features/seller/components/SublistingInlineSelect.js +2 -1
- package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
- package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
- package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
- package/dist/features/stores/actions/store-query-actions.js +3 -2
- package/dist/features/stores/components/StoreAuctionsPageView.js +4 -2
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
- package/dist/features/stores/components/StorePreOrdersPageView.js +4 -2
- package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
- package/dist/features/stores/components/StoreProductsPageView.js +2 -1
- package/dist/features/stores/components/StoreProductsView.js +5 -4
- package/dist/features/stores/components/StoresIndexListing.js +4 -3
- package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
- package/dist/features/stores/hooks/useStores.d.ts +6 -6
- package/dist/features/wishlist/components/WishlistView.js +4 -3
- package/dist/features/wishlist/hooks/useUserWishlist.d.ts +15 -15
- package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CollectionItem, CollectionListItem } from "../types";
|
|
2
2
|
export declare function useCollections(opts?: {
|
|
3
3
|
endpoint?: string;
|
|
4
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
4
|
+
}): import("@tanstack/react-query").UseQueryResult<CollectionListItem[], Error>;
|
|
5
5
|
export declare function useCollection(slug: string | undefined, opts?: {
|
|
6
6
|
endpoint?: string;
|
|
7
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
7
|
+
}): import("@tanstack/react-query").UseQueryResult<CollectionItem | null, Error>;
|
|
@@ -3,7 +3,7 @@ import type { IRepository } from "../../../contracts";
|
|
|
3
3
|
* Built-in job: Close live auctions whose `endTime` has passed.
|
|
4
4
|
*
|
|
5
5
|
* Run interval: every 5 minutes (recommended).
|
|
6
|
-
* Requires an
|
|
6
|
+
* Requires an sieveFilter("IRepository", SIEVE_OP.LT, "AuctionDocument>") injected at registration time.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
@@ -23,5 +23,5 @@ interface AuctionDocument {
|
|
|
23
23
|
highestBidAmount?: number;
|
|
24
24
|
closedAt?: string;
|
|
25
25
|
}
|
|
26
|
-
export declare function createAuctionExpiryJob(auctionRepo: IRepository<AuctionDocument>): import("
|
|
26
|
+
export declare function createAuctionExpiryJob(auctionRepo: IRepository<AuctionDocument>): import("@mohasinac/appkit").CronJobDefinition;
|
|
27
27
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
1
2
|
import { createCronJob } from "../registry";
|
|
2
3
|
export function createAuctionExpiryJob(auctionRepo) {
|
|
3
4
|
return createCronJob({
|
|
@@ -9,7 +10,7 @@ export function createAuctionExpiryJob(auctionRepo) {
|
|
|
9
10
|
timeoutSeconds: 60,
|
|
10
11
|
}, async (ctx) => {
|
|
11
12
|
const result = await auctionRepo.findAll({
|
|
12
|
-
filters:
|
|
13
|
+
filters: sieveAnd(sieveFilter("status", SIEVE_OP.EQ, "live"), sieveFilter("endTime", SIEVE_OP.LTE, ctx.scheduleTime)),
|
|
13
14
|
perPage: 500,
|
|
14
15
|
});
|
|
15
16
|
let processed = 0;
|
|
@@ -10,5 +10,5 @@ interface PreOrderDocument {
|
|
|
10
10
|
status: string;
|
|
11
11
|
expectedShippingDate?: string;
|
|
12
12
|
}
|
|
13
|
-
export declare function createPreOrderReminderJob(preOrderRepo: IRepository<PreOrderDocument>): import("
|
|
13
|
+
export declare function createPreOrderReminderJob(preOrderRepo: IRepository<PreOrderDocument>): import("@mohasinac/appkit").CronJobDefinition;
|
|
14
14
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
1
2
|
import { createCronJob } from "../registry";
|
|
2
3
|
export function createPreOrderReminderJob(preOrderRepo) {
|
|
3
4
|
const sevenDaysFromNow = () => {
|
|
@@ -15,7 +16,7 @@ export function createPreOrderReminderJob(preOrderRepo) {
|
|
|
15
16
|
}, async () => {
|
|
16
17
|
const cutoff = sevenDaysFromNow();
|
|
17
18
|
const result = await preOrderRepo.findAll({
|
|
18
|
-
filters:
|
|
19
|
+
filters: sieveAnd(sieveFilter("status", SIEVE_OP.EQ, "confirmed"), sieveFilter("expectedShippingDate", SIEVE_OP.LTE, cutoff)),
|
|
19
20
|
perPage: 500,
|
|
20
21
|
});
|
|
21
22
|
let processed = 0;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
2
3
|
import { productRepository } from "../../../repositories";
|
|
3
4
|
import { Container, Heading, Main, Section } from "../../../ui";
|
|
4
5
|
import { AdSlot } from "../../homepage/components/AdSlot";
|
|
@@ -16,12 +17,12 @@ function buildDigitalCodeFilters(params) {
|
|
|
16
17
|
const minPrice = sp(params, "minPrice");
|
|
17
18
|
const maxPrice = sp(params, "maxPrice");
|
|
18
19
|
if (minPrice)
|
|
19
|
-
parts.push(
|
|
20
|
+
parts.push(sieveFilter("price", SIEVE_OP.GTE, minPrice));
|
|
20
21
|
if (maxPrice)
|
|
21
|
-
parts.push(
|
|
22
|
+
parts.push(sieveFilter("price", SIEVE_OP.LTE, maxPrice));
|
|
22
23
|
const deliveryMethod = sp(params, "deliveryMethod");
|
|
23
24
|
if (deliveryMethod)
|
|
24
|
-
parts.push(
|
|
25
|
+
parts.push(sieveFilter("digitalCodeDelivery", SIEVE_OP.EQ, deliveryMethod));
|
|
25
26
|
return parts.join(",");
|
|
26
27
|
}
|
|
27
28
|
export async function DigitalCodesListView({ searchParams = {} }) {
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Business logic for event CRUD, status changes, entries, and public access.
|
|
5
5
|
* Auth, rate-limiting, and input validation are handled by the calling server action.
|
|
6
6
|
*/
|
|
7
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
8
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
7
9
|
import { serverLogger } from "../../../monitoring";
|
|
8
10
|
import { eventRepository } from "../repository/events.repository";
|
|
9
11
|
import { eventEntryRepository } from "../repository/event-entry.repository";
|
|
@@ -108,13 +110,13 @@ export async function listPublicEvents(params) {
|
|
|
108
110
|
if (!filters) {
|
|
109
111
|
const parts = [];
|
|
110
112
|
if (sp.has("status"))
|
|
111
|
-
parts.push(
|
|
113
|
+
parts.push(sieveFilter("status", SIEVE_OP.EQ, sp.get("status")));
|
|
112
114
|
if (sp.has("type"))
|
|
113
|
-
parts.push(
|
|
115
|
+
parts.push(sieveFilter("type", SIEVE_OP.EQ, sp.get("type")));
|
|
114
116
|
if (sp.has("types")) {
|
|
115
117
|
const types = sp.get("types").split(",");
|
|
116
118
|
if (types.length === 1)
|
|
117
|
-
parts.push(
|
|
119
|
+
parts.push(sieveFilter("type", SIEVE_OP.EQ, types[0]));
|
|
118
120
|
}
|
|
119
121
|
if (parts.length)
|
|
120
122
|
filters = parts.join(",");
|
|
@@ -157,7 +159,7 @@ export async function adminGetEventById(id) {
|
|
|
157
159
|
}
|
|
158
160
|
export async function adminGetEventEntries(eventId, params) {
|
|
159
161
|
const result = await eventEntryRepository.listForEvent(eventId, {
|
|
160
|
-
sorts: "
|
|
162
|
+
sorts: sortBy("createdAt", "DESC"),
|
|
161
163
|
page: params?.page ?? 1,
|
|
162
164
|
pageSize: params?.pageSize ?? 50,
|
|
163
165
|
});
|
|
@@ -52,7 +52,7 @@ const FORM_FIELD_TYPE_OPTIONS = [
|
|
|
52
52
|
{ label: "Checkbox", value: "checkbox" },
|
|
53
53
|
{ label: "Radio", value: "radio" },
|
|
54
54
|
{ label: "Date", value: "date" },
|
|
55
|
-
{ label: "Rating (1–5)", value: "rating" },
|
|
55
|
+
{ label: "Rating (1–5)", value: "rating" }, // audit-sieve-views-ok — form field type, not sort key
|
|
56
56
|
{ label: "File upload", value: "file" },
|
|
57
57
|
];
|
|
58
58
|
const FIELD_TYPES_WITH_OPTIONS = ["select", "multiselect", "radio", "checkbox"];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
4
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
3
5
|
import React from "react";
|
|
4
6
|
import { FilterChipGroup, ListingLayout } from "../../../ui";
|
|
5
7
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
@@ -29,13 +31,13 @@ export function AdminEventsView({ children, ...props }) {
|
|
|
29
31
|
searchPlaceholder: "Search events by title or type",
|
|
30
32
|
emptyLabel: "No events found",
|
|
31
33
|
filterKeys: ["status", "type"],
|
|
32
|
-
defaultSort: "
|
|
34
|
+
defaultSort: sortBy("startsAt", "DESC"),
|
|
33
35
|
queryKey: ["admin", "events", "listing"],
|
|
34
36
|
endpoint: ADMIN_ENDPOINTS.EVENTS,
|
|
35
37
|
sortOptions: [
|
|
36
|
-
{ value: "
|
|
38
|
+
{ value: sortBy("startsAt", "DESC"), label: "Starting soonest" },
|
|
37
39
|
{ value: "startsAt", label: "Starting latest" },
|
|
38
|
-
{ value: "
|
|
40
|
+
{ value: sortBy("createdAt", "DESC"), label: "Newest" },
|
|
39
41
|
{ value: "title", label: "Title A–Z" },
|
|
40
42
|
],
|
|
41
43
|
mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
|
|
@@ -51,9 +53,9 @@ export function AdminEventsView({ children, ...props }) {
|
|
|
51
53
|
buildFilters: (state) => {
|
|
52
54
|
const parts = [];
|
|
53
55
|
if (state.status && state.status !== "All")
|
|
54
|
-
parts.push(
|
|
56
|
+
parts.push(sieveFilter("status", SIEVE_OP.EQ, state.status));
|
|
55
57
|
if (state.type && state.type !== "All")
|
|
56
|
-
parts.push(
|
|
58
|
+
parts.push(sieveFilter("type", SIEVE_OP.EQ, state.type));
|
|
57
59
|
return parts.join(",") || undefined;
|
|
58
60
|
},
|
|
59
61
|
primaryAction: {
|
|
@@ -24,7 +24,7 @@ export declare const EVENT_ADMIN_SORT_OPTIONS: readonly [{
|
|
|
24
24
|
readonly value: string;
|
|
25
25
|
readonly label: "Ends Soonest";
|
|
26
26
|
}, {
|
|
27
|
-
readonly value:
|
|
27
|
+
readonly value: string;
|
|
28
28
|
readonly label: "Most Entries";
|
|
29
29
|
}, {
|
|
30
30
|
readonly value: string;
|
|
@@ -49,7 +49,7 @@ export declare const EVENT_SELLER_SORT_OPTIONS: readonly [{
|
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Ends Soonest";
|
|
51
51
|
}, {
|
|
52
|
-
readonly value:
|
|
52
|
+
readonly value: string;
|
|
53
53
|
readonly label: "Most Entries";
|
|
54
54
|
}, {
|
|
55
55
|
readonly value: string;
|
|
@@ -68,7 +68,7 @@ export declare const EVENT_PUBLIC_SORT_OPTIONS: readonly [{
|
|
|
68
68
|
readonly value: string;
|
|
69
69
|
readonly label: "Title Z–A";
|
|
70
70
|
}, {
|
|
71
|
-
readonly value:
|
|
71
|
+
readonly value: string;
|
|
72
72
|
readonly label: "Most Entries";
|
|
73
73
|
}];
|
|
74
74
|
export declare const EVENT_SORT_OPTIONS: readonly [{
|
|
@@ -90,7 +90,7 @@ export declare const EVENT_SORT_OPTIONS: readonly [{
|
|
|
90
90
|
readonly value: string;
|
|
91
91
|
readonly label: "Ends Soonest";
|
|
92
92
|
}, {
|
|
93
|
-
readonly value:
|
|
93
|
+
readonly value: string;
|
|
94
94
|
readonly label: "Most Entries";
|
|
95
95
|
}, {
|
|
96
96
|
readonly value: string;
|
|
@@ -20,7 +20,7 @@ export const EVENT_ADMIN_SORT_OPTIONS = [
|
|
|
20
20
|
{ value: sortBy(EVENT_FIELDS.STARTS_AT, "ASC"), label: "Starts Soonest" },
|
|
21
21
|
{ value: sortBy(EVENT_FIELDS.ENDS_AT), label: "Ends Latest" },
|
|
22
22
|
{ value: sortBy(EVENT_FIELDS.ENDS_AT, "ASC"), label: "Ends Soonest" },
|
|
23
|
-
{ value: "
|
|
23
|
+
{ value: sortBy("stats.totalEntries", "DESC"), label: "Most Entries" },
|
|
24
24
|
{ value: sortBy(EVENT_FIELDS.CREATED_AT), label: "Newest First" },
|
|
25
25
|
];
|
|
26
26
|
export const EVENT_SELLER_SORT_OPTIONS = EVENT_ADMIN_SORT_OPTIONS;
|
|
@@ -29,7 +29,7 @@ export const EVENT_PUBLIC_SORT_OPTIONS = [
|
|
|
29
29
|
{ value: sortBy(EVENT_FIELDS.STARTS_AT), label: "Starts Latest" },
|
|
30
30
|
{ value: sortBy(EVENT_FIELDS.TITLE, "ASC"), label: "Title A–Z" },
|
|
31
31
|
{ value: sortBy(EVENT_FIELDS.TITLE), label: "Title Z–A" },
|
|
32
|
-
{ value: "
|
|
32
|
+
{ value: sortBy("stats.totalEntries", "DESC"), label: "Most Entries" },
|
|
33
33
|
];
|
|
34
34
|
// Backward-compatible alias.
|
|
35
35
|
export const EVENT_SORT_OPTIONS = EVENT_ADMIN_SORT_OPTIONS;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
3
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
2
4
|
import Link from "next/link";
|
|
3
5
|
import { Container, Div, Heading, Section, Stack, Text, } from "../../../ui";
|
|
4
6
|
import { ROUTES } from "../../../next";
|
|
@@ -15,8 +17,8 @@ export async function EventRafflesSection({ config, }) {
|
|
|
15
17
|
let events = [];
|
|
16
18
|
try {
|
|
17
19
|
const result = await eventRepository.list({
|
|
18
|
-
filters: "hasRaffle
|
|
19
|
-
sorts: "
|
|
20
|
+
filters: sieveAnd(sieveFilter("hasRaffle", SIEVE_OP.EQ, "true"), sieveFilter("status", SIEVE_OP.EQ, "active")),
|
|
21
|
+
sorts: sortBy("startsAt", "DESC"),
|
|
20
22
|
pageSize: limit,
|
|
21
23
|
});
|
|
22
24
|
events = (result.items ?? []);
|
|
@@ -16,7 +16,7 @@ export declare function useEvent<T extends EventItem = EventItem>(id: string, op
|
|
|
16
16
|
event: T | null;
|
|
17
17
|
isLoading: boolean;
|
|
18
18
|
error: string | null;
|
|
19
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
19
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<EventItem | null, Error>>;
|
|
20
20
|
};
|
|
21
21
|
export declare function useEventEntries(eventId: string, params?: {
|
|
22
22
|
page?: number;
|
|
@@ -30,13 +30,13 @@ export declare function useEventEntries(eventId: string, params?: {
|
|
|
30
30
|
total: number;
|
|
31
31
|
isLoading: boolean;
|
|
32
32
|
error: string | null;
|
|
33
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
33
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<EventEntryListResponse, Error>>;
|
|
34
34
|
};
|
|
35
35
|
export declare function useEventLeaderboard(eventId: string, limit?: number, opts?: {
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
endpoint?: string;
|
|
38
38
|
}): {
|
|
39
|
-
leaderboard:
|
|
39
|
+
leaderboard: LeaderboardEntry[];
|
|
40
40
|
isLoading: boolean;
|
|
41
41
|
error: string | null;
|
|
42
42
|
};
|
|
@@ -23,6 +23,6 @@ export declare function useEvents<T extends EventItem = EventItem>(params?: Even
|
|
|
23
23
|
hasMore: boolean;
|
|
24
24
|
isLoading: boolean;
|
|
25
25
|
error: string | null;
|
|
26
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
26
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<EventListResponse, Error>>;
|
|
27
27
|
};
|
|
28
28
|
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { serverLogger } from "../../../monitoring";
|
|
4
|
+
import { sortBy } from "../../../constants/sort";
|
|
3
5
|
import { faqsRepository } from "../repository/faqs.repository";
|
|
4
6
|
// --- Schemas --------------------------------------------------------------
|
|
5
7
|
const faqBaseSchema = z.object({
|
|
@@ -89,10 +91,10 @@ export async function listFaqs(params) {
|
|
|
89
91
|
export async function listPublicFaqs(category, limit = 20) {
|
|
90
92
|
const filters = ["isActive==true"];
|
|
91
93
|
if (category)
|
|
92
|
-
filters.push(
|
|
94
|
+
filters.push(sieveFilter("category", SIEVE_OP.EQ, category));
|
|
93
95
|
const result = await faqsRepository.list({
|
|
94
96
|
filters: filters.join(","),
|
|
95
|
-
sorts: "
|
|
97
|
+
sorts: [sortBy("priority", "DESC"), sortBy("order", "ASC")].join(","),
|
|
96
98
|
page: 1,
|
|
97
99
|
pageSize: limit,
|
|
98
100
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Div, Heading, Input, SlottedListingView, Text } from "../../../ui";
|
|
4
|
+
import { sortBy } from "../../../constants/sort";
|
|
4
5
|
import { FAQCategorySidebar } from "./FAQCategorySidebar";
|
|
5
6
|
import { FAQSortDropdown } from "./FAQSortDropdown";
|
|
6
7
|
import { FAQAccordion } from "./FAQAccordion";
|
|
@@ -22,7 +23,7 @@ export function FAQPageContent({ initialCategory = "all", categories, routeHelpe
|
|
|
22
23
|
});
|
|
23
24
|
const { faqs: allMatchingFaqs } = useFaqList({
|
|
24
25
|
search: searchValue.trim() || undefined,
|
|
25
|
-
sorts: "
|
|
26
|
+
sorts: [sortBy("priority", "DESC"), sortBy("order", "ASC")].join(","),
|
|
26
27
|
page: 1,
|
|
27
28
|
pageSize: 200,
|
|
28
29
|
});
|
|
@@ -14,7 +14,7 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
14
14
|
faqs: import("..").FAQ[];
|
|
15
15
|
total: number;
|
|
16
16
|
categories: readonly string[];
|
|
17
|
-
data:
|
|
17
|
+
data: FAQListResponse;
|
|
18
18
|
error: Error;
|
|
19
19
|
isError: true;
|
|
20
20
|
isPending: false;
|
|
@@ -37,14 +37,14 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
37
37
|
isRefetching: boolean;
|
|
38
38
|
isStale: boolean;
|
|
39
39
|
isEnabled: boolean;
|
|
40
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
40
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
41
41
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
42
|
-
promise: Promise<
|
|
42
|
+
promise: Promise<FAQListResponse>;
|
|
43
43
|
} | {
|
|
44
44
|
faqs: import("..").FAQ[];
|
|
45
45
|
total: number;
|
|
46
46
|
categories: readonly string[];
|
|
47
|
-
data:
|
|
47
|
+
data: FAQListResponse;
|
|
48
48
|
error: null;
|
|
49
49
|
isError: false;
|
|
50
50
|
isPending: false;
|
|
@@ -67,9 +67,9 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
67
67
|
isRefetching: boolean;
|
|
68
68
|
isStale: boolean;
|
|
69
69
|
isEnabled: boolean;
|
|
70
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
70
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
71
71
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
72
|
-
promise: Promise<
|
|
72
|
+
promise: Promise<FAQListResponse>;
|
|
73
73
|
} | {
|
|
74
74
|
faqs: import("..").FAQ[];
|
|
75
75
|
total: number;
|
|
@@ -97,9 +97,9 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
97
97
|
isRefetching: boolean;
|
|
98
98
|
isStale: boolean;
|
|
99
99
|
isEnabled: boolean;
|
|
100
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
100
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
101
101
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
102
|
-
promise: Promise<
|
|
102
|
+
promise: Promise<FAQListResponse>;
|
|
103
103
|
} | {
|
|
104
104
|
faqs: import("..").FAQ[];
|
|
105
105
|
total: number;
|
|
@@ -127,9 +127,9 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
127
127
|
isRefetching: boolean;
|
|
128
128
|
isStale: boolean;
|
|
129
129
|
isEnabled: boolean;
|
|
130
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
130
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
131
131
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
132
|
-
promise: Promise<
|
|
132
|
+
promise: Promise<FAQListResponse>;
|
|
133
133
|
} | {
|
|
134
134
|
faqs: import("..").FAQ[];
|
|
135
135
|
total: number;
|
|
@@ -157,14 +157,14 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
157
157
|
isRefetching: boolean;
|
|
158
158
|
isStale: boolean;
|
|
159
159
|
isEnabled: boolean;
|
|
160
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
160
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
161
161
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
162
|
-
promise: Promise<
|
|
162
|
+
promise: Promise<FAQListResponse>;
|
|
163
163
|
} | {
|
|
164
164
|
faqs: import("..").FAQ[];
|
|
165
165
|
total: number;
|
|
166
166
|
categories: readonly string[];
|
|
167
|
-
data:
|
|
167
|
+
data: FAQListResponse;
|
|
168
168
|
isError: false;
|
|
169
169
|
error: null;
|
|
170
170
|
isPending: false;
|
|
@@ -187,8 +187,8 @@ export declare function useFaqList(options?: UseFaqListOptions): {
|
|
|
187
187
|
isRefetching: boolean;
|
|
188
188
|
isStale: boolean;
|
|
189
189
|
isEnabled: boolean;
|
|
190
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
190
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<FAQListResponse, Error>>;
|
|
191
191
|
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
192
|
-
promise: Promise<
|
|
192
|
+
promise: Promise<FAQListResponse>;
|
|
193
193
|
};
|
|
194
194
|
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
|
|
3
|
+
import { sortBy } from "@mohasinac/appkit";
|
|
2
4
|
import { Main } from "../../../ui";
|
|
3
5
|
import { carouselRepository, faqsRepository, siteSettingsRepository } from "../../../repositories";
|
|
4
6
|
import { fetchLiveStats } from "../lib/live-stats";
|
|
@@ -78,9 +80,9 @@ export async function MarketplaceHomepageView({ adSlots, newsletterFormSlot, onB
|
|
|
78
80
|
activeTypes.has("categories") ? listTopLevelCategories(12).catch(() => null) : null,
|
|
79
81
|
activeTypes.has("brands") ? listBrandCategories(12).catch(() => null) : null,
|
|
80
82
|
activeTypes.has("featured-bundles") ? listFeaturedBundles(8).catch(() => null) : null,
|
|
81
|
-
activeTypes.has("stores") ? listStores({ pageSize: 8, sorts: "
|
|
83
|
+
activeTypes.has("stores") ? listStores({ pageSize: 8, sorts: sortBy("averageRating", "DESC") }).catch(() => null) : null,
|
|
82
84
|
activeTypes.has("blog-articles") ? getFeaturedBlogPosts(6).catch(() => null) : null,
|
|
83
|
-
activeTypes.has("events") ? listPublicEvents({ filters: "status
|
|
85
|
+
activeTypes.has("events") ? listPublicEvents({ filters: sieveFilter("status", SIEVE_OP.EQ, "active"), pageSize: 6 }).catch(() => null) : null,
|
|
84
86
|
]);
|
|
85
87
|
// ProductDocument / BlogDocument / EventDocument have Date fields and extra Firestore-only
|
|
86
88
|
// fields absent from the corresponding *Item types. The casts below are safe: section
|
|
@@ -10,4 +10,4 @@ export interface BlogListResult {
|
|
|
10
10
|
export declare function useBlogArticles(options?: {
|
|
11
11
|
endpoint?: string;
|
|
12
12
|
initialPosts?: BlogListResult["posts"];
|
|
13
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
13
|
+
}): import("@tanstack/react-query").UseQueryResult<BlogListResult, Error>;
|
|
@@ -2,4 +2,4 @@ import type { ProductItem } from "@mohasinac/appkit/features/products";
|
|
|
2
2
|
export declare function useFeaturedAuctions(options?: {
|
|
3
3
|
filterByBrand?: string;
|
|
4
4
|
initialData?: ProductItem[];
|
|
5
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
5
|
+
}): import("@tanstack/react-query").UseQueryResult<ProductItem[], Error>;
|
|
@@ -2,4 +2,4 @@ import type { ProductItem } from "@mohasinac/appkit/features/products";
|
|
|
2
2
|
export declare function useFeaturedPreOrders(options?: {
|
|
3
3
|
filterByBrand?: string;
|
|
4
4
|
initialData?: ProductItem[];
|
|
5
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
5
|
+
}): import("@tanstack/react-query").UseQueryResult<ProductItem[], Error>;
|
|
@@ -2,4 +2,4 @@ import type { ProductListResponse } from "../../products/types";
|
|
|
2
2
|
export declare function useFeaturedProducts(options?: {
|
|
3
3
|
initialData?: ProductListResponse;
|
|
4
4
|
filterByBrand?: string;
|
|
5
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
5
|
+
}): import("@tanstack/react-query").UseQueryResult<ProductListResponse, Error>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { StoreListItem } from "../../stores/types";
|
|
2
2
|
export declare function useFeaturedStores(limit?: number, options?: {
|
|
3
3
|
initialData?: StoreListItem[];
|
|
4
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
4
|
+
}): import("@tanstack/react-query").UseQueryResult<StoreListItem[], Error>;
|
|
@@ -6,4 +6,4 @@ import type { CarouselSlide } from "../types/index";
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function useHeroCarousel(options?: {
|
|
8
8
|
initialData?: CarouselSlide[];
|
|
9
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
9
|
+
}): import("@tanstack/react-query").UseQueryResult<CarouselSlide[], Error>;
|
|
@@ -5,4 +5,4 @@ export interface HomepageEventsListResponse {
|
|
|
5
5
|
}
|
|
6
6
|
export declare function useHomepageEvents(limit?: number, options?: {
|
|
7
7
|
initialData?: EventItem[];
|
|
8
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
8
|
+
}): import("@tanstack/react-query").UseQueryResult<EventItem[], Error>;
|
|
@@ -4,4 +4,4 @@ export interface UseHomepageReviewsOptions {
|
|
|
4
4
|
initialData?: Review[];
|
|
5
5
|
staleTime?: number;
|
|
6
6
|
}
|
|
7
|
-
export declare function useHomepageReviews(options?: UseHomepageReviewsOptions): import("@tanstack/react-query").UseQueryResult<
|
|
7
|
+
export declare function useHomepageReviews(options?: UseHomepageReviewsOptions): import("@tanstack/react-query").UseQueryResult<Review[], Error>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { HomepageSectionDocument } from "../schemas";
|
|
2
|
-
export declare function useHomepageSections(params?: string): import("@tanstack/react-query").UseQueryResult<
|
|
2
|
+
export declare function useHomepageSections(params?: string): import("@tanstack/react-query").UseQueryResult<HomepageSectionDocument[], Error>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CategoryItem } from "../../categories/types";
|
|
2
2
|
export declare function useTopBrands(limit?: number, options?: {
|
|
3
3
|
initialData?: CategoryItem[];
|
|
4
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
4
|
+
}): import("@tanstack/react-query").UseQueryResult<CategoryItem[], Error>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CategoryItem } from "../../categories/types";
|
|
2
2
|
export declare function useTopCategories(limit?: number, options?: {
|
|
3
3
|
initialData?: CategoryItem[];
|
|
4
|
-
}): import("@tanstack/react-query").UseQueryResult<
|
|
4
|
+
}): import("@tanstack/react-query").UseQueryResult<CategoryItem[], Error>;
|
|
@@ -1,32 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
/**
|
|
4
|
-
* BottomActions Component
|
|
5
|
-
*
|
|
6
|
-
* A fixed-bottom mobile action bar rendered **above** BottomNavbar (bottom-14).
|
|
7
|
-
* Reads from `BottomActionsContext` — features register their actions via the
|
|
8
|
-
* `useBottomActions` hook; this component just renders whatever is registered.
|
|
9
|
-
*
|
|
10
|
-
* Two modes:
|
|
11
|
-
* - **Page mode** — shows registered page-level actions inline (Add to Cart,
|
|
12
|
-
* Buy Now, Place Bid, Proceed to Checkout, etc.) with an optional info label.
|
|
13
|
-
* - **Bulk mode** — activates when `bulk.selectedCount > 0`; shows:
|
|
14
|
-
* • Selection count pill on the left (tap to deselect all)
|
|
15
|
-
* • An upward-opening type-picker dropdown (middle, flex-1) — tap to
|
|
16
|
-
* choose WHICH action to run; the chosen label is always visible.
|
|
17
|
-
* • An "Apply" submit button on the right — executes the selected action,
|
|
18
|
-
* styled with the selected action's variant (danger = red, etc.).
|
|
19
|
-
*
|
|
20
|
-
* Layout rules:
|
|
21
|
-
* - Hidden on lg+ screens (`lg:hidden`) — desktop shows inline action panels.
|
|
22
|
-
* - The bar slides up with a 300 ms ease-out transition; `pointer-events-none`
|
|
23
|
-
* while off-screen.
|
|
24
|
-
*
|
|
25
|
-
* @component
|
|
26
|
-
* @example
|
|
27
|
-
* // Automatically rendered by LayoutClient — no manual usage required.
|
|
28
|
-
* // Features use `useBottomActions` to register their actions.
|
|
29
|
-
*/
|
|
30
3
|
import { useState, useRef, useEffect } from "react";
|
|
31
4
|
import { X, ChevronUp, ChevronDown, Check } from "lucide-react";
|
|
32
5
|
import { useBottomActionsContext } from "./BottomActionsContext";
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BottomActionsContext
|
|
3
|
-
*
|
|
4
|
-
* Provides a context for registering page-level mobile action bars.
|
|
5
|
-
* Features call `useBottomActions` to push actions; the `<BottomActions>`
|
|
6
|
-
* layout component reads this context and renders the bar above BottomNavbar.
|
|
7
|
-
*
|
|
8
|
-
* Supports two modes:
|
|
9
|
-
* - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
|
|
10
|
-
* - Bulk mode: activated when `bulk.selectedCount > 0` — shows selection
|
|
11
|
-
* count + custom bulk action buttons (Delete, Archive, Export, etc.)
|
|
12
|
-
*
|
|
13
|
-
* @example — product detail page
|
|
14
|
-
* ```tsx
|
|
15
|
-
* useBottomActions({
|
|
16
|
-
* actions: [
|
|
17
|
-
* { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
|
|
18
|
-
* { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
|
|
19
|
-
* { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
|
|
20
|
-
* ],
|
|
21
|
-
* });
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* @example — admin listing with bulk select
|
|
25
|
-
* ```tsx
|
|
26
|
-
* useBottomActions({
|
|
27
|
-
* bulk: {
|
|
28
|
-
* selectedCount: selectedIds.length,
|
|
29
|
-
* onClearSelection: () => setSelectedIds([]),
|
|
30
|
-
* actions: [
|
|
31
|
-
* { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
|
|
32
|
-
* ],
|
|
33
|
-
* },
|
|
34
|
-
* });
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
1
|
import React from "react";
|
|
38
2
|
import type { ButtonProps } from "../../ui";
|
|
39
3
|
export interface BottomAction {
|